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
#- 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
- - implicit_return
+ - 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:
typedef NSString* LKAnalyticsMetric NS_STRING_ENUM;
extern LKAnalyticsFailableEvent const LKAEventUpgrade;
+extern LKAnalyticsFailableEvent const LKAEventStash;
+extern LKAnalyticsFailableEvent const LKAEventStashLoad;
@interface LocalKeychainAnalytics : SFAnalytics
LKAnalyticsFailableEvent const LKAEventBackup = (LKAnalyticsFailableEvent)@"LKAEventBackup";
LKAnalyticsMetric const LKAMetricBackupDuration = (LKAnalyticsMetric)@"LKAMetricBackupDuration";
+// <rdar://problem/60767235> 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";
#define SOSAnalytics_h
#import <Foundation/Foundation.h>
-#import "Analytics/SFAnalytics.h"
+#import <Security/SFAnalytics.h>
extern NSString* const CKDKVSPerformanceCountersSampler;
#define SFAnalytics_h
#import <Foundation/Foundation.h>
-#import "SFAnalyticsSampler.h"
-#import "SFAnalyticsMultiSampler.h"
-#import "SFAnalyticsActivityTracker.h"
+#import <Security/SFAnalyticsSampler.h>
+#import <Security/SFAnalyticsMultiSampler.h>
+#import <Security/SFAnalyticsActivityTracker.h>
NS_ASSUME_NONNULL_BEGIN
// 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
#if TARGET_OS_OSX
#include <sys/sysctl.h>
+#include <membership.h>
#else
#import <sys/utsname.h>
#endif
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"
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
+ mode_t permissions = 0775;
+#else
+ mode_t permissions = 0700;
+ if (geteuid() == 0) {
+ // Root user directory needs to be read/write for group so that user supd can upload root 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
<key>splunk_bagURL</key>
<string>https://metrics-config.icloud.com/config/TransparencyAnalytics</string>
</dict>
+ <key>NetworkingTopic</key>
+ <dict>
+ <key>uploadSizeLimit</key>
+ <real>1000000</real>
+ <key>splunk_allowInsecureCertificate</key>
+ <false/>
+ <key>splunk_topic</key>
+ <string>xp_sear_trust</string>
+ <key>splunk_bagURL</key>
+ <string>https://xp.apple.com/config/1/report/xp_sear_trust</string>
+ <key>disableClientId</key>
+ <true/>
+ </dict>
</dict>
</plist>
extern NSString* const SFAnalyticsTopicKeySync;
extern NSString* const SFAnalyticsTopicTrust;
extern NSString* const SFAnalyticsTopicTransparency;
+extern NSString* const SFAnalyticsTopicNetworking;
typedef NS_ENUM(NSInteger, SFAnalyticsEventClass) {
SFAnalyticsEventClassSuccess,
#if __OBJC2__
-#import "Analytics/SQLite/SFSQLite.h"
-#import "SFAnalytics.h"
+#import <Security/SFSQLite.h>
+#import <Security/SFAnalytics.h>
@interface SFAnalyticsSQLiteStore : SFSQLite
#include <sqlite3.h>
#include <CommonCrypto/CommonDigest.h>
#import "utilities/debugging.h"
+#import "utilities/simulatecrash_assert.h"
#include <os/transaction_private.h>
#define kSFSQLiteBusyTimeout (5*60*1000)
- (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];
* 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
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;
* 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
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().
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
/*
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
/*
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
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
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
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.
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
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
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
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
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
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
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
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
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;
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.
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().
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
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().
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
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
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
/*
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
/*
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().
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
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().
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
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.
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
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.
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.
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
/*
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
/*
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
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
@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
/*!
#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
/*!
*/
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
*/
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
/*!
*/
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
*/
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
/*!
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
/*!
*/
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
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
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
/*!
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
/*!
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
#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
/*!
*/
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
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
#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
/*!
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
/*!
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
/*!
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
/*!
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
*/
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
*/
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
#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
/*!
*/
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
/*!
*/
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
*/
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
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
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
#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
/*!
*/
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
/*!
*/
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
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
#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
#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
*/
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
/*!
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
*/
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
*/
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
#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
-(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;
}
#import <CloudServices/SecureBackup.h>
#import <CoreFoundation/CFUserNotification.h>
#import <Foundation/Foundation.h>
-#import <ManagedConfiguration/MCProfileConnection.h>
-#import <ManagedConfiguration/MCFeatures.h>
+#import <ManagedConfiguration/ManagedConfiguration.h>
#import <MobileCoreServices/MobileCoreServices.h>
#import <MobileCoreServices/LSApplicationWorkspace.h>
#import <MobileGestalt.h>
}
- (instancetype)init {
- self = [super init];
-
- if (self) {
+ if ((self = [super init])) {
XPCNotificationDispatcher* dispatcher = [XPCNotificationDispatcher dispatcher];
_queue = dispatch_queue_create("CKDAKSLockMonitor", NULL);
}
- (void) _onqueueRecheck {
+ dispatch_assert_queue(_queue);
CFErrorRef aksError = NULL;
bool locked = true; // Assume locked if we get an error
#include "keychain/SecureObjectSync/SOSARCDefines.h"
#include "keychain/SecureObjectSync/SOSKVSKeys.h"
#include <utilities/SecCFWrappers.h>
-#include <utilities/SecPLWrappers.h>
#include "SOSCloudKeychainConstants.h"
#include <utilities/SecAKSWrappers.h>
-#include <utilities/SecADWrapper.h>
#include <utilities/SecNSAdditions.h>
#import "XPCNotificationDispatcher.h"
}
- (void)synchronizeStore {
- [self.store pushWrites];
+ [self.store pushWrites:[NSArray array] requiresForceSync:YES];
}
- (id) objectForKey: (NSString*) key {
[[self store] addOneToOutGoing];
[self.store setObject:obj forKey:key];
}
- }];
-
- [self.store pushWrites];
+ }];
+
+ [self.store pushWrites:[mutableValues allKeys] requiresForceSync:NO];
}
- (void)setObjectsFromDictionary:(NSDictionary<NSString*, NSObject*> *)values
- (NSDictionary<NSString *, id>*) copyAsDictionary;
-- (void)pushWrites;
+- (void)pushWrites:(NSArray<NSString*>*)keys requiresForceSync:(BOOL)requiresForceSync;
- (BOOL)pullUpdates:(NSError**) failure;
- (void)kvsStoreChanged: (NSNotification*) notification;
#import "Analytics/Clients/SOSAnalytics.h"
+#include "keychain/SecureObjectSync/SOSKVSKeys.h"
+#include <Security/OTConstants.h>
+
struct CKDKVSCounters {
uint64_t synchronize;
uint64_t synchronizeWithCompletionHandler;
uint64_t synchronizeFailures;
};
-
-
@interface CKDKVSStore ()
@property (readwrite, weak) UbiqitousKVSProxy* proxy;
@property (readwrite) NSUbiquitousKeyValueStore* cloudStore;
}
- (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;
}
}];
}
-- (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<NSString*>*)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
self.perfCounters->synchronize++;
});
secnotice("fresh", "%s RETURNING FROM syncdefaultsd SWCH: %@", kWAIT2MINID, self);
- [[self cloudStore] synchronize]; // Per olivier in <rdar://problem/13412631>, sync before getting values
- secnotice("fresh", "%s RETURNING FROM syncdefaultsd SYNC: %@", kWAIT2MINID, self);
+ if(SecKVSOnCloudKitIsEnabled() == NO) {
+ [[self cloudStore] synchronize]; // Per olivier in <rdar://problem/13412631>, sync before getting values
+ secnotice("fresh", "%s RETURNING FROM syncdefaultsd SYNC: %@", kWAIT2MINID, self);
+ }
}
dispatch_semaphore_signal(freshSemaphore);
}];
- (NSDictionary<NSString *, id>*) copyAsDictionary;
-- (void)pushWrites;
+- (void)pushWrites:(NSArray<NSString*>*)keys requiresForceSync:(BOOL)requiresForceSync;
- (BOOL)pullUpdates:(NSError**) failure;
- (void)perfCounters:(void(^)(NSDictionary *counters))callback;
}
- (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;
#import "CKDSecuritydAccount.h"
#import "CKDKVSStore.h"
#import "CKDAKSLockMonitor.h"
+#import "SOSCloudKeychainConstants.h"
+#include <utilities/simulatecrash_assert.h>
-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);
+#define PROXYXPCSCOPE "xpcproxy"
-int ckdproxymain(int argc, const char *argv[]);
+@interface CloudKeychainProxy : NSObject
+-(id _Nullable) init;
-#define PROXYXPCSCOPE "xpcproxy"
+@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;
-static void describeXPCObject(char *prefix, xpc_object_t object)
+@end
+
+static void cloudkeychainproxy_event_handler(xpc_connection_t peer)
{
-//#ifndef NDEBUG
- // This is useful for debugging.
- if (object)
+ 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 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);
- secdebug(PROXYXPCSCOPE, "%s%s\n", prefix, desc);
+ secinfo(PROXYXPCSCOPE, "%s%s", prefix, desc);
free(desc);
+ } else {
+ secinfo(PROXYXPCSCOPE, "%s<NULL>", prefix);
}
- else
- secdebug(PROXYXPCSCOPE, "%s<NULL>\n", prefix);
-
-//#endif
}
-static NSObject *CreateNSObjectForCFXPCObjectFromKey(xpc_object_t xdict, const char * _Nonnull key)
-{
+- (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<NSString*> *CreateArrayOfStringsForCFXPCObjectFromKey(xpc_object_t xdict, const char * _Nonnull key) {
- NSObject * possibleArray = CreateNSObjectForCFXPCObjectFromKey(xdict, key);
+- (NSArray<NSString*> *) 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__]) {
return onlyStrings ? (NSArray<NSString*>*) 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 (!strcmp(operation, kOperationPUTDictionary))
+ {
+ [self operation_put_dictionary: event];
+ [self sendAckResponse: peer forEvent: event];
+ }
+ else if (!strcmp(operation, kOperationGETv2))
+ {
+ [self operation_get_v2: peer forEvent: event];
+ // operationg_get_v2 sends the response
+ }
+ 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);
+ secnotice(XPROXYSCOPE, "%s XPC request: %s", kWAIT2MINID, kOperationSynchronizeAndWait);
+
+ [_proxyID waitForSynchronization:^(__unused NSDictionary *values, NSError *error)
{
- if (error)
+ secnotice(PROXYXPCSCOPE, "%s Result from [Proxy waitForSynchronization:]: %@", kWAIT2MINID, error);
+
+ if (replyMessage) // Caller wanted an ACK, so give one
{
- xpc_object_t xerrobj = SecCreateXPCObjectWithCFError((__bridge CFErrorRef)(error));
- xpc_dictionary_set_value(replyMessage, kMessageKeyError, xerrobj);
- } else {
- xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK");
+ 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);
}
- xpc_connection_send_message(peer, replyMessage);
- }
- }];
- }
- else if (!strcmp(operation, kOperationRegisterKeys))
- {
- xpc_object_t xkeysToRegisterDict = xpc_dictionary_get_value(event, kMessageKeyValue);
+ }];
+ }
+ 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);
+ xpc_object_t xKTRallkeys = xpc_dictionary_get_value(xkeysToRegisterDict, kMessageAllKeys);
- NSString* accountUUID = (NSString*) CreateNSObjectForCFXPCObjectFromKey(event, kMessageKeyAccountUUID);
+ NSString* accountUUID = (NSString*) [self CreateNSObjectForCFXPCObjectFromKey:event withKey: kMessageKeyAccountUUID];
- if (![accountUUID isKindOfClass:[NSString class]]) {
- accountUUID = nil;
- }
+ if (![accountUUID isKindOfClass:[NSString class]]) {
+ accountUUID = nil;
+ }
- NSDictionary *KTRallkeys = (__bridge_transfer NSDictionary *)(_CFXPCCreateCFObjectFromXPCObject(xKTRallkeys));
+ NSDictionary *KTRallkeys = (__bridge_transfer NSDictionary *)(_CFXPCCreateCFObjectFromXPCObject(xKTRallkeys));
- [SharedProxy() registerKeys: KTRallkeys forAccount: accountUUID];
- sendAckResponse(peer, event);
+ [_proxyID registerKeys: KTRallkeys forAccount: accountUUID];
+ [self sendAckResponse: peer forEvent: 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;
+ secinfo(PROXYXPCSCOPE, "RegisterKeys message sent");
}
-
- 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))
- {
+ 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<NSString*> * peerIDs = CreateArrayOfStringsForCFXPCObjectFromKey(event, kMessageKeyPeerIDList);
- NSArray<NSString*> * backupPeerIDs = CreateArrayOfStringsForCFXPCObjectFromKey(event, kMesssgeKeyBackupPeerIDList);
+ NSArray<NSString*> * peerIDs = [self CreateArrayOfStringsForCFXPCObjectFromKey: event withKey: kMessageKeyPeerIDList];
+ NSArray<NSString*> * backupPeerIDs = [self CreateArrayOfStringsForCFXPCObjectFromKey: event withKey: kMesssgeKeyBackupPeerIDList];
- require_action(peerIDs && backupPeerIDs, xit, (secnotice(XPROXYSCOPE, "Bad call to sync with peers"), result = false));
+ require_action(peerIDs && backupPeerIDs, xit, (secnotice(XPROXYSCOPE, "Bad call to sync with peers"), result = false));
- [SharedProxy() requestSyncWithPeerIDs: peerIDs backupPeerIDs: backupPeerIDs];
- sendAckResponse(peer, event);
+ [_proxyID requestSyncWithPeerIDs: peerIDs backupPeerIDs: backupPeerIDs];
+ [self sendAckResponse: peer forEvent: event];
- secdebug(PROXYXPCSCOPE, "RequestSyncWithAllPeers reply sent");
- }
- else if (!strcmp(operation, kOperationHasPendingSyncWithPeer)) {
- NSString *peerID = (NSString*) CreateNSObjectForCFXPCObjectFromKey(event, kMessageKeyPeerID);
+ secinfo(PROXYXPCSCOPE, "RequestSyncWithAllPeers reply sent");
+ }
+ else if (!strcmp(operation, kOperationHasPendingSyncWithPeer)) {
+ NSString *peerID = (NSString*) [self CreateNSObjectForCFXPCObjectFromKey: event withKey: kMessageKeyPeerID];
- BOOL hasPending = [SharedProxy() hasSyncPendingFor: peerID];
+ 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);
- secdebug(PROXYXPCSCOPE, "HasPendingSyncWithPeer reply sent");
+ 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*) CreateNSObjectForCFXPCObjectFromKey(event, kMessageKeyPeerID);
+ else if (!strcmp(operation, kOperationHasPendingKey)) {
+ NSString *peerID = (NSString*) [self CreateNSObjectForCFXPCObjectFromKey: event withKey: kMessageKeyPeerID];
- BOOL hasPending = [SharedProxy() hasPendingKey: peerID];
+ BOOL hasPending = [_proxyID hasPendingKey: peerID];
- xpc_object_t replyMessage = xpc_dictionary_create_reply(event);
- if (replyMessage)
+ 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))
{
- xpc_dictionary_set_bool(replyMessage, kMessageKeyValue, hasPending);
- xpc_connection_send_message(peer, replyMessage);
- secdebug(PROXYXPCSCOPE, "HasIncomingMessageFromPeer reply sent");
+ [_proxyID requestEnsurePeerRegistration];
+ [self sendAckResponse: peer forEvent: event];
+ secinfo(PROXYXPCSCOPE, "RequestEnsurePeerRegistration reply sent");
}
- }
- 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){
- 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;
+ 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);
-}
-
-void finalize_connection(void *not_used)
-{
- secdebug(PROXYXPCSCOPE, "finalize_connection");
- [SharedProxy() synchronizeStore];
- xpc_transaction_end();
+ if (!result) {
+ [self describeXPCObject: "handle_operation fail: " withObject: event];
+ }
+ }
}
-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) {
NSObject* object = (__bridge_transfer NSObject*) _CFXPCCreateCFObjectFromXPCObject(xvalue);
if (![object isKindOfClass:[NSDictionary<NSString*, NSObject*> 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<NSString*, NSObject*> *)object];
+ [_proxyID setObjectsFromDictionary: (NSDictionary<NSString*, NSObject*> *)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;
}
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;
}
[(__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();
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;
- }
- 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);
-}
+@end
-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);
}
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);
-}
freeWhenDone: false];
});
- 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;
-
- _pairingUUID = pairingUUID;
- _piggybackingVersion = piggybackingVersion;
- _epoch = epoch;
-
- if (self.send == nil || self.receive == nil) {
- return nil;
+ 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;
+
+ _pairingUUID = pairingUUID;
+ _piggybackingVersion = piggybackingVersion;
+ _epoch = epoch;
+
+ 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;
}
kUnexpectedMessage,
kInternalError,
kDERUnknownVersion,
+ kProcessApplicationFailure,
+ kUnsupportedTrustPlatform,
} KCJoiningError;
@interface NSError(KCJoiningError)
#include <corecrypto/ccsha2.h>
#include <corecrypto/ccdh_gp.h>
#include <utilities/debugging.h>
-#include <CommonCrypto/CommonRandomSPI.h>
#include <notify.h>
#if OCTAGON
#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
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"
- pairingUUID:[[NSUUID UUID] UUIDString]
- 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;
}
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);
- (NSData*) createTLKRequestResponse: (NSError**) error {
NSError* localError = NULL;
- NSData* initialSync = [self.circleDelegate circleGetInitialSyncViews:kSOSInitialSyncFlagTLKs error:&localError];
+ 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: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) {
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);
}
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
+ (nullable instancetype) messageWithType: (KCJoiningMessageType) type
data: (NSData*) firstData
- payload: (NSData*) secondData
+ payload: (nullable NSData*) secondData
error: (NSError**) error;
+ (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];
- (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;
}
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;
}
#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 <KeychainCircle/NSError+KCCreationHelpers.h>
return [self->_session encrypt:initialMessage.data error:error];
}
+
- (nullable NSData*) initialMessage: (NSError**) error {
secnotice("joining", "joining: KCJoiningRequestCircleSession initialMessage called");
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;
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);
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];
}
-- (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 {
secerror("octagon: expected voucher! returning from piggybacking.");
return nil;
}
+
OTSponsorToApplicantRound2M2 *voucher = pairingMessage.voucher;
//handle voucher message then join octagon
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;
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;
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->_piggy_version = session.piggybackingVersion;
+ 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;
#else
- self->_piggy_version = kPiggyV1;
+ self->_piggy_version = kPiggyV1;
#endif
-
+ }
return self;
}
#include <corecrypto/ccsha2.h>
#include <corecrypto/ccdh_gp.h>
#include <corecrypto/ccder.h>
-#include <CommonCrypto/CommonRandomSPI.h>
#import <Security/SecureObjectSync/SOSTypes.h>
#include <utilities/debugging.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"
#endif
#import <KeychainCircle/NSError+KCCreationHelpers.h>
@property (readwrite) uint64_t epoch;
@property (readwrite) NSData* challenge;
@property (readwrite) NSData* salt;
-#if OCTAGON
@property (readwrite) NSString* sessionUUID;
+#if OCTAGON
@property (nonatomic, strong) OTControl *otControl;
#endif
@property (nonatomic, strong) NSMutableDictionary *defaults;
}
#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.hasEpoch) {
+ if (pairingMessage.hasEpoch) {
secnotice("octagon", "received epoch message: %@", [pairingMessage.epoch dictionaryRepresentation]);
self.epoch = pairingMessage.epoch.epoch;
}
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->_piggy_version = KCJoiningOctagonPiggybackingEnabled() ? kPiggyV2 : kPiggyV1;
+ self->_otControl = [OTControl controlObject:true error:error];
- _sessionUUID = [[NSUUID UUID] UUIDString];
+ _sessionUUID = [[NSUUID UUID] UUIDString];
#else
- self->_piggy_version = kPiggyV1;
+ self->_piggy_version = kPiggyV1;
#endif
- secnotice("joining", "joining: initWithSecretDelegate called, uuid=%@", self.sessionUUID);
+ 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;
}
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;
}
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;
}
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;
}
#import <Security/SecureObjectSync/SOSTypes.h>
#import <utilities/debugging.h>
#import <utilities/SecCFWrappers.h>
+#import "utilities/SecCoreAnalytics.h"
#import <ipc/securityd_client.h>
#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/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 <notify.h>
#import <MobileGestalt.h>
#endif
-#import "utilities/SecADWrapper.h"
KCPairingIntent_Type KCPairingIntent_Type_None = @"none";
KCPairingIntent_Type KCPairingIntent_Type_SilentRepair = @"repair";
- (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"];
//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);
}
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");
} 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: %@",
[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);
}
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
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]);
}
}
@implementation FakeNSXPCConnection
- (instancetype) initWithControl:(id<SOSControlProtocol>)control
{
- self = [super init];
- if (self) {
+ if ((self = [super init])) {
_control = control;
}
return self;
complete(true, nil);
}
-- (void)triggerSync:(NSArray<NSString *> *)peers complete:(void(^)(bool success, NSError *))complete
+- (void)rpcTriggerSync:(NSArray<NSString *> *)peers complete:(void(^)(bool success, NSError *))complete
{
complete(true, NULL);
}
complete(nil, nil);
}
-- (void)triggerBackup:(NSArray<NSString *> *)backupPeers complete:(void (^)(NSError *))complete {
+- (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<NSString *> *)backupPeers complete:(void (^)(NSError *))complete {
+ complete(nil);
+}
+
+- (void)rpcTriggerRingUpdate:(void (^)(NSError *))complete {
complete(nil);
}
#include "keychain/SecureObjectSync/SOSFullPeerInfo.h"
#include "keychain/SecureObjectSync/SOSPeerInfoInternal.h"
-#include <CommonCrypto/CommonRandomSPI.h>
-
static SecKeyRef GenerateFullECKey_internal(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;
+ if (newPeerInfo == NULL) {
+ return nil;
+ }
+ self.peerInfo = newPeerInfo;
+ CFRelease(newPeerInfo);
+ newPeerInfo = NULL;
- self.sharedSecret = secret;
- self.incorrectSecret = incorrectSecret;
- self.incorrectTries = retries;
+ self.sharedSecret = secret;
+ self.incorrectSecret = incorrectSecret;
+ self.incorrectTries = retries;
+ }
return self;
}
}
- (id) initWithSecrets: (NSArray<NSString*>*) 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;
}
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];
KCJoiningAcceptSession* acceptSession = [[KCJoiningAcceptSession alloc] initWithSecretDelegate:acceptDelegate
circleDelegate:acceptDelegate
dsid:dsid
- rng:ccDRBGGetRngState()
+ rng:ccrng(NULL)
error:&error];
error = nil;
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];
KCJoiningAcceptSession* acceptSession = [[KCJoiningAcceptSession alloc] initWithSecretDelegate:acceptDelegate
circleDelegate:acceptDelegate
dsid:dsid
- rng:ccDRBGGetRngState()
+ rng:ccrng(NULL)
error:&error];
error = nil;
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];
KCJoiningAcceptSession* acceptSession = [[KCJoiningAcceptSession alloc] initWithSecretDelegate:acceptDelegate
circleDelegate:acceptDelegate
dsid:dsid
- rng:ccDRBGGetRngState()
+ rng:ccrng(NULL)
error:&error];
error = nil;
<false/>
<key>Command</key>
<array>
- <string>BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testSecPairBasicTest KCPairing.xctest</string>
+ <string>BATS_XCTEST_CMD</string>
+ <string>-NSTreatUnknownArgumentsAsOpen</string>
+ <string>NO</string>
+ <string>-ApplePersistenceIgnoreState</string>
+ <string>YES</string>
+ <string>-XCTest</string>
+ <string>testSecPairBasicTest</string>
+ <string>KCPairing.xctest</string>
</array>
</dict>
</array>
#include <corecrypto/ccrng.h>
#include <corecrypto/ccsha2.h>
#include <corecrypto/ccdh_gp.h>
-#include <CommonCrypto/CommonRandomSPI.h>
@interface KCSRPTests : XCTestCase
[self negotiateWithUser: @"TestUser"
digestInfo: ccsha256_di()
group: ccsrp_gp_rfc5054_3072()
- randomSource: ccDRBGGetRngState()];
+ randomSource: ccrng(NULL)];
}
@end
#include <CommonCrypto/CommonRandomSPI.h>
-
-static SecKeyRef GenerateFullECKey_internal(int keySize, NSError** error)
-{
- SecKeyRef full_key = NULL;
-
- NSDictionary* keygen_parameters = @{ (__bridge NSString*)kSecAttrKeyType:(__bridge NSString*) kSecAttrKeyTypeEC,
- (__bridge NSString*)kSecAttrKeySizeInBits: [NSNumber numberWithInt: keySize] };
-
-
- (void) OSStatusError(SecKeyGeneratePair((__bridge CFDictionaryRef)keygen_parameters, NULL, &full_key), error, @"Generate Key failed");
-
- return full_key;
-}
-
-static SecKeyRef GenerateFullECKey(int keySize, NSError** error) {
- return GenerateFullECKey_internal(keySize, error);
-}
-
static NSData* createTlkRequestMessage (KCAESGCMDuplexSession* aesSession) {
char someData[] = {1,2,3,4,5,6};
NSError* error = NULL;
}
- (id) initWithSecrets: (NSArray<NSString*>*) secrets retries: (int) retries code: (NSString*) code {
- self = [super init];
-
- self->_secrets = secrets;
- self.currentSecret = 0;
- self->_retriesPerSecret = retries;
- self->_retriesLeft = self.retriesPerSecret;
+ 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) ];
+ 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;
}
<false/>
<key>Command</key>
<array>
- <string>BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest KCDerTest KeychainCircleTests.xctest</string>
+ <string>BATS_XCTEST_CMD</string>
+ <string>-NSTreatUnknownArgumentsAsOpen</string>
+ <string>NO</string>
+ <string>-ApplePersistenceIgnoreState</string>
+ <string>YES</string>
+ <string>-XCTest</string>
+ <string>KCDerTest</string>
+ <string>KeychainCircleTests.xctest</string>
</array>
</dict>
<dict>
<false/>
<key>Command</key>
<array>
- <string>BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testAESGCMDuplex KeychainCircleTests.xctest</string>
+ <string>BATS_XCTEST_CMD</string>
+ <string>-NSTreatUnknownArgumentsAsOpen</string>
+ <string>NO</string>
+ <string>-ApplePersistenceIgnoreState</string>
+ <string>YES</string>
+ <string>-XCTest</string>
+ <string>testAESGCMDuplex</string>
+ <string>KeychainCircleTests.xctest</string>
</array>
</dict>
<dict>
<false/>
<key>Command</key>
<array>
- <string>BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testAESGCMDuplexCoding KeychainCircleTests.xctest</string>
+ <string>BATS_XCTEST_CMD</string>
+ <string>-NSTreatUnknownArgumentsAsOpen</string>
+ <string>NO</string>
+ <string>-ApplePersistenceIgnoreState</string>
+ <string>YES</string>
+ <string>-XCTest</string>
+ <string>testAESGCMDuplexCoding</string>
+ <string>KeychainCircleTests.xctest</string>
</array>
</dict>
<dict>
<false/>
<key>Command</key>
<array>
- <string>BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testJoiningSession KeychainCircleTests.xctest</string>
+ <string>BATS_XCTEST_CMD</string>
+ <string>-NSTreatUnknownArgumentsAsOpen</string>
+ <string>NO</string>
+ <string>-ApplePersistenceIgnoreState</string>
+ <string>YES</string>
+ <string>-XCTest</string>
+ <string>testJoiningSession</string>
+ <string>KeychainCircleTests.xctest</string>
</array>
</dict>
<dict>
<false/>
<key>Command</key>
<array>
- <string>BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testJoiningSessionRetry KeychainCircleTests.xctest</string>
+ <string>BATS_XCTEST_CMD</string>
+ <string>-NSTreatUnknownArgumentsAsOpen</string>
+ <string>NO</string>
+ <string>-ApplePersistenceIgnoreState</string>
+ <string>YES</string>
+ <string>-XCTest</string>
+ <string>testJoiningSessionRetry</string>
+ <string>KeychainCircleTests.xctest</string>
</array>
</dict>
<dict>
<false/>
<key>Command</key>
<array>
- <string>BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testJoiningSessionCodeChange KeychainCircleTests.xctest</string>
+ <string>BATS_XCTEST_CMD</string>
+ <string>-NSTreatUnknownArgumentsAsOpen</string>
+ <string> NO</string>
+ <string>-ApplePersistenceIgnoreState</string>
+ <string>YES </string>
+ <string>-XCTest</string>
+ <string>testJoiningSessionCodeChange</string>
+ <string>KeychainCircleTests.xctest</string>
</array>
</dict>
</array>
+++ /dev/null
-//
-// AppDelegate.h
-// KeychainEntitledTestApp_ios
-//
-// Copyright (c) 2017 Apple Inc. All rights reserved.
-//
-//
-
-#import <UIKit/UIKit.h>
-
-@interface AppDelegate : UIResponder <UIApplicationDelegate>
-
-@property (strong, nonatomic) UIWindow *window;
-
-
-@end
-
+++ /dev/null
-//
-// 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
+++ /dev/null
-{
- "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
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>CFBundleDevelopmentRegion</key>
- <string>en</string>
- <key>CFBundleExecutable</key>
- <string>$(EXECUTABLE_NAME)</string>
- <key>CFBundleIdentifier</key>
- <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
- <key>CFBundleInfoDictionaryVersion</key>
- <string>6.0</string>
- <key>CFBundleName</key>
- <string>$(PRODUCT_NAME)</string>
- <key>CFBundlePackageType</key>
- <string>APPL</string>
- <key>CFBundleShortVersionString</key>
- <string>1.0</string>
- <key>CFBundleVersion</key>
- <string>1</string>
- <key>LSRequiresIPhoneOS</key>
- <true/>
- <key>UILaunchStoryboardName</key>
- <string>LaunchScreen</string>
- <key>UIMainStoryboardFile</key>
- <string>Main</string>
- <key>UIRequiredDeviceCapabilities</key>
- <array>
- <string>armv7</string>
- </array>
- <key>UISupportedInterfaceOrientations</key>
- <array>
- <string>UIInterfaceOrientationPortrait</string>
- <string>UIInterfaceOrientationLandscapeLeft</string>
- <string>UIInterfaceOrientationLandscapeRight</string>
- </array>
- <key>UISupportedInterfaceOrientations~ipad</key>
- <array>
- <string>UIInterfaceOrientationPortrait</string>
- <string>UIInterfaceOrientationPortraitUpsideDown</string>
- <string>UIInterfaceOrientationLandscapeLeft</string>
- <string>UIInterfaceOrientationLandscapeRight</string>
- </array>
-</dict>
-</plist>
+++ /dev/null
-//
-// ViewController.h
-// KeychainEntitledTestApp_ios
-//
-// Copyright (c) 2017 Apple Inc. All rights reserved.
-//
-//
-
-#import <UIKit/UIKit.h>
-
-@interface ViewController : UIViewController
-
-
-@end
-
+++ /dev/null
-//
-// 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
+++ /dev/null
-//
-// main.m
-// KeychainEntitledTestApp_ios
-//
-// Copyright (c) 2017 Apple Inc. All rights reserved.
-//
-//
-
-#import <UIKit/UIKit.h>
-#import "AppDelegate.h"
-
-int main(int argc, char * argv[]) {
- @autoreleasepool {
- return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
- }
-}
+++ /dev/null
-//
-// AppDelegate.h
-// KeychainEntitledTestApp_mac
-//
-// Copyright (c) 2017 Apple Inc. All rights reserved.
-//
-//
-
-#import <Cocoa/Cocoa.h>
-
-@interface AppDelegate : NSObject <NSApplicationDelegate>
-
-
-@end
-
+++ /dev/null
-//
-// 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
+++ /dev/null
-{
- "images" : [
- {
- "idiom" : "mac",
- "size" : "16x16",
- "scale" : "1x"
- },
- {
- "idiom" : "mac",
- "size" : "16x16",
- "scale" : "2x"
- },
- {
- "idiom" : "mac",
- "size" : "32x32",
- "scale" : "1x"
- },
- {
- "idiom" : "mac",
- "size" : "32x32",
- "scale" : "2x"
- },
- {
- "idiom" : "mac",
- "size" : "128x128",
- "scale" : "1x"
- },
- {
- "idiom" : "mac",
- "size" : "128x128",
- "scale" : "2x"
- },
- {
- "idiom" : "mac",
- "size" : "256x256",
- "scale" : "1x"
- },
- {
- "idiom" : "mac",
- "size" : "256x256",
- "scale" : "2x"
- },
- {
- "idiom" : "mac",
- "size" : "512x512",
- "scale" : "1x"
- },
- {
- "idiom" : "mac",
- "size" : "512x512",
- "scale" : "2x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-}
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>CFBundleDevelopmentRegion</key>
- <string>en</string>
- <key>CFBundleExecutable</key>
- <string>$(EXECUTABLE_NAME)</string>
- <key>CFBundleIconFile</key>
- <string></string>
- <key>CFBundleIdentifier</key>
- <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
- <key>CFBundleInfoDictionaryVersion</key>
- <string>6.0</string>
- <key>CFBundleName</key>
- <string>$(PRODUCT_NAME)</string>
- <key>CFBundlePackageType</key>
- <string>APPL</string>
- <key>CFBundleShortVersionString</key>
- <string>1.0</string>
- <key>CFBundleVersion</key>
- <string>1</string>
- <key>LSMinimumSystemVersion</key>
- <string>$(MACOSX_DEPLOYMENT_TARGET)</string>
- <key>NSPrincipalClass</key>
- <string>NSApplication</string>
-</dict>
-</plist>
+++ /dev/null
-//
-// ViewController.h
-// KeychainEntitledTestApp_mac
-//
-// Copyright (c) 2017 Apple Inc. All rights reserved.
-//
-//
-
-#import <Cocoa/Cocoa.h>
-
-@interface ViewController : NSViewController
-
-
-@end
-
+++ /dev/null
-//
-// ViewController.m
-// KeychainEntitledTestApp_mac
-//
-// Copyright (c) 2017 Apple Inc. All rights reserved.
-//
-//
-
-#import "ViewController.h"
-
-@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
+++ /dev/null
-//
-// main.m
-// KeychainEntitledTestApp_mac
-//
-// Copyright (c) 2017 Apple Inc. All rights reserved.
-//
-//
-
-#import <Cocoa/Cocoa.h>
-
-int main(int argc, const char * argv[]) {
- return NSApplicationMain(argc, argv);
-}
// was asked to file this radar for accounts: <rdar://problem/40176124> 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];
--- /dev/null
+framework module OctagonTrust [system] {
+ umbrella header "OctagonTrust.h"
+
+ export *
+ module * { export * }
+}
-framework module Security [extern_c] {
+framework module Security [extern_c][system] {
umbrella header "Security.h"
export *
-framework module Security [extern_c] {
+framework module Security [extern_c][system] {
umbrella header "Security.h"
export *
-module Security.SecTask [extern_c] {
+module Security.SecTask [extern_c][system] {
header "SecTask.h"
export *
}
+++ /dev/null
-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.
+++ /dev/null
-/*
- * 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 <Security/Security.h>
-#include <Security/SecBreadcrumb.h>
-#include <Security/SecRandom.h>
-
-#include <corecrypto/ccaes.h>
-#include <corecrypto/ccpbkdf2.h>
-#include <corecrypto/ccmode.h>
-#include <corecrypto/ccmode_factory.h>
-#include <corecrypto/ccsha2.h>
-
-#include <CommonCrypto/CommonRandomSPI.h>
-
-#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;
-}
+++ /dev/null
-/*
- * 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);
+++ /dev/null
-/*
- * 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 <Foundation/Foundation.h>
-#include <Security/Security.h>
-#include <Security/SecBreadcrumb.h>
-#include <utilities/SecCFRelease.h>
-
-#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;
-}
+++ /dev/null
-/* 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 <regressions/test/testmore.h>
-
-ONE_TEST(bc_10_password)
.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.
-(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
-(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;
}
+++ /dev/null
-./Modules
\ No newline at end of file
<string>123456.test.group2</string>
<string>com.apple.bluetooth</string>
</array>
+ <key>com.apple.private.AuthorizationServices</key>
+ <array>
+ <string>com.apple.trust-settings.admin</string>
+ </array>
+ <key>com.apple.private.security.storage.Keychains</key>
+ <true/>
</dict>
</plist>
/* Don't prevent multiple inclusion of this file. */
#include <libsecurity_ssl/regressions/ssl_regressions.h>
#include <libsecurity_keychain/regressions/keychain_regressions.h>
-#include <Breadcrumb/breadcrumb_regressions.h>
#include <libsecurity_cms/regressions/cms_regressions.h>
#include <libsecurity_transform/regressions/transform_regressions.h>
#include <shared_regressions/shared_regressions.h>
--- /dev/null
+//
+// PreloginUserDb.h
+// authd
+//
+
+OSStatus preloginudb_copy_userdb(const char * _Nullable uuid, UInt32 flags, CFArrayRef _Nonnull * _Nonnull output);
--- /dev/null
+//
+// PreloginUserDb.m
+// authd
+//
+// Copyright © 2019 Apple. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <libgen.h>
+#import <APFS/APFS.h>
+#import <DiskManagement/DiskManagement.h>
+#import "PreloginUserDb.h"
+#import <LocalAuthentication/LAContext+Private.h>
+#import <SoftLinking/SoftLinking.h>
+#import "debugging.h"
+#import <Security/Authorization.h>
+#import <Security/AuthorizationTagsPriv.h>
+#import <libaks_filevault.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";
+
+
+@interface PreloginUserDb : NSObject
+
+- (instancetype)init;
+
+- (BOOL) loadWithError:(NSError **)error;
+
+- (NSArray<NSDictionary *> *) users;
+- (NSArray<NSDictionary *> *) users:(NSString *)volumeUuid;
+
+@end
+
+typedef void (^AIRDBDACommonCompletionHandler)(DADissenterRef dissenter);
+static void _commonDACompletionCallback(DADiskRef disk, DADissenterRef dissenter, void *context)
+{
+ AIRDBDACommonCompletionHandler handler = (__bridge AIRDBDACommonCompletionHandler)context;
+ handler(dissenter);
+}
+
+@implementation PreloginUserDb {
+ DMManager *_diskMgr;
+ id _daSession;
+ NSMutableDictionary<NSString*, NSMutableArray*> *_dbDataDict; // NSDictionary indexed by volume UUID (NSString*)
+ NSMutableDictionary<NSString*, NSString*> *_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)];
+ }
+ 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);
+
+ _dbDataDict = [NSMutableDictionary new];
+ _dbVolumeGroupMap = [NSMutableDictionary new];
+ [self processPrebootVolumes:prebootVolumes currentRecoveryVolumeUUID:uuid];
+
+ 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]; // load admins from ALL preboot partitions
+ }
+
+ if (err) {
+ *err = nil;
+ }
+ return YES;
+}
+
+- (NSArray<NSDictionary *> *)users
+{
+ return [self users:nil];
+}
+
+- (NSArray<NSDictionary *> *) 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;
+}
+#pragma mark - Private Methods
+
+- (void)processPrebootVolumes:(NSArray*)prebootVolumes currentRecoveryVolumeUUID:(NSUUID *)currentRecoveryVolumeUUID
+{
+ // 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) {
+ 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;
+ }
+
+ [self processVolumeData:volumeUUID mountPoint: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_SCUNLOCK_DATA] = userData[kSCEnforcementItemName];
+ }
+ if ([userData.allKeys containsObject:kSCUnlockDataItemName]) {
+ dict[@PLUDB_SCUNLOCK_DATA] = userData[kSCUnlockDataItemName];
+ }
+ 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];
+ }
+}
+
+@end
+
+OSStatus preloginudb_copy_userdb(const char *uuid, UInt32 flags, CFArrayRef *output)
+{
+ if (!output) {
+ return errAuthorizationBadAddress;
+ }
+ 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;
+ }
+
+ 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;
+}
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
+ <key>com.apple.keystore.console</key>
+ <true/>
<key>com.apple.private.LocalAuthentication.ExtractCredential</key>
<true/>
- <key>com.apple.keystore.console</key>
+ <key>com.apple.private.security.clear-library-validation</key>
+ <true/>
+ <key>com.apple.keystore.filevault</key>
<true/>
</dict>
</plist>
AUTHORIZATION_DISMISS,
AUTHORIZATION_SETUP,
AUTHORIZATION_ENABLE_SMARTCARD,
- AUTHORIZATION_PREAUTHORIZE_CREDENTIALS
+ AUTHORIZATION_PREAUTHORIZE_CREDENTIALS,
+ AUTHORIZATION_COPY_PRELOGIN_USERDB,
+ AUTHORIZATION_COPY_RIGHT_PROPERTIES
};
#if defined(__cplusplus)
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);
}
}
}
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");
#include "authutilities.h"
#include <Security/AuthorizationTags.h>
+#include <Security/AuthorizationTagsPriv.h>
#include <dispatch/private.h>
#include <CommonCrypto/CommonCrypto.h>
+#include <security_utilities/simulatecrash_assert.h>
+
AUTHD_DEFINE_LOG
typedef struct _auth_item_s * auth_item_t;
xpc_dictionary_set_string(xpc_data, AUTH_XPC_ITEM_NAME, item->data.name);
if (item->data.value) {
// <rdar://problem/13033889> 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
</dict>
<key>com.apple.trust-settings.admin</key>
<dict>
- <key>allow-root</key>
- <true/>
- <key>class</key>
- <string>user</string>
<key>comment</key>
- <string>For modifying Trust Settings in the Local Admin domain.</string>
- <key>group</key>
- <string>admin</string>
+ <string>For modifying Trust Settings in the Admin domain. Requires entitlement or admin authentication.</string>
+ <key>class</key>
+ <string>rule</string>
+ <key>k-of-n</key>
+ <integer>1</integer>
+ <key>rule</key>
+ <array>
+ <string>entitled</string>
+ <string>authenticate-admin</string>
+ </array>
</dict>
<key>com.apple.trust-settings.user</key>
<dict>
</dict>
<key>com.apple.uninstalld.uninstall</key>
<dict>
+ <key>authenticate-user</key>
+ <false/>
<key>class</key>
- <string>rule</string>
- <key>rule</key>
- <string>entitled-admin-or-authenticate-admin</string>
+ <string>user</string>
+ <key>entitled</key>
+ <true/>
+ <key>version</key>
+ <integer>1</integer>
</dict>
<key>config.add.</key>
<dict>
<key>comment</key>
<string>For burning media.</string>
</dict>
+ <key>com.apple.installassistant.requestpassword</key>
+ <dict>
+ <key>authenticate-user</key>
+ <true/>
+ <key>class</key>
+ <string>user</string>
+ <key>comment</key>
+ <string>Authenticate as an administrator, password only.</string>
+ <key>group</key>
+ <string>admin</string>
+ <key>password-only</key>
+ <true/>
+ <key>shared</key>
+ <false/>
+ <key>timeout</key>
+ <integer>0</integer>
+ </dict>
<key>system.csfde.requestpassword.weak</key>
<dict>
<key>class</key>
<key>class</key>
<string>rule</string>
<key>comment</key>
- <string>Checked when user is installing Apple-provided software.</string>
+ <string>Checked when user is installing Apple software.</string>
<key>rule</key>
<string>root-or-entitled-admin-or-authenticate-admin</string>
</dict>
<key>mechanisms</key>
<array>
<string>builtin:policy-banner</string>
+ <string>builtin:prelogin</string>
<string>loginwindow:login</string>
<string>builtin:login-begin</string>
<string>builtin:reset-password,privileged</string>
<string>loginwindow:done</string>
</array>
<key>version</key>
- <integer>7</integer>
+ <integer>8</integer>
+ </dict>
+ <key>system.login.filevault</key>
+ <dict>
+ <key>class</key>
+ <string>evaluate-mechanisms</string>
+ <key>comment</key>
+ <string>Login mechanism based rule for Filevault.</string>
+ <key>mechanisms</key>
+ <array>
+ <string>builtin:policy-banner</string>
+ <string>loginwindow:login</string>
+ <string>builtin:login-begin</string>
+ <string>builtin:authenticate,privileged</string>
+ <string>builtin:login-success</string>
+ <string>loginwindow:success</string>
+ <string>loginwindow:done</string>
+ </array>
</dict>
<key>system.login.fus</key>
<dict>
<key>version</key>
<integer>1</integer>
</dict>
+ <key>com.apple.configurationprofiles.deviceenrollment.install</key>
+ <dict>
+ <key>class</key>
+ <string>user</string>
+ <key>comment</key>
+ <string>This right is used by UserManagement to ask for an admin password.</string>
+ <key>group</key>
+ <string>admin</string>
+ <key>password-only</key>
+ <true/>
+ <key>shared</key>
+ <false/>
+ <key>version</key>
+ <integer>1</integer>
+ </dict>
+ <key>com.apple.configurationprofiles.deviceenrollment.uninstall</key>
+ <dict>
+ <key>class</key>
+ <string>user</string>
+ <key>comment</key>
+ <string>This right is used by UserManagement to ask for an admin password.</string>
+ <key>group</key>
+ <string>admin</string>
+ <key>password-only</key>
+ <true/>
+ <key>shared</key>
+ <false/>
+ <key>version</key>
+ <integer>1</integer>
+ </dict>
<key>com.apple.safaridriver.allow</key>
<dict>
<key>comment</key>
<key>shared</key>
<false/>
</dict>
- </dict>
+ <key>com.apple.system-migration.launch</key>
+ <dict>
+ <key>comment</key>
+ <string>Used by Migration Assistant.</string>
+ <key>class</key>
+ <string>rule</string>
+ <key>rule</key>
+ <string>authenticate-admin-nonshared</string>
+ <key>shared</key>
+ <false/>
+ </dict>
+ <key>com.apple.system-migration.cleanup</key>
+ <dict>
+ <key>comment</key>
+ <string>Used by System Migration.</string>
+ <key>class</key>
+ <string>rule</string>
+ <key>rule</key>
+ <string>authenticate-admin-nonshared</string>
+ <key>shared</key>
+ <false/>
+ </dict>
+ </dict>
<key>rules</key>
<dict>
<key>admin</key>
<string>builtin:authenticate</string>
<string>builtin:reset-password,privileged</string>
<string>builtin:authenticate,privileged</string>
- <string>PKINITMechanism:auth,privileged</string>
</array>
+ <key>version</key>
+ <integer>1</integer>
</dict>
<key>kcunlock</key>
<dict>
#include <Security/SecBase.h>
#include <sandbox.h>
+#include <security_utilities/simulatecrash_assert.h>
+
AUTHD_DEFINE_LOG
static Boolean AuthTokenEqualCallBack(const void *value1, const void *value2)
#include "debugging.h"
#include <AssertMacros.h>
-#include <assert.h>
AUTHD_DEFINE_LOG
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);
free_safe(values);
return result;
}
+
+bool isInLWOS()
+{
+ // temporary solution until we find a better way
+ return getenv("__OSINSTALL_ENVIRONMENT") != NULL;
+}
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 isInLWOS(void);
+
#if defined(__cplusplus)
}
#endif
(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")
(preference-domain "com.apple.authd"))
(allow system-audit system-sched)
+
+(allow iokit-open
+ (iokit-user-client-class "AppleAPFSUserClient")
+ (iokit-user-client-class "AppleKeyStoreUserClient"))
AUTH_INLINE uint64_t
crc64_final(uint64_t crc)
{
- return crc ^= xorout;
+ return crc ^ xorout;
}
AUTH_INLINE AUTH_NONNULL_ALL uint64_t
#include "credential.h"
#include "authutilities.h"
+#include "authitems.h"
+#include <Security/AuthorizationTagsPriv.h>
#include "debugging.h"
#include "crc.h"
_credential_create()
{
credential_t cred = NULL;
-
+
cred = (credential_t)_CFRuntimeCreateInstance(kCFAllocatorDefault, credential_get_type_id(), AUTH_CLASS_SIZE(credential), NULL);
require(cred != NULL, done);
return cred;
}
+credential_t
+credential_create_lwos(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)
{
}
bool
-credential_check_membership(credential_t cred,const char* group)
+credential_check_membership(credential_t cred, const char* group)
{
bool result = false;
+
+ if (isInLWOS()) {
+ return false; // cannot succeed in LWOS as we do not have group data
+ }
+
CFStringRef cachedGroup = NULL;
require(group != NULL, done);
require(cred->uid != 0 || cred->uid != (uid_t)-2, done);
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_lwos(auth_items_t context, bool session);
+
AUTH_NONNULL_ALL
uid_t credential_get_uid(credential_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;
auth_rights_t grantedRights;
CFTypeRef la_context;
- bool preauthorizing;
enum Reason reason;
int32_t tries;
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 (isInLWOS()) {
+ engine->sessionCredential = credential_create_lwos(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);
}
}
+static bool _is_lwos_user_in_group(engine_t engine, rule_t rule)
+{
+ if (!isInLWOS()) {
+ 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)
{
return errAuthorizationDenied;
}
- if (credential_get_valid(cred) != true) {
+ if (credential_get_valid(cred) != true && !isInLWOS()) {
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;
}
}
- if (credential_check_membership(cred, rule_get_group(rule))) {
+ if (credential_check_membership(cred, rule_get_group(rule)) || _is_lwos_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 {
static OSStatus
_evaluate_authentication(engine_t engine, rule_t rule)
{
+ os_log_debug(AUTHD_LOG, "engine %lld: FV mode %d", engine->engine_index, isInLWOS());
+
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 (!isInLWOS()) {
+ // we do not need to set hints in LWOS 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)) {
status = errAuthorizationDenied;
credential_t newCred = NULL;
- if (auth_items_exist(engine->context, "uid")) {
- newCred = credential_create(auth_items_get_uint(engine->context, "uid"));
+
+ if (isInLWOS() && auth_items_exist(engine->context, kAuthorizationFVAdmin)) {
+ os_log_debug(AUTHD_LOG, "Credentials for FV unlock (engine %lld)", engine->engine_index);
+ newCred = credential_create_lwos(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);
}
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) || isInLWOS()) {
+ 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);
}
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 (!isInLWOS()) {
+ status = _evaluate_user_credential_for_rule(engine, engine->sessionCredential, rule, true, true, NULL);
+
+ if (status == errAuthorizationSuccess) {
+ return errAuthorizationSuccess;
+ }
}
return errAuthorizationDenied;
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);
}
}
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;
});
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);
}
// 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));
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:
#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 = 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);
- }
+ OSStatus status = errAuthorizationInternal;
+
+ CFMutableDictionaryRef properties = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ require(properties != NULL, done);
+ require(rightName != NULL, done);
- 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)
__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);
engine_acquire_sheet_data(engine);
_extract_password_from_la(engine);
- engine->preauthorizing = true;
}
engine->dismissed = false;
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;
// only need the hints & mechanisms if we are going to show ui
if (engine->flags & kAuthorizationFlagInteractionAllowed || engine->flags & kAuthorizationFlagSheet) {
+ os_log_debug(AUTHD_LOG, "setting hints for UI authorization");
_set_right_hints(engine->hints, key);
_set_localization_hints(dbconn, engine->hints, rule);
if (!engine->authenticateRule) {
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;
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);
#include <xpc/xpc.h>
#include <xpc/private.h>
#include <dispatch/dispatch.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include <sandbox.h>
#if DEBUG
}
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;
#if DEBUG
case AUTHORIZATION_DEV:
server_dev();
#include <Security/SecCode.h>
#include <Security/SecRequirement.h>
+#include <security_utilities/simulatecrash_assert.h>
+
AUTHD_DEFINE_LOG
struct _process_s {
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)
{
bool
rule_get_shared(rule_t rule)
{
+ if (isInLWOS()) {
+ return false;
+ }
return rule_check_flags(rule, RuleFlagShared);
}
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);
#include "engine.h"
#include "connection.h"
#include "AuthorizationTags.h"
+#include "PreloginUserDb.h"
#include <bsm/libbsm.h>
#include <Security/Authorization.h>
#include <IOKit/pwr_mgt/IOPMLib.h>
#include <IOKit/pwr_mgt/IOPMLibPrivate.h>
+#include <security_utilities/simulatecrash_assert.h>
+
AUTHD_DEFINE_LOG
#define MAX_PROCESS_RIGHTS 100
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)
// 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;
-
- 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"));
+ 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);
- 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;
}
// 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"));
+
+ 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;
+}
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);
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);
+
#if defined(__cplusplus)
}
#endif
#include <dispatch/dispatch.h>
#include <CoreFoundation/CoreFoundation.h>
+#include <security_utilities/simulatecrash_assert.h>
+
AUTHD_DEFINE_LOG
struct _session_s {
ONE_TEST(authd_01_authorizationdb)
ONE_TEST(authd_02_basicauthorization)
ONE_TEST(authd_04_executewithprivileges)
+ONE_TEST(authd_05_rightproperties)
//
#import <Security/Authorization.h>
+#import <Security/AuthorizationPriv.h>
#import <Security/AuthorizationDB.h>
#import <Security/AuthorizationTagsPriv.h>
#import <Foundation/Foundation.h>
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;
+}
ALWAYS_SEARCH_USER_PATHS = NO
-GCC_C_LANGUAGE_STANDARD = gnu99
+GCC_C_LANGUAGE_STANDARD = gnu2x
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
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
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
+++ /dev/null
-./libsecurity_asn1/lib
\ No newline at end of file
+++ /dev/null
-./libsecurity_cdsa_client/lib
\ No newline at end of file
+++ /dev/null
-./libsecurity_cdsa_plugin/lib
\ No newline at end of file
+++ /dev/null
-./libsecurity_cdsa_utilities/lib
\ No newline at end of file
+++ /dev/null
-./libsecurity_cdsa_utils/lib
\ No newline at end of file
+++ /dev/null
-./libsecurity_codesigning/lib
\ No newline at end of file
+++ /dev/null
-./libsecurity_comcryption/lib
\ No newline at end of file
+++ /dev/null
-./libsecurity_cryptkit/lib
\ No newline at end of file
+++ /dev/null
-./libsecurity_filedb/lib
\ No newline at end of file
+++ /dev/null
-./libsecurity_keychain/lib
\ No newline at end of file
+++ /dev/null
-./libsecurity_ocspd/common
\ No newline at end of file
+++ /dev/null
-./libsecurity_pkcs12/lib
\ No newline at end of file
+++ /dev/null
-./libsecurity_smime/lib
\ No newline at end of file
+++ /dev/null
-./libsecurity_utilities/lib
\ No newline at end of file
+++ /dev/null
-./libsecurityd/lib
\ No newline at end of file
"com.apple.security.sudo" = "Allow";
"com.apple.configurationprofiles.userenrollment.install" = "Enroll";
+
+"com.apple.configurationprofiles.deviceenrollment.install" = "Enroll";
+
+"com.apple.configurationprofiles.deviceenrollment.uninstall" = "Unenroll";
"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.";
"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.";
"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.";
"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.";
"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.";
+++ /dev/null
-;; 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")))
#include <security_cdsa_utilities/cssmdata.h>
#include <AppleCSPSession.h>
#include <AppleCSPUtils.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include <security_utilities/debugging.h>
#include <Security/oidsalg.h>
#include <YarrowConnection.h>
// 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:
mAllocdPrivKey);
}
else {
- assert(opStarted());
+ assert(opStarted());
}
if(mPubKey == NULL) {
assert(!opStarted());
mAllocdPubKey);
}
else {
- assert(opStarted());
+ assert(opStarted());
}
/* validate context - no other attributes allowed */
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:
#include <security_cdsa_utilities/cssmdata.h>
#include "AppleCSPSession.h"
#include "AppleCSPUtils.h"
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include <security_utilities/debugging.h>
#define feeKeyDebug(args...) secinfo("feeKey", ## args)
#include <security_cryptkit/feeDigitalSignature.h>
#include <security_cryptkit/falloc.h>
#include <stdexcept>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include <security_utilities/debugging.h>
#define feeSigObjDebug(args...) secinfo("feeSig", ##args)
#include <security_cdsa_utilities/cssmdata.h>
#include <AppleCSPSession.h>
#include <AppleCSPUtils.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include <security_utilities/debugging.h>
#include "RSA_DSA_utils.h"
#include <YarrowConnection.h>
#include "RSA_DSA_signature.h"
#include "RSA_DSA_utils.h"
#include <stdexcept>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include <security_utilities/debugging.h>
#include <security_cdsa_utilities/cssmdata.h>
#include <opensslUtils/opensslUtils.h>
if (d->dict())
{
- auto_ptr<Dictionary>apd(d);
+ unique_ptr<Dictionary>apd(d);
rsaLookupVal(*apd, kRSAMaxKeySizePref, maxKeySize);
rsaLookupVal(*apd, kRSAMaxPublicExponentPref, maxPubExponentSize);
}
bool isPub;
bool isOaep = false;
- assert(hdr->BlobType == CSSM_KEYBLOB_RAW);
+ assert(hdr->BlobType == CSSM_KEYBLOB_RAW);
switch(hdr->AlgorithmId) {
case CSSM_ALGID_RSA:
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)
}
}
else {
- assert(opStarted());
+ assert(opStarted());
}
unsigned cipherBlockSize = RSA_size(mRsaKey);
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include <security_asn1/SecNssCoder.h>
#include <CoreFoundation/CoreFoundation.h>
*/
CSSM_KEY_SIZE keySize;
try {
- auto_ptr<CSPKeyInfoProvider> provider(infoProvider(key));
+ unique_ptr<CSPKeyInfoProvider> provider(infoProvider(key));
provider->QueryKeySizeInBits(keySize);
}
catch(const CssmError &cerror) {
(hdr.AlgorithmId == CSSM_ALGID_DSA)) {
hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_FIPS186;
try {
- auto_ptr<CSPKeyInfoProvider> provider(infoProvider(key));
+ unique_ptr<CSPKeyInfoProvider> provider(infoProvider(key));
provider->QueryKeySizeInBits(keySize);
}
catch(...) {
/* now figure out the key size by finding a provider for this key */
CSSM_KEY_SIZE keySize;
try {
- auto_ptr<CSPKeyInfoProvider> provider(infoProvider(key));
+ unique_ptr<CSPKeyInfoProvider> provider(infoProvider(key));
provider->QueryKeySizeInBits(keySize);
}
catch(...) {
#endif
#include <stdio.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include "cryptlib.h"
#include "bn_lcl.h"
#endif
#include <stdio.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include "cryptlib.h"
#include <openssl/bn_legacy.h>
#ifdef ATALLA
# include <alloca.h>
# include <atasi.h>
-# include <assert.h>
+# include <security_utilities/simulatecrash_assert.h>
# include <dlfcn.h>
#endif
#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 <assert.h>
-# define bn_check_top(a) assert ((a)->top >= 0 && (a)->top <= (a)->dmax);
-#else
-# define bn_check_top(a)
-#endif
+#include <security_utilities/simulatecrash_assert.h>
+#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
#include <Security/oidsalg.h>
#include <Security/SecAsn1Templates.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#define sslAsn1Debug(args...) secinfo("sslAsn1", ##args)
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);
- }
+}
}
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);
- }
+}
// 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> ssKey(&mSSCSPDLSession.find<SSKey>(ioKey));
+ unique_ptr<SSKey> ssKey(&mSSCSPDLSession.find<SSKey>(ioKey));
ssKey->free(accessCred, ioKey, deleteKey);
}
else
if(!inSize) return;
const CssmData in(const_cast<void *>(mNullDigest.digestPtr()), inSize);
- IFDEBUG(size_t origOutSize = out.length());
+ size_t origOutSize = out.length();
if (encoding()) {
clientSession().encrypt(*mContext, mKeyHandle, in, out);
}
/* 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;
/*
* 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);
}
/* 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();
}
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;
};
#include <security_ocspd/ocspResponse.h>
#include <security_ocspd/ocspExtensions.h>
#include <security_ocspd/ocspdUtils.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include <string.h>
#include <Security/oidsalg.h>
#include <Security/oidscert.h>
#include <Security/oidsalg.h>
#include <Security/cssmapple.h>
-/*
- * 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 <Security/SecKeychain.h>
-#include <Security/SecKeychainSearch.h>
-#include <Security/SecCertificate.h>
-#include <Security/oidscert.h>
-#include <sys/types.h>
-#include <pwd.h>
-
-#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
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 */
}
/*
#include <Security/cssmapple.h>
#include <security_utilities/debugging.h>
#include <Security/cssmapple.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#define tpCredDebug(args...) secinfo("tpCred", ## args)
#include <security_utilities/globalizer.h>
#include <security_utilities/threading.h>
#include <security_ocspd/ocspdUtils.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
/*
* Set this flag nonzero to turn off this cache module. Generally used to debug
#include <Security/SecCertificatePriv.h>
#include <string.h>
#include <ctype.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include <CoreFoundation/CFString.h>
#include <CommonCrypto/CommonDigest.h>
#include <ctype.h>
#include <stdbool.h>
+#include <security_utilities/simulatecrash_assert.h>
+
/*
* Given a string containing either a UTC-style or "generalized time"
* time string, convert to a CFDateRef. Returns nonzero on
#include <security_utilities/utilities.h>
#include <security_asn1/secasn1.h>
#include <string.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#ifdef NDEBUG
#define THROW_ENABLE 1
#include "SecAsn1Templates.h"
#include "X509Templates.h"
#include "keyTemplates.h"
-#include <assert.h>
#include <stddef.h>
/*
#include "X509Templates.h"
#include "keyTemplates.h"
#include <stddef.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
typedef struct {
SecAsn1Oid typeId;
#include "keyTemplates.h" /* for kSecAsn1AlgorithmIDTemplate */
#include "SecAsn1Templates.h"
#include <stddef.h>
-#include <assert.h>
// MARK: ----- OCSP Request -----
ap = &head->next;
a = *ap;
- if (!a)
+ if (!a) {
return;
+ }
do {
*ap = a->next;
#ifdef __APPLE__
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#define PR_ASSERT(_exp) assert(_exp)
#define PR_NOT_REACHED(_reas) assert(0)
PR_Assert(_reasonStr,__FILE__,__LINE__)
#endif
-#else
+#else /* defined(DEBUG) || defined(FORCE_PR_ASSERT) */
+
+#ifdef __APPLE__
+#include <security_utilities/simulatecrash_assert.h>
+
+#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) */
#include "secasn1.h"
#include "secerr.h"
-#include "assert.h"
+#include <security_utilities/simulatecrash_assert.h>
#ifdef NDEBUG
#define DEBUG_DECASN1 0
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);
+++ /dev/null
-.
\ No newline at end of file
#include <xpc/xpc.h>
#include <xpc/private.h>
#include <mach/mach.h>
-#include <syslog.h>
#include <AssertMacros.h>
#include <CoreFoundation/CFXPCBridge.h>
#include <CoreGraphics/CGWindow.h>
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);
}
});
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;);
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);
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);
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;
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);
return status;
}
-static OSStatus
-_AuthorizationPreauthorizeCredentials_send_message(xpc_object_t message)
-{
- 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 AuthorizationCopyRightProperties(const char *rightName, CFDictionaryRef *output)
{
- 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;
}
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);
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);
}
// 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);
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);
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;
}
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);
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;
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);
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);
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);
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);
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;
+}
#include <security_cdsa_utilities/cssmbridge.h>
#include <Security/SecBase.h>
#include <security_utilities/logging.h>
+#include "LegacyAPICounts.h"
//
// This no longer talks to securityd; it is a kernel function.
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<CFMutableDictionaryRef> userPrefsDict(CFDictionaryCreateMutable(NULL, 10, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
-// CFRef<CFMutableDictionaryRef> globalPrefsDict(CFDictionaryCreateMutable(NULL, 10, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
-//
-// if (!userPrefsDict || !globalPrefsDict)
-// return errSessionValueNotSet;
-//
-// CFRef<CFArrayRef> appleLanguagesArray(static_cast<CFArrayRef>(CFPreferencesCopyAppValue(appleLanguagesStr, kCFPreferencesCurrentApplication)));
-// if (appleLanguagesArray)
-// CFDictionarySetValue(globalPrefsDict, appleLanguagesStr, appleLanguagesArray);
-//
-// CFRef<CFNumberRef> controlTintNumber(static_cast<CFNumberRef>(CFPreferencesCopyAppValue(controlTintStr, kCFPreferencesCurrentApplication)));
-// if (controlTintNumber)
-// CFDictionarySetValue(globalPrefsDict, controlTintStr, controlTintNumber);
-//
-// CFRef<CFNumberRef> keyboardUIModeNumber(static_cast<CFNumberRef>(CFPreferencesCopyAppValue(keyboardUIModeStr, kCFPreferencesCurrentApplication)));
-// if (keyboardUIModeNumber)
-// CFDictionarySetValue(globalPrefsDict, keyboardUIModeStr, keyboardUIModeNumber);
-//
-// CFRef<CFNumberRef> textDirectionNumber(static_cast<CFNumberRef>(CFPreferencesCopyAppValue(textDirectionStr, kCFPreferencesCurrentApplication)));
-// if (textDirectionNumber)
-// CFDictionarySetValue(globalPrefsDict, textDirectionStr, textDirectionNumber);
-//
-// if (CFDictionaryGetCount(globalPrefsDict) > 0)
-// CFDictionarySetValue(userPrefsDict, kCFPreferencesAnyApplication, globalPrefsDict);
-//
-// CFPreferencesSynchronize(hitoolboxAppIDStr, kCFPreferencesCurrentUser,
-// kCFPreferencesCurrentHost);
-// CFRef<CFDictionaryRef> hitoolboxPrefsDict(static_cast<CFDictionaryRef>(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<CFDataRef> 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;
}
/*!
- @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.
/*!
- @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.
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
/*!
- @struct
+ @typedef
Callback API provided by the AuthorizationEngine.
@field version Engine callback version.
/*!
- @struct
+ @typedef
Interface that must be implemented by each plugin.
@field version Must be set to kAuthorizationPluginInterfaceVersion
#include <Security/AuthSession.h>
#include <sys/types.h> // uid_t
#include <mach/message.h>
+#include <CoreFoundation/CFDictionary.h>
#if defined(__cplusplus)
extern "C" {
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
@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,
@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,
int stdErr,
int stdIn,
void(^__nullable processFinished)(const int exitStatus));
+
+/*!
+ @function AuthorizationCopyPreloginUserDatabase
+ Returns 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);
+
#if defined(__cplusplus)
}
#endif
#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"
#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"
/* Sheet window ID */
#define kAuthorizationEnvironmentWindowId "cgwindowid"
+/* LWOS 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_ */
//
// trampolineClient - Authorization trampoline client-side implementation
//
-#include <asl.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
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;
// Exception model
//
const char *
-Error::what () const throw()
+Error::what () const _NOEXCEPT
{
return "CSSM client library error";
}
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,
#include <security_cdsa_plugin/cssmplugin.h>
#include <security_cdsa_utilities/cssmbridge.h>
#include <Security/cssmaci.h>
-
+// The disclaimer up top used to be true but rdar://24426719 removed libsecurity_cdsa_plugin_generate
+#include "LegacyAPICounts.h"
ACAbstractPluginSession::~ACAbstractPluginSession()
{ /* virtual */ }
#include <security_cdsa_plugin/cssmplugin.h>
#include <security_cdsa_utilities/cssmbridge.h>
#include <Security/cssmcli.h>
-
+// The disclaimer up top used to be true but rdar://24426719 removed libsecurity_cdsa_plugin_generate
+#include "LegacyAPICounts.h"
CLAbstractPluginSession::~CLAbstractPluginSession()
{ /* virtual */ }
#include <security_cdsa_plugin/cssmplugin.h>
#include <security_cdsa_utilities/cssmbridge.h>
#include <Security/cssmcspi.h>
-
+// The disclaimer up top used to be true but rdar://24426719 removed libsecurity_cdsa_plugin_generate
+#include "LegacyAPICounts.h"
CSPAbstractPluginSession::~CSPAbstractPluginSession()
{ /* virtual */ }
#include <security_cdsa_plugin/cssmplugin.h>
#include <security_cdsa_utilities/cssmbridge.h>
#include <Security/cssmdli.h>
+// The disclaimer up top used to be true but rdar://24426719 removed libsecurity_cdsa_plugin_generate
+#include "LegacyAPICounts.h"
DLAbstractPluginSession::~DLAbstractPluginSession()
//
// 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); }
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();
DatabaseMap::iterator anIterator = mDatabaseMap.find (inDbName);
if (anIterator == mDatabaseMap.end())
{
- auto_ptr<Database> aDatabase(make(inDbName));
+ unique_ptr<Database> aDatabase(make(inDbName));
mDatabaseMap.insert(DatabaseMap::value_type(aDatabase->mDbName, aDatabase.get()));
return aDatabase.release();
}
const AccessCredentials *inAccessCred,
const void *inOpenParameters)
{
- auto_ptr<DbContext>aDbContext(makeDbContext(inDatabaseSession,
+ unique_ptr<DbContext>aDbContext(makeDbContext(inDatabaseSession,
inAccessRequest,
inAccessCred,
inOpenParameters));
const CSSM_RESOURCE_CONTROL_CONTEXT *inCredAndAclEntry,
const void *inOpenParameters)
{
- auto_ptr<DbContext>aDbContext(makeDbContext(inDatabaseSession,
+ unique_ptr<DbContext>aDbContext(makeDbContext(inDatabaseSession,
inAccessRequest,
(inCredAndAclEntry
? AccessCredentials::optional(inCredAndAclEntry->AccessCred)
DbContextMap::iterator it = mDbContextMap.find(inDbHandle);
if (it == mDbContextMap.end())
CssmError::throwMe(CSSM_ERRCODE_INVALID_DB_HANDLE);
- auto_ptr<DbContext> aDbContext(it->second);
+ unique_ptr<DbContext> aDbContext(it->second);
mDbContextMap.erase(it);
mDatabaseManager.dbClose(*aDbContext);
}
#include <security_cdsa_plugin/cssmplugin.h>
#include <security_cdsa_utilities/cssmbridge.h>
#include <Security/cssmtpi.h>
-
+// The disclaimer up top used to be true but rdar://24426719 removed libsecurity_cdsa_plugin_generate
+#include "LegacyAPICounts.h"
TPAbstractPluginSession::~TPAbstractPluginSession()
{ /* virtual */ }
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;
}
#include <security_cdsa_plugin/cssmplugin.h>
#include <security_cdsa_plugin/pluginsession.h>
#include <memory>
+#include "LegacyAPICounts.h"
ModuleNexus<CssmPlugin::SessionMap> CssmPlugin::sessionMap;
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();
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;
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<PluginSession> session(this->makeSession(theHandle,
+ unique_ptr<PluginSession> session(this->makeSession(theHandle,
version,
subserviceId, subserviceType,
attachFlags,
//
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;
{
//
// 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();
}
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; }
CSSM_SPI_ModuleEventHandler CssmNotifyCallback,
void *CssmNotifyCallbackCtx)
{
- BEGIN_API
+ BEGIN_API_NO_METRICS
plugin().moduleLoad(Guid::required(CssmGuid),
Guid::required(ModuleGuid),
ModuleCallback(CssmNotifyCallback, CssmNotifyCallbackCtx));
CSSM_SPI_ModuleEventHandler CssmNotifyCallback,
void *CssmNotifyCallbackCtx)
{
- BEGIN_API
+ BEGIN_API_NO_METRICS
plugin().moduleUnload(Guid::required(CssmGuid),
Guid::required(ModuleGuid),
ModuleCallback(CssmNotifyCallback, CssmNotifyCallbackCtx));
const CSSM_UPCALLS *Upcalls,
CSSM_MODULE_FUNCS_PTR *FuncTbl)
{
- BEGIN_API
+ BEGIN_API_NO_METRICS
plugin().moduleAttach(ModuleHandle,
Guid::required(CssmGuid),
Guid::required(ModuleGuid),
SPIPREFIX CSSM_RETURN SPINAME(CSSM_SPI_ModuleDetach) (CSSM_MODULE_HANDLE ModuleHandle)
{
- BEGIN_API
+ BEGIN_API_NO_METRICS
plugin().moduleDetach(ModuleHandle);
END_API(CSSM)
}
// 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<void>(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
// 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
// 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);
}
}
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:
//
// 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); }
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;
{ *(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;
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;
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<Allocator *>(ref); }
};
#include <security_cdsa_utilities/cssmerrors.h>
#include <Security/cssm.h>
-
namespace Security {
-
//
// API boilerplate macros. These provide a frame for C++ code that is impermeable to exceptions.
// Usage:
// 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); } \
}
-CssmData& CssmOwnedData::get() const throw()
+CssmData& CssmOwnedData::get() const _NOEXCEPT
{
return referent;
}
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
};
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...)
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.
private:
const CssmData &mData;
-#ifndef NDEBUG
CSSM_DB_ATTRIBUTE_FORMAT mFormat;
-#endif
};
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; }
address(const_cast<CssmNetAddress *>(ident.dbLocation()))
{ }
- operator DLDbIdentifier () { return DLDbIdentifier(*uid, name, address); }
+ operator DLDbIdentifier () {
+ DLDbIdentifier db(*uid, name, address);
+ return db;
+ }
};
template<class Action>
}
-const char *CssmError::what() const throw ()
+const char *CssmError::what() const _NOEXCEPT
{
return whatBuffer;
}
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);
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;
// logically remove the first element (skip it)
void snip();
+
+ CssmList &operator =(const CssmList& other);
public:
void clear(Allocator &alloc); // free my contents
{
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] = '}';
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);
}
-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
&& 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"
CSSM_RETURN CryptoDataClass::callbackShim(CSSM_DATA *output, void *ctx)
{
- BEGIN_API
+ BEGIN_API_NO_METRICS
*output = reinterpret_cast<CryptoDataClass *>(ctx)->yield();
END_API(CSSM)
}
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);
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,
#include <Security/cssmtype.h>
#include <Security/cssmapple.h> /* cssmPerror() */
#include <CoreFoundation/CoreFoundation.h>
-#include <assert.h>
#ifdef __cplusplus
extern "C" {
#define CFRELEASE(cfr) if(cfr != NULL) { CFRelease(cfr); }
+#include <security_utilities/simulatecrash_assert.h>
+#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
#include <sys/param.h>
#include <xpc/xpc.h>
#include <syslog.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include <libproc.h>
#include <sandbox.h>
#include <syslog.h>
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;
auditData);
}
CFRef<SecCodeRef> 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<CFURLRef> codePath;
- if ((rc = SecCodeCopyPath(code, kSecCSDefaultFlags, &codePath.aref())) == noErr) {
+ if (SecCodeCopyPath(code, kSecCSDefaultFlags, &codePath.aref()) == noErr) {
CFRef<CFDataRef> data = CFURLCreateData(NULL, codePath, kCFStringEncodingUTF8, true);
xpc_dictionary_set_data(reply, "bundleURL", CFDataGetBytePtr(data), CFDataGetLength(data));
}
: text(s)
{
}
- virtual ~ANTLRException() throw()
+ virtual ~ANTLRException() _NOEXCEPT
{
}
public:
CharStreamException(const ANTLR_USE_NAMESPACE(std)string& s)
: ANTLRException(s) {}
- ~CharStreamException() throw() {}
+ ~CharStreamException() _NOEXCEPT {}
};
#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE
CharStreamIOException(ANTLR_USE_NAMESPACE(std)exception& e)
: CharStreamException(e.what()), io(e) {}
- ~CharStreamIOException() throw() {}
+ ~CharStreamIOException() _NOEXCEPT {}
};
#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE
: ANTLRException(mesg)
{
}
- virtual ~IOException() throw()
+ virtual ~IOException() _NOEXCEPT
{
}
};
CharScanner* scanner_
);
- ~MismatchedCharException() throw() {}
+ ~MismatchedCharException() _NOEXCEPT {}
/**
* Returns a clean error message (no line number/column information)
bool matchNot,
const ANTLR_USE_NAMESPACE(std)string& fileName_
);
- ~MismatchedTokenException() throw() {}
+ ~MismatchedTokenException() _NOEXCEPT {}
/**
* Returns a clean error message (no line number/column information)
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)
NoViableAltForCharException(int c, const ANTLR_USE_NAMESPACE(std)string& fileName_,
int line_, int column_);
- virtual ~NoViableAltForCharException() throw()
+ virtual ~NoViableAltForCharException() _NOEXCEPT
{
}
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;
}
{
}
- ~SemanticException() throw()
+ ~SemanticException() _NOEXCEPT
{
}
};
: ANTLRException(s)
{
}
- virtual ~TokenStreamException() throw()
+ virtual ~TokenStreamException() _NOEXCEPT
{
}
};
, io(e)
{
}
- ~TokenStreamIOException() throw()
+ ~TokenStreamIOException() _NOEXCEPT
{
}
private:
, recog(re)
{
}
- virtual ~TokenStreamRecognitionException() throw()
+ virtual ~TokenStreamRecognitionException() _NOEXCEPT
{
}
virtual ANTLR_USE_NAMESPACE(std)string toString() const
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();
}
class TokenStreamRetryException : public TokenStreamException {
public:
TokenStreamRetryException() {}
- ~TokenStreamRetryException() throw() {}
+ ~TokenStreamRetryException() _NOEXCEPT {}
};
#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE
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) );
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 */
};
@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 */
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*/
};
/*!
//
// Clean up a SecCode object
//
-SecCode::~SecCode() throw()
+SecCode::~SecCode() _NOEXCEPT
try {
} catch (...) {
return;
SECCFFUNCTIONS(SecCode, SecCodeRef, errSecCSInvalidObjectRef, gCFObjects().Code)
SecCode(SecCode *host);
- virtual ~SecCode() throw();
+ virtual ~SecCode() _NOEXCEPT;
bool equal(SecCFObject &other);
CFHashCode hash();
//
// Clean up a SecCodeSigner
//
-SecCodeSigner::~SecCodeSigner() throw()
+SecCodeSigner::~SecCodeSigner() _NOEXCEPT
try {
delete mLimitedAsync;
} catch (...) {
//
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);
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;
//
// Clean up a SecRequirement object
//
-SecRequirement::~SecRequirement() throw()
+SecRequirement::~SecRequirement() _NOEXCEPT
try {
::free((void *)mReq);
} catch (...) {
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();
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);
#include "cskernel.h"
#include <security_utilities/cfmunge.h>
#include <security_utilities/logging.h>
+#include <xpc/private.h>
using namespace CodeSigning;
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
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");
#include <Security/CSCommon.h>
#include <CoreFoundation/CFBase.h>
+#include <xpc/xpc.h>
#ifdef __cplusplus
extern "C" {
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
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
@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
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 */
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,
+
};
#if TARGET_OS_OSX
@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
/*!
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
| kSecCSCheckGatekeeperArchitectures
| kSecCSRestrictSymlinks
| kSecCSRestrictToAppLike
- | kSecCSUseSoftwareSigningCert
- | kSecCSValidatePEH
+ | kSecCSUseSoftwareSigningCert
+ | kSecCSValidatePEH
| kSecCSSingleThreaded
+ | kSecCSApplyEmbeddedPolicy
+ | kSecCSSkipRootVolumeExceptions
);
if (errors)
flags |= kSecCSFullReport; // internal-use flag
+#if !TARGET_OS_OSX
+ flags |= kSecCSApplyEmbeddedPolicy;
+#endif
+
SecPointer<SecStaticCode> 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
// the directory, we potentially skip resource validation even though the
// caller will go on to trust the signature
// <rdar://problem/6075501> 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
MacOSError::throwMe(errSecCSNoMainExecutable);
}
- auto_ptr<MachO> arch(execImage->architecture());
+ unique_ptr<MachO> arch(execImage->architecture());
if (arch.get() == NULL) {
MacOSError::throwMe(errSecCSNoMainExecutable);
}
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.
};
OSStatus SecStaticCodeCheckValidity(SecStaticCodeRef staticCode, SecCSFlags flags,
#include <dispatch/private.h>
#include <os/assumes.h>
#include <regex.h>
+#import <utilities/entitlements.h>
namespace Security {
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
{
CODESIGN_STATIC_CREATE(this, rep);
//
// Clean up a SecStaticCode object
//
-SecStaticCode::~SecStaticCode() throw()
+SecStaticCode::~SecStaticCode() _NOEXCEPT
try {
::free(const_cast<Requirement *>(mDesignatedReq));
delete mResourcesValidContext;
mNotarizationChecked = false;
mStaplingChecked = false;
mNotarizationDate = NAN;
-#if TARGET_OS_OSX
- mEvalDetails = NULL;
-#endif
mRep->flush();
#if TARGET_OS_OSX
DTRACK(CODESIGN_EVAL_STATIC_SIGNATURE, this, (char*)this->mainExecutablePath().c_str());
#if TARGET_OS_OSX
- // decode CMS and extract SecTrust for verification
- CFRef<CMSDecoderRef> 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<CFArrayRef> vf_policies(createVerificationPolicies());
- CFRef<CFArrayRef> ts_policies(createTimeStampingAndRevocationPolicies());
-
- 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;
- }
- 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<CFDataRef> hashAgilityV1;
- switch (OSStatus rc = CMSDecoderCopySignerAppleCodesigningHashAgility(cms, 0, &hashAgilityV1.aref())) {
- case noErr:
- if (hashAgilityV1) {
- CFRef<CFDictionaryRef> 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);
+ if (!(mValidationFlags & kSecCSApplyEmbeddedPolicy)) {
+ // decode CMS and extract SecTrust for verification
+ CFRef<CMSDecoderRef> 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<CFArrayRef> vf_policies(createVerificationPolicies());
+ CFRef<CFArrayRef> ts_policies(createTimeStampingAndRevocationPolicies());
+
+ 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;
+ }
+ Security::Syslog::error("CMSDecoderCopySignerStatus failed with %s error (%d)",
+ reason, (int)status);
+ 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<CFDictionaryRef> hashAgilityV2;
- switch (OSStatus rc = CMSDecoderCopySignerAppleCodesigningHashAgilityV2(cms, 0, &hashAgilityV2.aref())) {
+ // retrieve auxiliary v1 data bag and verify against current state
+ CFRef<CFDataRef> 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<CFDictionaryRef> 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);
+ }
- /* 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;
+ // retrieve auxiliary v2 data bag and verify against current state
+ CFRef<CFDictionaryRef> 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);
}
- CFRef<CFNumberRef> key = makeCFNumber(int(tag));
- CFRef<CFDataRef> entryCdhash;
- entryCdhash = (CFDataRef)CFDictionaryGetValue(hashAgilityV2, (void*)key.get());
-
- CodeDirectory const *cd = (CodeDirectory const*)CFDataGetBytePtr(entry.second);
- CFRef<CFDataRef> ourCdhash = cd->cdhash(false); // Untruncated cdhash!
- if (!CFEqual(entryCdhash, ourCdhash)) {
- 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<CFNumberRef> key = makeCFNumber(int(tag));
+ CFRef<CFDataRef> entryCdhash;
+ entryCdhash = (CFDataRef)CFDictionaryGetValue(hashAgilityV2, (void*)key.get());
+
+ CodeDirectory const *cd = (CodeDirectory const*)CFDataGetBytePtr(entry.second);
+ CFRef<CFDataRef> ourCdhash = cd->cdhash(false); // Untruncated cdhash!
+ if (!CFEqual(entryCdhash, ourCdhash)) {
+ MacOSError::throwMe(errSecCSSignatureFailed);
+ }
+
+ if (entry.first == this->hashAlgorithm()) {
+ foundOurs = true;
+ }
}
- 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);
+ }
- /* 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 */
+ // 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);
- }
-
- // 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 (mValidationFlags & kSecCSNoNetworkAccess) {
- MacOSError::check(SecTrustSetNetworkFetchAllowed(mTrust,false)); // no network?
- }
- MacOSError::check(SecTrustSetKeychainsAllowed(mTrust, false));
+ // 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);
+ }
- CSSM_APPLE_TP_ACTION_DATA actionData = {
- CSSM_APPLE_TP_ACTION_VERSION, // version of data structure
- 0 // action flags
- };
+ // set up the environment for SecTrust
+ if (mValidationFlags & kSecCSNoNetworkAccess) {
+ MacOSError::check(SecTrustSetNetworkFetchAllowed(mTrust,false)); // no network?
+ }
+ MacOSError::check(SecTrustSetKeychainsAllowed(mTrust, false));
- 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
- }
+ CSSM_APPLE_TP_ACTION_DATA actionData = {
+ CSSM_APPLE_TP_ACTION_VERSION, // version of data structure
+ 0 // action flags
+ };
- for (;;) { // at most twice
- MacOSError::check(SecTrustSetParameters(mTrust,
- CSSM_TP_ACTION_DEFAULT, CFTempData(&actionData, sizeof(actionData))));
+ 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
+ }
- // evaluate trust and extract results
- 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<CFStringRef> 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<CFStringRef> teamIDFromCD = CFStringCreateWithCString(NULL, teamID(), kCFStringEncodingUTF8);
- if (!teamIDFromCD) {
- Security::Syslog::error("Could not get team identifier (%s)", teamID());
- MacOSError::throwMe(errSecCSInvalidTeamIdentifier);
+ 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<CFStringRef> 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 (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);
+ if (teamIDFromCert) {
+ CFRef<CFStringRef> 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
+ 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 (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<CFArrayRef> 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);
+ 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<CFArrayRef> 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);
+ }
}
- 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;
}
- return actionData.ActionFlags & CSSM_TP_ACTION_ALLOW_EXPIRED;
- }
-#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<CFDictionaryRef> attrs;
- CFRef<CFArrayRef> 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<CFDataRef> hashBag;
- hashBag = CFDataRef(CFDictionaryGetValue(attrs, kSecCMSHashAgility));
- if (hashBag) {
- CFRef<CFDictionaryRef> hashDict = makeCFDictionaryFrom(hashBag);
- CFArrayRef cdList = CFArrayRef(CFDictionaryGetValue(hashDict, CFSTR("cdhashes")));
- CFArrayRef myCdList = this->cdHashes();
- if (cdList == NULL || !CFEqual(cdList, myCdList))
- MacOSError::throwMe(errSecCSSignatureFailed);
- }
+ } 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 :-)
- /*
- * 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);
+ CFRef<CFDictionaryRef> attrs;
+ CFRef<CFArrayRef> vf_policies(createVerificationPolicies());
- return false; // XXX: Not checking for expired certs
-#endif
+ // 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<CFDataRef> hashBag;
+ hashBag = CFDataRef(CFDictionaryGetValue(attrs, kSecCMSHashAgility));
+ if (hashBag) {
+ CFRef<CFDictionaryRef> 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
+ */
+ mCertChain.take(copyCertChain(mTrust));
+
+ // Did we implicitly trust the signer?
+ mTrustedSigningCertChain = (trustResult == kSecTrustResultUnspecified || trustResult == kSecTrustResultProceed);
+
+ return false; // XXX: Not checking for expired certs
+ }
}
#if TARGET_OS_OSX
return makeCFArray(1, ssRef.get());
}
#if TARGET_OS_OSX
+ if (mValidationFlags & kSecCSApplyEmbeddedPolicy) {
+ CFRef<SecPolicyRef> iOSRef = SecPolicyCreateiPhoneApplicationSigning();
+ return makeCFArray(1, iOSRef.get());
+ }
+
CFRef<SecPolicyRef> core;
MacOSError::check(SecPolicyCopy(CSSM_CERT_X_509v3,
&CSSMOID_APPLE_TP_CODE_SIGNING, &core.aref()));
}
+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.
}
if (doit) {
+ string root = cfStringRelease(copyCanonicalPath());
+ bool itemIsOnRootFS = isOnRootFilesystem(root.c_str());
+ bool requestForcedValidation = (mValidationFlags & kSecCSSkipRootVolumeExceptions);
+ bool useRootFSPolicy = itemIsOnRootFS && !requestForcedValidation;
+
+ secinfo("staticCode", "performing resource validation for %s (%d, %d, %d)", root.c_str(),
+ itemIsOnRootFS, requestForcedValidation, useRootFSPolicy);
+
if (mLimitedAsync == NULL) {
bool runMultiThreaded = ((flags & kSecCSSingleThreaded) == kSecCSSingleThreaded) ? false :
(diskRep()->fd().mediumType() == kIOPropertyMediumTypeSolidStateKey);
// 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;
bool isSymlink = (ent->fts_info == FTS_SL);
void (^validate)() = ^{
- validateResource(files, relpath, isSymlink, *mResourcesValidContext, flags, version);
+ bool needsValidation = true;
+
+ if (useRootFSPolicy) {
+ CFRef<CFURLRef> itemURL = makeCFURL(relpath, false, resourceBase());
+ string itemPath = cfString(itemURL);
+ if (isOnRootFilesystem(itemPath.c_str())) {
+ 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();
};
});
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
//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)));
#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<CFMutableDictionaryRef> tempEntitlements = makeCFMutableDictionary(entdict);
+ updateCatalystEntitlements(tempEntitlements);
+ CFRef<CFDictionaryRef> 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 (...) { }
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) {
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) {
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);
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));
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;
// signature verification outcome (mTrust == NULL => not done yet)
CFRef<SecTrustRef> mTrust; // outcome of crypto validation (valid or not)
CFRef<CFArrayRef> mCertChain;
-#if TARGET_OS_OSX
- CSSM_TP_APPLE_EVIDENCE_INFO *mEvalDetails;
-#else
bool mTrustedSigningCertChain;
-#endif
};
// 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;
{ "enforcement", kSecCodeSignatureEnforcement, true },
{ "library-validation", kSecCodeSignatureLibraryValidation, true },
{ "runtime", kSecCodeSignatureRuntime, true },
+ { "linker-signed", kSecCodeSignatureLinkerSigned, true },
{ NULL }
};
//
// We need a nothrow destructor
//
-CSError::~CSError() throw ()
+CSError::~CSError() _NOEXCEPT
{ }
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
{
if (ProcessCode *guest = dynamic_cast<ProcessCode *>(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
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; }
#include <security_asn1/SecAsn1Templates.h>
#include <Security/SecCertificatePriv.h>
#include <Security/SecCertificate.h>
+#include <Security/SecPolicyPriv.h>
#include <utilities/SecAppleAnchorPriv.h>
#include <utilities/SecInternalReleasePriv.h>
#include "requirement.h"
#include <security_utilities/hashing.h>
#include <security_utilities/debugging.h>
#include <security_utilities/errors.h>
+#include <sys/mount.h>
#include <sys/utsname.h>
+#include "debugging.h"
extern "C" {
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
}
//
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.
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;
}
}
}
+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);
+}
+
} // end namespace CodeSigning
} // end namespace Security
Dispatch::Semaphore *mResourceSemaphore;
};
+// Check if the path is on the root filesystem, protected by the OS.
+bool isOnRootFilesystem(const char *path);
} // end namespace CodeSigning
#include <security_utilities/logging.h>
#include "dirscanner.h"
+#include <sstream>
+
namespace Security {
namespace CodeSigning {
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
}
}
// machorep - DiskRep mix-in for handling Mach-O main executables
//
#include "machorep.h"
+#include "notarization.h"
#include "StaticCode.h"
#include "reqmaker.h"
#include <security_utilities/logging.h>
if (ctx->offset)
mExecutable = new Universal(fd(), (size_t)ctx->offset, ctx->size);
else if (ctx->arch) {
- auto_ptr<Universal> full(new Universal(fd()));
+ unique_ptr<Universal> full(new Universal(fd()));
mExecutable = new Universal(fd(), full->archOffset(ctx->arch), full->archLength(ctx->arch));
} else
mExecutable = new Universal(fd());
void MachORep::prepareForSigning(SigningContext &context)
{
if (context.digestAlgorithms().empty()) {
- auto_ptr<MachO> macho(mainExecutableImage()->architecture());
+ unique_ptr<MachO> macho(mainExecutableImage()->architecture());
uint32_t limit = 0;
switch (macho->platform()) {
size_t MachORep::signingLimit()
{
- auto_ptr<MachO> macho(mExecutable->architecture());
+ unique_ptr<MachO> 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> macho(arch ? mExecutable->architecture(*arch) : mExecutable->architecture());
+ unique_ptr<MachO> macho(arch ? mExecutable->architecture(*arch) : mExecutable->architecture());
if (!needsExecSeg(*macho)) {
return 0;
size_t MachORep::execSegLimit(const Architecture *arch)
{
- auto_ptr<MachO> macho(arch ? mExecutable->architecture(*arch) : mExecutable->architecture());
+ unique_ptr<MachO> macho(arch ? mExecutable->architecture(*arch) : mExecutable->architecture());
if (!needsExecSeg(*macho)) {
return 0;
//
CFDataRef MachORep::identification()
{
- std::auto_ptr<MachO> macho(mainExecutableImage()->architecture());
+ std::unique_ptr<MachO> macho(mainExecutableImage()->architecture());
return identificationFor(macho.get());
}
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) {
EmbeddedSignatureBlob *MachORep::signingData()
{
if (!mSigningData) { // fetch and cache
- auto_ptr<MachO> macho(mainExecutableImage()->architecture());
+ unique_ptr<MachO> macho(mainExecutableImage()->architecture());
if (macho.get())
if (const linkedit_data_command *cs = macho->findCodeSignature()) {
size_t offset = macho->flip(cs->dataoff);
{
CFRef<CFDataRef> info;
try {
- auto_ptr<MachO> macho(mainExecutableImage()->architecture());
+ unique_ptr<MachO> macho(mainExecutableImage()->architecture());
if (const section *sect = macho->findSection("__TEXT", "__info_plist")) {
if (macho->is64()) {
const section_64 *sect64 = reinterpret_cast<const section_64 *>(sect);
CFDictionaryRef MachORep::diskRepInformation()
{
- auto_ptr<MachO> macho (mainExecutableImage()->architecture());
+ unique_ptr<MachO> macho (mainExecutableImage()->architecture());
CFRef<CFDictionaryRef> info;
uint32_t platform = 0;
Requirement *MachORep::libraryRequirements(const Architecture *arch, const SigningContext &ctx)
{
- auto_ptr<MachO> macho(mainExecutableImage()->architecture(*arch));
+ unique_ptr<MachO> macho(mainExecutableImage()->architecture(*arch));
Requirement::Maker maker;
Requirement::Maker::Chain chain(maker, opOr);
MacOSError::throwMe(errSecCSInternalError);
}
+void MachORep::registerStapledTicket()
+{
+ CFRef<CFDataRef> data = NULL;
+ if (mSigningData) {
+ data.take(mSigningData->component(cdTicketSlot));
+ registerStapledTicketInMachO(data);
+ }
+}
} // end namespace CodeSigning
} // end namespace Security
void flush(); // flush cache
static bool candidate(UnixPlusPlus::FileDesc &fd);
+ void registerStapledTicket();
public:
static CFDataRef identificationFor(MachO *macho);
registerStapledTicketWithSystem(ticketData);
}
+void
+registerStapledTicketInMachO(CFDataRef ticketData)
+{
+ if (ticketData == NULL) {
+ return;
+ }
+ secinfo("notarization", "successfully found stapled ticket in MachO");
+ registerStapledTicketWithSystem(ticketData);
+}
+
}
}
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
xpc_release(request);
xpc_release(conn);
- if (!mBundleURL)
+ if (!mBundleURL) {
MacOSError::throwMe(errSecCSNoSuchCode);
-
- mDataFetched = true;
+ }
+
+ mDataFetched = true;
}
#include <sys/csr.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOCFUnserialize.h>
+#include <libDER/oids.h>
#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 <security/mac.h>
+
+#define AMFI_INTF_CD_HASH_LEN 20
+#endif
+
namespace Security {
namespace CodeSigning {
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)
// 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<CFStringRef> 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<CFStringRef> 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);
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, ^{
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<CFDataRef> 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;
}
// 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;
bool verifyAnchor(SecCertificateRef cert, const unsigned char *digest);
bool appleSigned();
bool appleAnchored();
+ bool inTrustCache();
bool trustedCerts();
bool trustedCert(int slot);
if (CFRef<CFDataRef> 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)
entitlements = state.mEntitlementData;
if (!entitlements && (inherit & kSecCodeSignerPreserveEntitlements))
entitlements = code->component(cdEntitlementSlot);
-
- generateEntitlementDER = signingFlags() & kSecCSSignGenerateEntitlementDER;
// work out the CodeDirectory flags word
bool haveCdFlags = false;
if (!(signingFlags() & kSecCSSignV1)) {
CFCopyRef<CFDictionaryRef> rules2 = cfget<CFDictionaryRef>(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<CFDictionaryRef>("{+%O"
+ rules2.take(cfmake<CFDictionaryRef>("{+%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;
if (state.mPreserveAFSC)
writer->setPreserveAFSC(state.mPreserveAFSC);
- auto_ptr<ArchEditor> editor(state.mDetached
+ unique_ptr<ArchEditor> editor(state.mDetached
? static_cast<ArchEditor *>(new BlobEditor(*fat, *this))
: new MachOEditor(writer, *fat, this->digestAlgorithms(), rep->mainExecutablePath()));
assert(editor->count() > 0);
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;
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);
});
}
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)
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);
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);
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
//
struct Arch : public BlobWriter {
Architecture architecture; // our architecture
- auto_ptr<MachO> source; // Mach-O object to be signed
+ unique_ptr<MachO> source; // Mach-O object to be signed
std::map<CodeDirectory::HashAlgorithm, RefPointer<CodeDirectory::Builder> > cdBuilders;
InternalRequirements ireqs; // consolidated internal requirements
size_t blobSize; // calculated SuperBlob size
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);
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;
*************************************************************/
#include <stdio.h>
-#include<assert.h>
#include <math.h>
#include <stdlib.h>
#include "giants.h"
*************************************************************/
#include <stdio.h>
-#include<assert.h>
#include <math.h>
#include"giants.h"
#include "tools.h"
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
*/
//
void *Attachment::upcallMalloc(CSSM_HANDLE handle, size_t size)
{
- BEGIN_API
+ BEGIN_API_NO_METRICS
return HandleObject::find<Attachment>(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<Attachment>(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<Attachment>(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<Attachment>(handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE).calloc(size, num);
END_API1(NULL)
}
CSSM_RETURN Attachment::upcallCcToHandle(CSSM_CC_HANDLE handle,
CSSM_MODULE_HANDLE *modHandle)
{
- BEGIN_API
+ BEGIN_API_NO_METRICS
Required(modHandle) = HandleObject::find<HandleContext>((CSSM_HANDLE)handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE).attachment.handle();
END_API(CSP)
}
CSSM_FUNC_NAME_ADDR_PTR FunctionTable,
uint32 NumFunctions)
{
- BEGIN_API
+ BEGIN_API_NO_METRICS
Attachment &attachment = HandleObject::find<Attachment>(handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE);
Required(guid) = attachment.myGuid();
Required(version) = attachment.mVersion;
#include "module.h"
#include <security_utilities/globalizer.h>
#include <security_cdsa_utilities/cssmbridge.h>
-
+#include "LegacyAPICounts.h"
//
// We currently use exactly one instance of CssmManager.
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:
* (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))
/* 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,
CSSM_SERVICE_TYPE ServiceType,
CSSM_MODULE_EVENT EventType)
{
- BEGIN_API
+ BEGIN_API_NO_METRICS
static_cast<Module *>(Context)->spiEvent(EventType,
Guid::required(ModuleGuid),
SubserviceId,
#include <Security/cssmkrapi.h>
#include <Security/cssmkrspi.h>
#include <security_cdsa_utilities/cssmbridge.h>
+#include "LegacyAPICounts.h"
//
uint32 indexOffset = mTableSection.at(indexSectionOffset + (i + 2) * AtomSize);
ReadSection indexSection(mTableSection.subsection(indexOffset));
- auto_ptr<DbConstIndex> index(new DbConstIndex(*this, indexSection));
+ unique_ptr<DbConstIndex> index(new DbConstIndex(*this, indexSection));
mIndexMap.insert(ConstIndexMap::value_type(index->indexId(), index.get()));
index.release();
}
{
modifyTable();
- auto_ptr<WriteSection> aWriteSection(new WriteSection());
+ unique_ptr<WriteSection> aWriteSection(new WriteSection());
getMetaRecord().packRecord(*aWriteSection, inAttributes, inData);
uint32 aRecordNumber = nextRecordNumber();
#endif
// Update the actual packed record.
- auto_ptr<WriteSection> aDbRecord(new WriteSection());
+ unique_ptr<WriteSection> aDbRecord(new WriteSection());
getMetaRecord().updateRecord(anOldDbRecord, *aDbRecord,
CssmDbRecordAttributeData::overlay(inAttributes), inData, inModifyMode);
Table::ConstIndexMap::const_iterator it;
for (it = mTable->mIndexMap.begin(); it != mTable->mIndexMap.end(); it++) {
- auto_ptr<DbMutableIndex> mutableIndex(new DbMutableIndex(*it->second));
+ unique_ptr<DbMutableIndex> mutableIndex(new DbMutableIndex(*it->second));
mIndexMap.insert(MutableIndexMap::value_type(it->first, mutableIndex.get()));
mutableIndex.release();
}
if (it == mIndexMap.end()) {
// create the new index
- auto_ptr<DbMutableIndex> index(new DbMutableIndex(metaRecord, indexId, isUniqueIndex));
+ unique_ptr<DbMutableIndex> index(new DbMutableIndex(metaRecord, indexId, isUniqueIndex));
it = mIndexMap.insert(MutableIndexMap::value_type(indexId, index.get())).first;
index.release();
}
// XXX Set the size boundary on aTableSection.
const ReadSection aTableSection =
aSchemaSection.subsection(aTableOffset);
- auto_ptr<Table> aTable(new Table(aTableSection));
+ unique_ptr<Table> aTable(new Table(aTableSection));
Table::Id aTableId = aTable->getMetaRecord().dataRecordType();
mTableMap.insert(TableMap::value_type(aTableId, aTable.get()));
aTable.release();
uint32 anAttributeId = aRecordData[1];
uint32 anAttributeNameFormat = aRecordData[2];
uint32 anAttributeFormat = aRecordData[5];
- auto_ptr<string> aName;
+ unique_ptr<string> aName;
const CssmData *aNameID = NULL;
if (aRecordData[3].size() == 1)
if (aRecordData[3].format() != CSSM_DB_ATTRIBUTE_FORMAT_STRING)
CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
- auto_ptr<string> aName2(new string(static_cast<string>(aRecordData[3])));
- aName = aName2;
+ unique_ptr<string> aName2(new string(static_cast<string>(aRecordData[3])));
+ aName = std::move(aName2);
}
if (aRecordData[4].size() == 1)
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
mDbVersion->mTableMap.end();
for (; anIt != anEnd; ++anIt)
{
- auto_ptr<ModifiedTable> aTable(new ModifiedTable(anIt->second));
+ unique_ptr<ModifiedTable> aTable(new ModifiedTable(anIt->second));
mModifiedTableMap.insert(ModifiedTableMap::value_type(anIt->first,
aTable.get()));
aTable.release();
ModifiedTable *
DbModifier::createTable(MetaRecord *inMetaRecord)
{
- auto_ptr<MetaRecord> aMetaRecord(inMetaRecord);
- auto_ptr<ModifiedTable> aModifiedTable(new ModifiedTable(inMetaRecord));
+ unique_ptr<MetaRecord> aMetaRecord(inMetaRecord);
+ unique_ptr<ModifiedTable> aModifiedTable(new ModifiedTable(inMetaRecord));
// Now that aModifiedTable is fully constructed it owns inMetaRecord
aMetaRecord.release();
}
void
-DbModifier::rollback() throw()
+DbModifier::rollback() _NOEXCEPT
{
// This will destroy the AtomicTempFile if we have one causing it to rollback.
mAtomicTempFile = NULL;
{
// XXX: register Cursor with DbContext and have DbContext call
// dataAbortQuery for all outstanding Query objects on close.
- auto_ptr<Cursor> aCursor(mDbModifier.createCursor(inQuery));
+ unique_ptr<Cursor> aCursor(mDbModifier.createCursor(inQuery));
Table::Id aTableId;
RecordId aRecordId;
CssmData *inoutData,
CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord)
{
- auto_ptr<Cursor> aCursor(&HandleObject::find<Cursor>(inResultsHandle, CSSMERR_DL_INVALID_RESULTS_HANDLE));
+ unique_ptr<Cursor> aCursor(&HandleObject::find<Cursor>(inResultsHandle, CSSMERR_DL_INVALID_RESULTS_HANDLE));
Table::Id aTableId;
RecordId aRecordId;
RecordId &recordId);
private:
- auto_ptr<DbQueryKey> mQueryKey;
+ unique_ptr<DbQueryKey> mQueryKey;
const Table &mTable;
const DbConstIndex *mIndex;
Allocator &inAllocator,
RecordId &recordId);
private:
- auto_ptr<CssmAutoQuery> mQuery;
+ unique_ptr<CssmAutoQuery> mQuery;
DbVersion::const_iterator mTableIterator;
- auto_ptr<Cursor> mCursor;
+ unique_ptr<Cursor> mCursor;
};
//
void deleteDatabase();
void commit();
- void rollback() throw();
+ void rollback() _NOEXCEPT;
// Record changing members
void deleteRecord(Table::Id inTableId, const RecordId &inRecordId);
#include <copyfile.h>
#include <sandbox.h>
#include <set>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#define kAtomicFileMaxBlockSize INT_MAX
{
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());
}
// 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)
{
-void AtomicLockedFile::unlock() throw()
+void AtomicLockedFile::unlock() _NOEXCEPT
{
mFileLocker->unlock();
}
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.
private:
void lock(mode_t mode = (S_IRUSR|S_IRGRP|S_IROTH) /* === 0444 */);
- void unlock() throw();
+ void unlock() _NOEXCEPT;
private:
FileLocker* mFileLocker;
for (uint32 i = 0; i < mKey.mNumKeyValues; i++) {
const MetaAttribute &metaAttribute = *mKey.mIndex.mAttributes[i];
- auto_ptr<DbValue> value1(metaAttribute.createValue(*key1, valueOffset1));
- auto_ptr<DbValue> value2(metaAttribute.createValue(*key2, valueOffset2));
+ unique_ptr<DbValue> value1(metaAttribute.createValue(*key1, valueOffset1));
+ unique_ptr<DbValue> value2(metaAttribute.createValue(*key2, valueOffset2));
if (metaAttribute.evaluate(value1.get(), value2.get(), CSSM_DB_LESS_THAN))
return true;
for (uint32 i = 0; i < numAttributes; i++) {
const MetaAttribute &metaAttribute = *mIndex.mAttributes[i];
- auto_ptr<DbValue> value1(metaAttribute.createValue(mKeySection.subsection(mKeyRange),
+ unique_ptr<DbValue> value1(metaAttribute.createValue(mKeySection.subsection(mKeyRange),
valueOffset1));
- auto_ptr<DbValue> value2(metaAttribute.createValue(other.mKeySection.subsection(other.mKeyRange),
+ unique_ptr<DbValue> value2(metaAttribute.createValue(other.mKeySection.subsection(other.mKeyRange),
valueOffset2));
if (metaAttribute.evaluate(value1.get(), value2.get(), CSSM_DB_LESS_THAN))
size_t aNewCapacity = max(n, inNewCapacity);
mAddress = reinterpret_cast<uint8 *>(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;
}
uint32 at(uint32 inOffset) const
{
- if (inOffset > mLength)
+ if (CheckUInt32Add(inOffset, AtomSize) > mLength)
{
CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
}
+++ /dev/null
-.
\ No newline at end of file
CFRetain(mCertificateRef);
}
-CertificateValues::~CertificateValues() throw()
+CertificateValues::~CertificateValues() _NOEXCEPT
{
if (mCertificateProperties)
CFRelease(mCertificateProperties);
public:
CertificateValues(SecCertificateRef certificateRef);
- virtual ~CertificateValues() throw();
+ virtual ~CertificateValues() _NOEXCEPT;
static CFStringRef remapLabelToKey(CFStringRef label);
CFArrayRef copyPropertyValues(CFErrorRef *error);
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.
setupAttrs();
}
-ExtendedAttribute::~ExtendedAttribute() throw()
+ExtendedAttribute::~ExtendedAttribute() _NOEXCEPT
{
}
ExtendedAttribute(ExtendedAttribute &extendedAttribute);
- virtual ~ExtendedAttribute() throw();
+ virtual ~ExtendedAttribute() _NOEXCEPT;
virtual PrimaryKey add(Keychain &keychain);
bool operator == (const ExtendedAttribute &other) const;
}
}
-Identity::~Identity() throw()
+Identity::~Identity() _NOEXCEPT
{
if (mPrivateKey)
CFRelease(mPrivateKey);
Identity(const SecKeyRef privateKey,
const SecPointer<Certificate> &certificate);
Identity(const StorageManager::KeychainList &keychains, const SecPointer<Certificate> &certificate);
- virtual ~Identity() throw();
+ virtual ~Identity() _NOEXCEPT;
SecPointer<KeyItem> privateKey() const;
SecPointer<Certificate> certificate() const;
}
}
-IdentityCursorPolicyAndID::~IdentityCursorPolicyAndID() throw()
+IdentityCursorPolicyAndID::~IdentityCursorPolicyAndID() _NOEXCEPT
{
if (mPolicy) {
CFRelease(mPolicy);
mKeyCursor->add(CSSM_DB_EQUAL, KeySchema::Unwrap, true);
}
-IdentityCursor::~IdentityCursor() throw()
+IdentityCursor::~IdentityCursor() _NOEXCEPT
{
}
StLock<Mutex>_(mMutex);
CFDataRef entryValue = nil;
- auto_ptr<Dictionary> identDict;
+ unique_ptr<Dictionary> identDict;
Dictionary* d = Dictionary::CreateDictionary("com.apple.security.systemidentities", Dictionary::US_System);
if (d)
{
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> &identity);
CFDataRef pubKeyHashForSystemIdentity(CFStringRef domain);
{
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> &identity);
virtual void findPreferredIdentity();
void ItemImpl::encodeAttributes(CssmOwnedData &attributeBlob) {
// Sometimes we don't have our attributes. Find them.
- auto_ptr<DbAttributes> dbAttributes(getCurrentAttributes());
+ unique_ptr<DbAttributes> dbAttributes(getCurrentAttributes());
encodeAttributesFromDictionary(attributeBlob, dbAttributes.get());
}
}
void ItemImpl::computeDigest(CssmOwnedData &sha2) {
- auto_ptr<DbAttributes> dbAttributes(getCurrentAttributes());
+ unique_ptr<DbAttributes> dbAttributes(getCurrentAttributes());
ItemImpl::computeDigestFromDictionary(sha2, dbAttributes.get());
}
return true;
}
- auto_ptr<DbAttributes> dbAttributes(getCurrentAttributes());
+ unique_ptr<DbAttributes> dbAttributes(getCurrentAttributes());
return checkIntegrityFromDictionary(aclBearer, dbAttributes.get());
}
// them.
AclEntryInfo &info = aclInfos.at(0);
- auto_ptr<ACL> acl(new ACL(info, Allocator::standard()));
+ unique_ptr<ACL> acl(new ACL(info, Allocator::standard()));
for(int i = 1; i < aclInfos.count(); i++) {
secnotice("integrity", "*** DUPLICATE INTEGRITY ACL, something has gone wrong");
} 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<CssmClient::DbAttributes> primaryKeyAttrs;
+ unique_ptr<CssmClient::DbAttributes> primaryKeyAttrs;
if(cssme.error == CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA) {
secnotice("integrity", "possible duplicate, trying to delete invalid items");
// 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_ptr<DbAttributes>dbDupAttributes (new DbAttributes(kc->database(), 1));
+ unique_ptr<DbAttributes>dbDupAttributes (new DbAttributes(kc->database(), 1));
fillDbAttributesFromSchema(*dbDupAttributes, recordType, kc);
// Occasionally this cursor won't return the item attributes (for an unknown reason).
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();
// new item members
RefPointer<CssmDataContainer> mData;
- auto_ptr<CssmClient::DbAttributes> mDbAttributes;
+ unique_ptr<CssmClient::DbAttributes> mDbAttributes;
SecPointer<Access> mAccess;
// db item members
}
}
-KCCursorImpl::~KCCursorImpl() throw()
+KCCursorImpl::~KCCursorImpl() _NOEXCEPT
{
}
KCCursorImpl(const StorageManager::KeychainList &searchList, const SecKeychainAttributeList *attrList);
public:
- virtual ~KCCursorImpl() throw();
+ virtual ~KCCursorImpl() _NOEXCEPT;
bool next(Item &item);
bool mayDelete();
}
}
-KeyItem::operator CFTypeRef() const throw()
+KeyItem::operator CFTypeRef() const _NOEXCEPT
{
StMaybeLock<Mutex> _(this->getMutexForObject());
pubKeyHash.set(*pubKeyHashData);
passThrough.allocator().free(pubKeyHashData);
- auto_ptr<string> privDescription;
- auto_ptr<string> pubDescription;
+ unique_ptr<string> privDescription;
+ unique_ptr<string> pubDescription;
try {
privDescription.reset(new string(initialAccess->promptDescription()));
pubDescription.reset(new string(initialAccess->promptDescription()));
csp.allocator().free(cssmData->Data);
csp.allocator().free(cssmData);
- auto_ptr<string>privDescription;
- auto_ptr<string>pubDescription;
+ unique_ptr<string>privDescription;
+ unique_ptr<string>pubDescription;
try {
privDescription.reset(new string(initialAccess->promptDescription()));
pubDescription.reset(new string(initialAccess->promptDescription()));
// 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);
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);
--- /dev/null
+/*
+ * 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 LegacyAPICounts_h
+#define LegacyAPICounts_h
+
+#include <stdbool.h>
+#include <dispatch/dispatch.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void countLegacyAPI(dispatch_once_t* token, const char* api);
+void setCountLegacyAPIEnabledForThread(bool value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LegacyAPICounts_h */
--- /dev/null
+/*
+ * 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 <os/feature_private.h>
+#import <sys/codesign.h>
+
+#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);
+ }
+
+ // security tool doesn't have entitlements, I wonder if there are more.
+ if (!identifier) {
+ identifier = CFBridgingRelease(SecTaskCopySigningIdentifier(task, NULL));
+ }
+
+ 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;
+}
+
+#pragma mark - SPI
+
+void setCountLegacyAPIEnabledForThread(bool value) {
+ [[NSThread currentThread] threadDictionary][@"countLegacyAPIEnabled"] = value ? @YES : @NO;
+}
+
+void countLegacyAPI(dispatch_once_t* token, const char* api) {
+ static NSString* identifier;
+ static BOOL shouldCount;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ identifier = applicationIdentifierForSelf() ?: @"unknown";
+ shouldCount = os_feature_enabled(Security, LegacyAPICounts);
+ });
+
+ 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<NSString *,NSObject *> * _Nonnull{
+ return @{
+ @"app" : identifier,
+ @"api" : apiStringObject,
+ };
+ }];
+ });
+}
-PasswordImpl::~PasswordImpl() throw()
+PasswordImpl::~PasswordImpl() _NOEXCEPT
{
}
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);
secinfo("policy", "Policy() this %p", this);
}
-Policy::~Policy() throw()
+Policy::~Policy() _NOEXCEPT
{
secinfo("policy", "~Policy() this %p", this);
}
Policy(TP supportingTp, const CssmOid &policyOid);
public:
- virtual ~Policy() throw();
+ virtual ~Policy() _NOEXCEPT;
TP &tp() { return mTp; }
const TP &tp() const { return mTp; }
//
// Destroy
//
-PolicyCursor::~PolicyCursor() throw()
+PolicyCursor::~PolicyCursor() _NOEXCEPT
{
}
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> &policy);
bool oidProvided() { return mOidGiven; }
#include "SecBridge.h"
+#include "LegacyAPICounts.h"
+
// Forward reference
/*!
@function GetACLAuthorizationTagFromString
SecKeychainPromptSelector promptSelector,
SecACLRef *newAcl)
{
+ COUNTLEGACYAPI
CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector;
cdsaPromptSelector.version = CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION;
cdsaPromptSelector.flags = promptSelector;
CFStringRef *description,
SecKeychainPromptSelector *promptSelector)
{
+ COUNTLEGACYAPI
CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector;
memset(&cdsaPromptSelector, 0, sizeof(cdsaPromptSelector));
OSStatus err = errSecSuccess;
CFStringRef description,
SecKeychainPromptSelector promptSelector)
{
+ COUNTLEGACYAPI
CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector;
cdsaPromptSelector.version = CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION;
cdsaPromptSelector.flags = promptSelector;
CFArrayRef SecACLCopyAuthorizations(SecACLRef acl)
{
+ COUNTLEGACYAPI
CFArrayRef result = NULL;
if (NULL == acl)
{
OSStatus SecACLUpdateAuthorizations(SecACLRef acl, CFArrayRef authorizations)
{
+ COUNTLEGACYAPI
if (NULL == acl || NULL == authorizations)
{
return errSecParam;
#include <utilities/SecCFWrappers.h>
+#include "LegacyAPICounts.h"
/* No restrictions. Permission to perform all operations on
the resource or available to an ACL 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 =
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;
CFArrayRef SecAccessCopyMatchingACLList(SecAccessRef accessRef, CFTypeRef authorizationTag)
{
+ COUNTLEGACYAPI
CFArrayRef result = NULL;
CSSM_ACL_AUTHORIZATION_TAG tag = GetACLAuthorizationTagFromString((CFStringRef)authorizationTag);
OSStatus err = SecAccessCopySelectedACLList(accessRef, tag, &result);
// Make a bundle instance using the URLRef.
secBundle = CFBundleCreate(kCFAllocatorDefault,bundleURL);
- if (!secBundle)
+ if (!secBundle) {
goto xit;
+ }
trustedAppListFileNameWithoutExtension =
CFStringCreateMutableCopy(NULL,CFStringGetLength(trustedAppListFileName),trustedAppListFileName);
// 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;
OSStatus SecAccessCreateWithTrustedApplications(CFStringRef trustedApplicationsPListPath, CFStringRef accessLabel, Boolean allowAny, SecAccessRef* returnedAccess)
{
+ COUNTLEGACYAPI
OSStatus err = errSecSuccess;
SecAccessRef accessToReturn=nil;
CFMutableArrayRef trustedApplications=nil;
@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
@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
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.
@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)
// 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)
#include <Security/SecKeychainPriv.h>
#include <security_keychain/KCUtilities.h>
#include <security_cdsa_utilities/cssmbridge.h>
+#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:
//
#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(); } \
//
#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) { \
//
#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); } \
#include <sys/param.h>
#include <syslog.h>
#include "CertificateValues.h"
+#include "LegacyAPICounts.h"
OSStatus SecCertificateGetCLHandle_legacy(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle);
extern CSSM_KEYUSE ConvertArrayToKeyUsage(CFArrayRef usage);
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;
}
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 } };
CssmData service(const_cast<char *>(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))
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
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);
CFStringRef name,
CFArrayRef keyUsage)
{
+ COUNTLEGACYAPI
CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage);
return SecCertificateSetPreference(certificate, name, keyUse, NULL);
}
+++ /dev/null
-/*
- * 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 <Security/SecCertificateBundle.h>
-
-#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);
-}
+++ /dev/null
-/*
- * 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 <Security/SecBase.h>
-#include <Security/cssmtype.h>
-#include <CoreFoundation/CFArray.h>
-
-#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_ */
#include <Security/SecIdentityPriv.h>
#include <Security/SecItem.h>
#include <Security/SecBase.h>
+#include <security_utilities/simulatecrash_assert.h>
using namespace Security;
using namespace KeychainCore;
#include <sys/param.h>
#include <syslog.h>
#include <os/activity.h>
+#include "LegacyAPICounts.h"
/* private function declarations */
OSStatus
SecCertificateRef certificate,
SecKeyRef privateKey)
{
+ COUNTLEGACYAPI
SecIdentityRef identityRef = NULL;
OSStatus __secapiresult;
SecCertificateRef __itemImplRef = NULL;
return identityRef;
}
-CFComparisonResult
-SecIdentityCompare(
- SecIdentityRef identity1,
- SecIdentityRef identity2,
- CFOptionFlags compareOptions)
-{
- if (!identity1 || !identity2)
- {
- if (identity1 == identity2)
- return kCFCompareEqualTo;
- else if (identity1 < identity2)
- return kCFCompareLessThan;
- else
- return kCFCompareGreaterThan;
- }
-
- try {
- SecPointer<Identity> id1(Identity::required(identity1));
- SecPointer<Identity> id2(Identity::required(identity2));
-
- if (id1 == id2)
- return kCFCompareEqualTo;
- else if (id1 < id2)
- return kCFCompareLessThan;
- else
- return kCFCompareGreaterThan;
- } catch(...)
- {}
-
- return kCFCompareGreaterThan;
-}
-
static
CFArrayRef _SecIdentityCopyPossiblePaths(
CFStringRef name)
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))
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<char *>(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,
CssmData service(const_cast<char *>(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))
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
return (status == errSecItemNotFound) ? errSecSuccess : status;
}
-
-static
-OSStatus _SecIdentityAddPreferenceItemWithName(
- SecKeychainRef keychainRef,
- SecIdentityRef identityRef,
- CFStringRef idString,
- SecKeychainItemRef *itemRef)
-{
- // 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<Certificate> 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<char *>(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<char *>(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<void *>(reinterpret_cast<const void *>(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_scope(activity);
- os_release(activity);
-
- OSStatus status = errSecInternalComponent;
- CFArrayRef names = _SecIdentityCopyPossiblePaths(idString);
- if (!names) {
- return status;
- }
-
- 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);
- }
- 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; }
- }
- 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; }
- }
- }
-
- 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> 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<char *>(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<void *>(reinterpret_cast<const void *>(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> certificate(static_cast<Certificate *>(certItem.get()));
- SecPointer<Identity> identity(new Identity(keychains, certificate));
- if (certItemRef)
- CFRelease(certItemRef);
-
- Required(identityRef) = identity->handle();
-
- END_SECAPI
-}
-
/*
* System Identity Support.
*/
os_release(activity);
StLock<Mutex> _(systemIdentityLock());
- auto_ptr<Dictionary> identDict;
+ unique_ptr<Dictionary> identDict;
/* get top-level dictionary - if not present, we're done */
Dictionary* d = Dictionary::CreateDictionary(IDENTITY_DOMAIN, Dictionary::US_System);
MacOSError::throwMe(errSecAuthFailed);
}
- auto_ptr<MutableDictionary> identDict;
+ unique_ptr<MutableDictionary> identDict;
MutableDictionary *d = MutableDictionary::CreateMutableDictionary(IDENTITY_DOMAIN, Dictionary::US_System);
if (d)
{
#include <os/activity.h>
#include "SecBridge.h"
-
+#include "LegacyAPICounts.h"
CFTypeID
SecIdentitySearchGetTypeID(void)
#include <string.h>
#include <ctype.h>
+#include <security_utilities/simulatecrash_assert.h>
+
/*
* Text parsing routines.
*
#include <Security/SecKeyPriv.h>
#include <security_cdsa_utils/cuCdsaUtils.h>
#include <openssl/pem.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include <Security/SecBase.h>
#define SecPkcs8Dbg(args...) secinfo("SecPkcs8", ## args)
#include <Security/SecTrustPriv.h>
#include "utilities/array_size.h"
#include "utilities/SecCFWrappers.h"
+#include "LegacyAPICounts.h"
#include <AssertMacros.h>
#include <syslog.h>
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,
//
// Note that we allocate *items if needed.
+ CFTypeRef localResult = NULL;
+
if (!item || !itemParams || !result)
return errSecParam;
CFArrayAppendValue(itemArray, itemRef);
}
else {
- *result = CFRetain((CFTypeRef)itemRef);
+ CFReleaseNull(localResult);
+ localResult = CFRetain((CFTypeRef)itemRef);
}
}
CFArrayAppendValue(itemArray, persistentRef);
}
else {
- *result = CFRetain(persistentRef);
+ CFReleaseNull(localResult);
+ localResult = CFRetain(persistentRef);
}
CFRelease(persistentRef);
}
CFArrayAppendValue(itemArray, dataRef);
}
else {
- *result = CFRetain(dataRef);
+ CFReleaseNull(localResult);
+ localResult = CFRetain(dataRef);
}
CFRelease(dataRef);
status = errSecSuccess;
CFArrayAppendValue(itemArray, dataRef);
}
else {
- *result = CFRetain(dataRef);
+ CFReleaseNull(localResult);
+ localResult = CFRetain(dataRef);
}
CFRelease(dataRef);
(void) SecKeychainItemFreeContent(NULL, data);
CFArrayAppendValue(itemArray, attrsDict);
}
else {
- *result = CFRetain(attrsDict);
+ CFReleaseNull(localResult);
+ localResult = CFRetain(attrsDict);
}
CFRelease(attrsDict);
}
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;
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,
else
*result = NULL;
+ setCountLegacyAPIEnabledForThread(false);
+
CFAllocatorRef allocator = CFGetAllocator(query);
CFIndex matchCount = 0;
CFMutableArrayRef itemArray = NULL;
}
_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
else if (result)
*result = NULL;
+ setCountLegacyAPIEnabledForThread(false);
+
CFAllocatorRef allocator = CFGetAllocator(attributes);
CFMutableArrayRef itemArray = NULL;
SecKeychainItemRef item = NULL;
*result = NULL;
}
_FreeSecItemParams(itemParams);
+ setCountLegacyAPIEnabledForThread(true);
return status;
}
CFRelease(results);
}
+ setCountLegacyAPIEnabledForThread(false);
+
OSStatus result = errSecSuccess;
CFIndex ix, count = CFArrayGetCount(items);
for (ix=0; ix < count; ix++) {
}
}
+ setCountLegacyAPIEnabledForThread(true);
+
if (items) {
CFRelease(items);
}
CFRelease(results);
}
+ setCountLegacyAPIEnabledForThread(false);
+
OSStatus result = errSecSuccess;
CFIndex ix, count = CFArrayGetCount(items);
for (ix=0; ix < count; ix++) {
}
}
+ setCountLegacyAPIEnabledForThread(true);
+
if (items)
CFRelease(items);
//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");
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 {
#include <Security/AuthorizationTagsPriv.h>
#include <Security/Authorization.h>
#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);
OSStatus
SecKeychainGetVersion(UInt32 *returnVers)
{
+ COUNTLEGACYAPI
if (!returnVers)
return errSecSuccess;
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_scope(activity);
- os_release(activity);
-
- RequiredParam(keychainRef)=globals().storageManager.make(pathName, false)->handle();
-
- 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_t activity = os_activity_create("SecKeychainOpen", 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 ();
+ RequiredParam(keychainRef)=globals().storageManager.make(pathName, 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);
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);
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);
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);
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);
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);
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);
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);
//
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);
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);
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);
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);
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);
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);
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);
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);
{
BEGIN_SECAPI
- RequiredParam(version);
+ RequiredParam(version);
*version = Keychain::optional(keychainRef)->database()->dbBlobVersion();
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);
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);
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);
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);
{
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);
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);
{
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);
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);
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);
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);
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);
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);
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);
OSStatus SecKeychainMakeFromFullPath(const char *fullPathName, SecKeychainRef *keychainRef)
{
BEGIN_SECAPI
- RequiredParam(fullPathName);
+
+ RequiredParam(fullPathName);
RequiredParam(keychainRef)=make(fullPathName)->handle();
END_SECAPI
}
OSStatus SecKeychainIsValid(SecKeychainRef keychainRef, Boolean* isValid)
{
BEGIN_SECAPI
- *isValid = false;
+
+ *isValid = false;
if (KeychainImpl::optional(keychainRef)->dlDbIdentifier().ssuid().guid() == gGuidAppleCSPDL)
*isValid = true;
END_SECAPI
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;
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);
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);
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);
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);
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);
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);
const CSSM_GUID *guid, uint32 subServiceType)
{
BEGIN_SECAPI
- RequiredParam(dbName);
+
+ RequiredParam(dbName);
StorageManager &smr = globals().storageManager;
smr.isInDomainList(domain, dbName, *guid, subServiceType);
END_SECAPI
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);
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);
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);
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();
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);
}
OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRef systemKeychainRef, CFStringRef username, CFStringRef password) {
+ COUNTLEGACYAPI
SecTrustedApplicationRef itemPath;
SecAccessRef ourAccessRef = NULL;
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);
OSStatus SecKeychainStoreUnlockKeyWithPubKeyHash(CFDataRef pubKeyHash, CFStringRef tokenID, CFDataRef wrapPubKeyHash,
SecKeychainRef userKeychain, CFStringRef password)
{
+ COUNTLEGACYAPI
CFRef<CFStringRef> pwd;
OSStatus result;
}
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<CFStringRef> 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;
}
-
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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);
/*
@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
@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 ----
/*!
@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
@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 ----
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
@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
@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 ----
/*!
@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
@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
@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
@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 ----
/*!
@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
@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 ----
/*!
+++ /dev/null
-/*
- * 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 <Security/SecKeychain.h>
-#include <Security/SecKeychainItem.h>
-#include <Security/SecAccess.h>
-#include <Security/SecAccessPriv.h>
-#include <Security/SecTrustedApplicationPriv.h>
-#include <Security/SecACL.h>
-#include <CoreFoundation/CoreFoundation.h>
-
-
-OSStatus SecKeychainAddIToolsPassword(SecKeychainRef __unused keychain,
- UInt32 __unused accountNameLength,
- const char * __unused accountName,
- UInt32 __unused passwordLength,
- const void * __unused passwordData,
- SecKeychainItemRef * __unused itemRef)
-{
- return errSecParam;
-}
#include "KCExceptions.h"
#include "Access.h"
#include "SecKeychainItemExtendedAttributes.h"
+#include "LegacyAPICounts.h"
extern "C" Boolean SecKeyIsCDSAKey(SecKeyRef ref);
SecKeychainItemGetTypeID(void)
{
BEGIN_SECAPI
-
return gTypes().ItemImpl.typeID;
END_SECAPI1(_kCFRuntimeNotATypeID)
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);
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);
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);
SecKeychainItemFreeAttributesAndData(SecKeychainAttributeList *attrList, void *data)
{
BEGIN_SECAPI
-
ItemImpl::freeAttributesAndData(attrList, data);
END_SECAPI
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);
OSStatus
SecKeychainItemCopyKeychain(SecKeychainItemRef itemRef, SecKeychainRef* keychainRef)
{
- BEGIN_SECKCITEMAPI
+ BEGIN_SECKCITEMAPI
// make sure this item has a keychain
Keychain kc = ItemImpl::required(__itemImplRef)->keychain();
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);
END_SECKCITEMAPI
}
-#if 0
-static
-OSStatus SecAccessCreateFromObject(CFTypeRef sourceRef,
- SecAccessRef *accessRef)
-{
- BEGIN_SECAPI
-
- Required(accessRef); // preflight
- SecPointer<Access> 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)
{
static OSStatus SecKeychainItemCreatePersistentReferenceFromCertificate(SecCertificateRef certRef,
CFDataRef *persistentItemRef, Boolean isIdentity)
{
+ COUNTLEGACYAPI
OSStatus __secapiresult;
if (!certRef || !persistentItemRef) {
return errSecParam;
@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
*/
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
@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
@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
@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
@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
@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
@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
@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
@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
@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);
/*!
@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 ----
@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
@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
#include "KCCursor.h"
#include <os/activity.h>
-/* 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);
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.
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.
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
/* 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
@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
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
*/
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
@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
*/
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
@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
__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);
/* 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)
#include <os/activity.h>
#include "SecBridge.h"
+#include "LegacyAPICounts.h"
CFTypeID
SecKeychainSearchGetTypeID(void)
{
BEGIN_SECAPI
-
return gTypes().KCCursorImpl.typeID;
END_SECAPI1(_kCFRuntimeNotATypeID)
@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
@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
@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
#include <os/activity.h>
-#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)
}
- // 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()) {
@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
@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)
}
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)
SecPolicySearchGetTypeID(void)
{
BEGIN_SECAPI
-
return gTypes().PolicyCursor.typeID;
END_SECAPI1(_kCFRuntimeNotATypeID)
SecPolicyRef* policyRef)
{
BEGIN_SECAPI
-
RequiredParam(policyRef);
SecPointer<Policy> policy;
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();
+ });
}
#include <security_utilities/simpleprefs.h>
#include <securityd_client/dictionary.h>
#include <securityd_client/ssclient.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include <dlfcn.h>
#include <libproc.h>
#include <syslog.h>
Dictionary* dictionary = Dictionary::CreateDictionary(kSecTrustSettingsPrefsDomain, Dictionary::US_System);
if (dictionary)
{
- auto_ptr<Dictionary> prefsDict(dictionary);
+ unique_ptr<Dictionary> prefsDict(dictionary);
/* this returns false if the pref isn't there, just like we want */
tsUserTrustDisable = prefsDict->getBoolValue(kSecTrustSettingsDisableUserTrustSettings);
}
return result;
}
- auto_ptr<TrustSettings>_(ts); // make sure this gets deleted just in case something throws underneath
+ unique_ptr<TrustSettings>_(ts); // make sure this gets deleted just in case something throws underneath
if(trustSettings) {
*trustSettings = ts->copyTrustSettings(cert);
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<Mutex> _(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<Mutex> _(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);
/*
return result;
}
- auto_ptr<TrustSettings>_(ts);
+ unique_ptr<TrustSettings>_(ts);
if(certRef != NULL) {
ts->setTrustSettings(certRef, trustSettingsDictOrArray);
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(
return result;
}
- auto_ptr<TrustSettings>_(ts);
+ unique_ptr<TrustSettings>_(ts);
ts->setTrustSettings(certRef, trustSettingsDictOrArray);
ts->flushToDisk();
return result;
}
- auto_ptr<TrustSettings>_(ts);
+ unique_ptr<TrustSettings>_(ts);
/* deleteTrustSettings throws if record not found */
trustSettingsDbg("SecTrustSettingsRemoveTrustSettings: deleting from domain %d",
return status;
}
- auto_ptr<TrustSettings>_(ts);
+ unique_ptr<TrustSettings>_(ts);
CFMutableArrayRef outArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
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.
return result;
}
- auto_ptr<TrustSettings>_(ts);
+ unique_ptr<TrustSettings>_(ts);
*trustSettings = ts->createExternal();
return errSecSuccess;
return result;
}
- auto_ptr<TrustSettings>_(ts);
+ unique_ptr<TrustSettings>_(ts);
ts->flushToDisk();
tsTrustSettingsChanged();
SecTrustedApplicationGetTypeID(void)
{
BEGIN_SECAPI
-
return gTypes().TrustedApplication.typeID;
END_SECAPI1(_kCFRuntimeNotATypeID)
SecCertificateRef anchor, SecTrustedApplicationRef *appRef)
{
BEGIN_SECAPI
-
CFRef<SecRequirementRef> req;
MacOSError::check(SecRequirementCreateGroup(CFTempString(groupName), anchor,
kSecCSDefaultFlags, &req.aref()));
*/
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
*/
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
*/
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
* 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
@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
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);
/*!
@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);
/*!
*/
OSStatus SecTrustedApplicationCopyExternalRepresentation(
SecTrustedApplicationRef appRef,
- CFDataRef *externalRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac);
+ CFDataRef *externalRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst);
/*!
@function SecTrustedApplicationCreateWithExternalRepresentation
*/
OSStatus SecTrustedApplicationCreateWithExternalRepresentation(
CFDataRef externalRef,
- SecTrustedApplicationRef *appRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac);
+ SecTrustedApplicationRef *appRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst);
/*
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);
/*
* 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);
/*
* 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)
#include <security_asn1/SecNssCoder.h>
#include <security_cdsa_utils/cuCdsaUtils.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
using namespace Security;
using namespace KeychainCore;
{
StLock<Mutex>_(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,
//
static SecCertificateRef _rootCertificateWithSubjectOfCertificate(SecCertificateRef certificate)
{
- if (!certificate)
+ if (!certificate) {
return NULL;
+ }
- StLock<Mutex> _(SecTrustKeychainsGetMutex());
+ StLock<Mutex> _(SecTrustKeychainsGetMutex());
// get data+length for the provided certificate
CSSM_CL_HANDLE clHandle = 0;
SecCertificateRef resultCert = NULL;
OSStatus status = errSecSuccess;
- if (!certificate)
+ if (!certificate) {
return NULL;
+ }
StLock<Mutex> _(SecTrustKeychainsGetMutex());
{
StLock<Mutex> _(SecTrustKeychainsGetMutex());
- if (!oidString)
+ if (!oidString) {
return NULL;
+ }
CFDictionaryRef evOidDict = _evCAOidDict();
if (!evOidDict)
return NULL;
pd = new Dictionary(tempDict);
CFRelease(tempDict);
- auto_ptr<Dictionary> prefsDict(pd);
+ unique_ptr<Dictionary> prefsDict(pd);
bool doOcsp = false;
bool doCrl = false;
#include <security_keychain/KCCursor.h>
#include <security_ocspd/ocspdClient.h>
#include <CoreFoundation/CoreFoundation.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include <dispatch/dispatch.h>
#include <sys/stat.h>
#include <syslog.h>
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.
*/
*/
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(
#include <Security/cssmtype.h>
#include <Security/cssmapple.h>
#include <Security/oidscert.h>
-#include <assert.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
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 {
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);
- (id)init
{
- self = [super init];
+ if ((self = [super init])) {
+ }
return self;
}
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)
{
-Manifest::~Manifest () throw ()
+Manifest::~Manifest () _NOEXCEPT
{
delete mManifestSigner;
}
Manifest ();
- virtual ~Manifest () throw ();
+ virtual ~Manifest () _NOEXCEPT;
ManifestInternal& GetManifestInternal () {return mManifestInternal;}
ManifestSigner* GetSigner () {return mManifestSigner;}
#include "SecureDownloadInternal.h"
#include "SecCFRelease.h"
+#include "simulatecrash_assert.h"
+
//
// SecureDownloadXML: SecureDownloadXML.c
// cc -g -framework CoreFoundation -o $@ $^
#include <sys/param.h>
#include <dirent.h>
#include <fcntl.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include <time.h>
#include <string>
#include <unistd.h>
void removeSubservice(const char *guid, uint32 ssid);
// implement CssmHeap::Allocator
- void *malloc(size_t size) throw(std::bad_alloc)
+ void *malloc(size_t size)
{ return mCssmMemoryFunctions.malloc(size); }
- void free(void *addr) throw()
+ void free(void *addr) _NOEXCEPT
{ mCssmMemoryFunctions.free(addr); }
- void *realloc(void *addr, size_t size) throw(std::bad_alloc)
+ void *realloc(void *addr, size_t size)
{ return mCssmMemoryFunctions.realloc(addr, size); }
MDSModule &module() { return mModule; }
#include <memory>
#include <security_utilities/globalizer.h>
#include <security_utilities/threading.h>
+#include "LegacyAPICounts.h"
#define MSApiDebug(args...) secinfo("MDS_API", ## args)
MDS_Terminate (MDS_HANDLE inMDSHandle)
{
BEGIN_API
- auto_ptr<MDSSession> aMDSSession (&HandleObject::findAndKill<MDSSession> (inMDSHandle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE));
+ unique_ptr<MDSSession> aMDSSession (&HandleObject::findAndKill<MDSSession> (inMDSHandle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE));
aMDSSession->terminate (); // Even if terminate throws the MDSSession object will be deleted.
END_API(MDS)
}
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;
}
/*
#include "pkcs12BagAttrs.h"
#include "pkcs12Utils.h"
#include <security_asn1/nssUtils.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include <Security/SecBase.h>
/*
* Copying constructor used by P12SafeBag during encoding
#include "pkcs12Debug.h"
#include "pkcs12Utils.h"
#include <string.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include <Security/Security.h>
#include <Security/SecKeyPriv.h>
#include <Security/SecAsn1Templates.h>
// 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<SDKey> ssKey(&mSDCSPDLSession.find<SDKey>(ioKey));
+ unique_ptr<SDKey> ssKey(&mSDCSPDLSession.find<SDKey>(ioKey));
ssKey->free(accessCred, ioKey, deleteKey);
}
else
if(!inSize) return;
const CssmData in(const_cast<void *>(mNullDigest.digestPtr()), inSize);
- IFDEBUG(size_t origOutSize = out.length());
+ size_t origOutSize = out.length();
if (encoding()) {
clientSession().encrypt(*mContext, mKeyHandle, in, out);
}
#include <Security/cssmapi.h>
#include <Security/oidscert.h>
#include <Security/oidscert.h>
+#include <utilities/SecCFWrappers.h>
#include <syslog.h>
/* for errKCDuplicateItem */
#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
// 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;
+ 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_ArenaUnmark(pl, mark);
-
- CSSM_CL_FreeFieldValue(clHandle, &CSSMOID_X509V1SerialNumber, serialNumber);
- CSSM_CL_FreeFieldValue(clHandle, &OID_X509V1IssuerNameStd, issuer);
+ }
+ PORT_Memcpy(certIssuerAndSN->serialNumber.Data, serialNumber.Data, serialNumber.Length);
+ certIssuerAndSN->serialNumber.Length = serialNumber.Length;
- if (itemImplRef)
- CFRelease(itemImplRef);
- if (certRef)
- CFRelease(certRef);
+ CFRelease(serial_data);
+ CFRelease(issuer_data);
+ PORT_ArenaUnmark(pl, mark);
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;
}
/*
* CMS digesting.
*/
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include "cmslocal.h"
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 */
- }
-
- if (SECOID_SetAlgorithmID(poolp, &(signerinfo->digestEncAlg), pubkAlgTag,
+ 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), sigAlgTag,
NULL) != SECSuccess)
goto loser;
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) {
/*
SecCertificateRef signercert;
CFStringRef emailAddress = NULL;
- if ((signercert = SecCmsSignerInfoGetSigningCertificate(sinfo, NULL)) == NULL)
- return NULL;
-
- SecCertificateGetEmailAddress(signercert, &emailAddress);
+ if ((signercert = SecCmsSignerInfoGetSigningCertificate(sinfo, NULL)) == NULL) {
+ return NULL;
+ }
- return CFRetainSafe(emailAddress);
+ CFArrayRef names = SecCertificateCopyRFC822Names(signercert);
+ if (names) {
+ if (CFArrayGetCount(names) > 0) {
+ emailAddress = (CFStringRef)CFArrayGetValueAtIndex(names, 0);
+ }
+ CFRetainSafe(emailAddress);
+ CFRelease(names);
+ }
+ return emailAddress;
}
}
xit:
- if (certRef)
+ if (certRef) {
CFRelease(certRef);
- return status;
+ }
+ return status;
}
static void saveTSACertificates(CSSM_DATA **signingCerts, CFMutableArrayRef outArray)
#include <Security/keyTemplates.h> /* for kSecAsn1AlgorithmIDTemplate */
#include <Security/SecAsn1Templates.h>
#include <stddef.h>
-#include <assert.h>
#include "tsaTemplates.h"
#include "cmslocal.h"
}
#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) {
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");
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);
verify_tests(kc, false);
encrypt_tests(certificate);
decrypt_tests(false);
- cleanup_keychain(kc, identity, certificate);
+ cleanup_keychain(&kc, &identity, &certificate);
return 0;
}
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,
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)
*/
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,
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,
+++ /dev/null
-.
\ No newline at end of file
* 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
/***** Internal Record Layer APIs *****/
-#include <CommonCrypto/CommonRandomSPI.h>
-#define CCRNGSTATE ccDRBGGetRngState()
+#include <corecrypto/ccrng.h>
+#define CCRNGSTATE ccrng(NULL)
SSLRecordContextRef
SSLCreateInternalRecordLayer(SSLContextRef sslCtx)
OSStatus
_SSLSetProtocolVersionEnabled (SSLContextRef context,
SSLProtocol protocol,
- Boolean enable) API_UNAVAILABLE(iosmac);
+ Boolean enable) API_UNAVAILABLE(macCatalyst);
/*
* Obtain a value specified in SSLSetProtocolVersionEnabled.
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,
*/
OSStatus
_SSLSetProtocolVersion (SSLContextRef context,
- SSLProtocol version) API_UNAVAILABLE(iosmac);
+ SSLProtocol version) API_UNAVAILABLE(macCatalyst);
/*
* Obtain the protocol version specified in SSLSetProtocolVersion.
*/
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
*/
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.
*/
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
*/
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
*/
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
OSStatus
_SSLSetTrustedRoots (SSLContextRef context,
CFArrayRef trustedRoots,
- Boolean replaceExisting) API_UNAVAILABLE(iosmac);
+ Boolean replaceExisting) API_UNAVAILABLE(macCatalyst);
/*
* Obtain an array of SecCertificateRefs representing the current
*/
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
OSStatus
_SSLSetCertificateAuthorities(SSLContextRef context,
CFTypeRef certificateOrArray,
- Boolean replaceExisting) API_UNAVAILABLE(iosmac);
+ Boolean replaceExisting) API_UNAVAILABLE(macCatalyst);
/*
* Obtain the certificates specified in SSLSetCertificateAuthorities(),
OSStatus
_SSLCopyCertificateAuthorities(SSLContextRef context,
- CFArrayRef *certificates) API_UNAVAILABLE(iosmac); /* RETURNED */
+ CFArrayRef *certificates) API_UNAVAILABLE(macCatalyst); /* RETURNED */
/*
* Request peer certificates. Valid anytime, subsequent to
*/
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
*/
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.
*/
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
* 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.
*/
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
*/
OSStatus
SSLNewDatagramContext (Boolean isServer,
- SSLContextRef *dtlsContextPtr) API_UNAVAILABLE(iosmac); /* RETURNED */
+ SSLContextRef *dtlsContextPtr) API_UNAVAILABLE(macCatalyst); /* RETURNED */
#include <tls_handshake.h>
#include <string.h>
-#include <assert.h>
#include <Security/SecBase.h>
#include <Security/SecureTransportPriv.h>
SSLContextRef ctx,
SecTrustRef *trust) /* RETURNED */
{
- OSStatus status = errSecSuccess;
- if (ctx == NULL || trust == NULL)
- return errSecParam;
+ 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);
+ /* Create a SecTrustRef if this was a resumed session and we
+ didn't have one yet. */
+ if (!ctx->peerSecTrust) {
+ status = sslCreateSecTrust(ctx, &ctx->peerSecTrust);
}
- *trust = ctx->peerSecTrust;
- if (ctx->peerSecTrust)
+ *trust = ctx->peerSecTrust;
+ if (ctx->peerSecTrust) {
CFRetain(ctx->peerSecTrust);
+ }
- return status;
+ return status;
}
OSStatus SSLGetPeerSecTrust(
#include <string.h>
#include <stdlib.h>
-#include <assert.h>
+#include "utilities/simulatecrash_assert.h"
#include <Security/SecTrustPriv.h>
#include <Security/SecPolicy.h>
#include "sslDebug.h"
#include "sslKeychain.h"
#include <string.h>
-#include <assert.h>
+#include "utilities/simulatecrash_assert.h"
#include <Security/Security.h>
#include "SSLRecordInternal.h"
#include <string.h>
-#include <assert.h>
#include <utilities/SecIOFormat.h>
#include "sslDebug.h"
#include "sslCipherSpecs.h"
-#include <assert.h>
+#include <utilities/simulatecrash_assert.h>
#include <string.h>
#include <utilities/SecIOFormat.h>
#include <utilities/SecCFWrappers.h>
+#import <utilities/SecCoreAnalytics.h>
#include <CommonCrypto/CommonDigest.h>
#include <Security/SecCertificatePriv.h>
#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);
}
}
#include <tls_helpers.h>
#include <tls_cache.h>
+#include "utilities/simulatecrash_assert.h"
+
static
int tls_handshake_write_callback(tls_handshake_ctx_t ctx, const SSLBuffer data, uint8_t content_type)
{
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);
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;
/* make non blocking */
fcntl(sock, F_SETFL, O_NONBLOCK);
-
return sock;
}
#define test_printf(x...)
-/* extern struct ccrng_state *ccDRBGGetRngState(); */
-#include <CommonCrypto/CommonRandomSPI.h>
-#define CCRNGSTATE ccDRBGGetRngState()
+#include <corecrypto/ccrng.h>
+#define CCRNGSTATE ccrng(NULL)
struct RecQueueItem {
STAILQ_ENTRY(RecQueueItem) next; /* link to next queued entry or NULL */
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);
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;
--- /dev/null
+{
+ "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
+}
--- /dev/null
+{
+ "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
+}
<string>/AppleInternal/XCTests/com.apple.security/</string>
<key>Command</key>
<array>
- <string>BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest Self SecureTransport_ios_tests.xctest</string>
+ <string>BATS_XCTEST_CMD</string>
+ <string>-NSTreatUnknownArgumentsAsOpen</string>
+ <string>NO</string>
+ <string> -ApplePersistenceIgnoreState</string>
+ <string>YES</string>
+ <string>-XCTest</string>
+ <string>Self</string>
+ <string>SecureTransport_ios_tests.xctest</string>
</array>
</dict>
</array>
<string>/AppleInternal/XCTests/com.apple.security/</string>
<key>Command</key>
<array>
- <string>BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest Self SecureTransport_macos_tests.xctest</string>
+ <string>BATS_XCTEST_CMD</string>
+ <string>-NSTreatUnknownArgumentsAsOpen</string>
+ <string>NO</string>
+ <string>-ApplePersistenceIgnoreState</string>
+ <string>YES</string>
+ <string>-XCTest</string>
+ <string>Self</string>
+ <string>SecureTransport_macos_tests.xctest</string>
</array>
</dict>
</array>
static void *securetransport_ssl_thread(void *arg)
{
OSStatus ortn;
- int sock = (int)arg;
+ int sock = *((int*)arg);
int socket = accept(sock, NULL, NULL);
}
//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");
#define test_printf(x...)
-/* extern struct ccrng_state *ccDRBGGetRngState(); */
-#include <CommonCrypto/CommonRandomSPI.h>
-#define CCRNGSTATE ccDRBGGetRngState()
+#include <corecrypto/ccrng.h>
+#define CCRNGSTATE ccrng(NULL)
struct RecQueueItem {
STAILQ_ENTRY(RecQueueItem) next; /* link to next queued entry or NULL */
+++ /dev/null
-.
\ No newline at end of file
* @APPLE_LICENSE_HEADER_END@
*/
-#include "SecEncodeTransform.h"
+#include <Security/SecEncodeTransform.h>
#ifdef __cplusplus
extern "C" {
* @APPLE_LICENSE_HEADER_END@
*/
-#include "SecTransform.h"
+#include <Security/SecTransform.h>
#ifdef __cplusplus
extern "C" {
* @APPLE_LICENSE_HEADER_END@
*/
-#include "SecTransform.h"
+#include <Security/SecTransform.h>
#ifdef __cplusplus
extern "C" {
#include <CoreFoundation/CoreFoundation.h>
#include <Security/SecKey.h>
-#include "SecTransform.h"
+#include <Security/SecTransform.h>
#ifdef __cplusplus
extern "C" {
#include "Utilities.h"
#include <Security/Security.h>
#include "misc.h"
-#include <mach-o/dyld_priv.h> // for dyld_get_program_sdk_version
+#include <mach-o/dyld_priv.h>
+
+#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");
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!
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!
* @APPLE_LICENSE_HEADER_END@
*/
-#include "SecTransform.h"
+#include <Security/SecTransform.h>
#include <Security/SecBase.h>
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;
}
ah = makeAH(ta);
if (!ah)
{
+ free(ta);
return NULL;
}
ta->name = CFStringCreateCopy(NULL, label);
if (!ta->name)
{
+ CFRelease(ah);
free(ta);
return NULL;
}
{
CFReleaseNull(ta->name);
free(ta);
+ CFRelease(ah);
return NULL;
}
{
// 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
{
// 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
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);
// 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();
#include "SecTransform.h"
#include "SecExternalSourceTransform.h"
#include "SecNullTransform.h"
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
@implementation speed_test
{
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())
{
return result;
}
+CFURLRef __nullable SecTranslocateCreateGeneric (CFURLRef pathToTranslocate,
+ CFURLRef destinationPath,
+ CFErrorRef* __nullable error)
+{
+ CFURLRef result = NULL;
+ CFIndex errorCode = 0;
+
+ try
+ {
+ string sourcePath = cfString(pathToTranslocate);
+ Security::SecTranslocate::GenericTranslocationPath path{sourcePath, Security::SecTranslocate::TranslocationOptions::Unveil};
+
+ string dpath = cfString(destinationPath);
+ string out_path = Security::SecTranslocate::getTranslocator()->translocatePathForUser(path, dpath);
+
+ if(!out_path.empty())
+ {
+ result = makeCFURL(out_path, true);
+ }
+ else
+ {
+ Syslog::error("SecTranslocateCreateGeneric: No mountpoint and no prior exception. Shouldn't be here");
+ UnixError::throwMe(EINVAL);
+ }
+
+ }
+ catch (Security::UnixError err)
+ {
+ errorCode = err.unixError();
+ }
+ catch(...)
+ {
+ Syslog::critical("SecTranslocateCreateGeneric: uncaught exception during mountpoint creation");
+ errorCode = EACCES;
+ }
+
+ if (error && errorCode)
+ {
+ *error = SecTranslocateMakePosixError(errorCode);
+ }
+ return result;
+}
+
/* Decide whether we need to translocate */
Boolean SecTranslocateURLShouldRunTranslocated(CFURLRef path, bool* shouldTranslocate, CFErrorRef* __nullable error)
{
try
{
string pathToCheck = cfString(path);
- Security::SecTranslocate::TranslocationPath tPath(pathToCheck);
+ Security::SecTranslocate::TranslocationPath tPath(pathToCheck, Security::SecTranslocate::TranslocationOptions::Default);
*shouldTranslocate = tPath.shouldTranslocate();
result = true;
}
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
dispatch_release(syncQ);
}
-string TranslocatorClient::translocatePathForUser(const TranslocationPath &originalPath, const string &destPath)
+string TranslocatorClient::requestTranslocation(const string& source,
+ const string& destination,
+ 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);
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, kSecTranslocateXPCMessageOriginalPath, source.c_str());
+ xpc_dictionary_set_int64(msg, kSecTranslocateXPCMessageOptions, static_cast<int64_t>(flags));
+ if(!destination.empty())
{
- xpc_dictionary_set_string(msg, kSecTranslocateXPCMessageDestinationPath, destPath.c_str());
+ xpc_dictionary_set_string(msg, kSecTranslocateXPCMessageDestinationPath, destination.c_str());
}
xpc_object_t reply = xpc_connection_send_message_with_reply_sync(service, msg);
return outPath;
}
+string TranslocatorClient::translocatePathForUser(const TranslocationPath &originalPath, const string &destPath)
+{
+ if (!originalPath.shouldTranslocate())
+ {
+ return originalPath.getOriginalRealPath(); //return original path if we shouldn't translocate
+ }
+
+ return requestTranslocation(originalPath.getOriginalRealPath(), destPath, TranslocationOptions::Default);
+}
+
+string TranslocatorClient::translocatePathForUser(const GenericTranslocationPath &originalPath, const string &destPath)
+{
+ if (!originalPath.shouldTranslocate())
+ {
+ return originalPath.getOriginalRealPath(); //return original path if we shouldn't translocate
+ }
+
+ return requestTranslocation(originalPath.getOriginalRealPath(), destPath, TranslocationOptions::Generic);
+}
+
void TranslocatorClient::appLaunchCheckin(pid_t pid)
{
xpc_object_t msg = xpc_dictionary_create(NULL, NULL, 0);
~TranslocatorClient();
string translocatePathForUser(const TranslocationPath &originalPath, const string &destPath) override;
+ string translocatePathForUser(const GenericTranslocationPath &originalPath, const string &destPath) override;
bool destroyTranslocatedPathForUser(const string &translocatedPath) override;
void appLaunchCheckin(pid_t pid) override;
private:
TranslocatorClient() = delete;
TranslocatorClient(const TranslocatorClient &that) = delete;
+
+ string requestTranslocation(const string& source, const string& destination, const TranslocationOptions flags);
+
dispatch_queue_t syncQ;
xpc_connection_t service;
};
--- /dev/null
+//
+// SecTranslocateEnumUtils.h
+// Security
+//
+//
+
+#ifndef SecTranslocateEnumUtils_h
+#define SecTranslocateEnumUtils_h
+
+#include <type_traits>
+
+template<typename Enum>
+Enum operator |(Enum lhs, Enum rhs)
+{
+ static_assert(std::is_enum<Enum>::value,
+ "template parameter is not an enum type");
+
+ using underlying = typename std::underlying_type<Enum>::type;
+
+ return static_cast<Enum> (
+ static_cast<underlying>(lhs) |
+ static_cast<underlying>(rhs)
+ );
+}
+
+template<typename Enum>
+Enum operator &(Enum lhs, Enum rhs)
+{
+ static_assert(std::is_enum<Enum>::value,
+ "template parameter is not an enum type");
+
+ using underlying = typename std::underlying_type<Enum>::type;
+
+ return static_cast<Enum> (
+ static_cast<underlying>(lhs) &
+ static_cast<underlying>(rhs)
+ );
+}
+
+#endif /* SecTranslocateEnumUtils_h */
public:
virtual ~Translocator() {};
virtual string translocatePathForUser(const TranslocationPath &originalPath, const string &destPath) = 0;
+ virtual string translocatePathForUser(const GenericTranslocationPath &originalPath, const string &destPath) = 0;
virtual bool destroyTranslocatedPathForUser(const string &translocatedPath) = 0;
virtual void appLaunchCheckin(pid_t pid) = 0;
};
return newPath;
}
+string TranslocatorServer::translocatePathForUser(const GenericTranslocationPath &originalPath, const string &destPath)
+{
+ __block string newPath;
+ __block exception_ptr exception(0);
+
+ dispatch_sync(syncQ, ^{
+ try
+ {
+ newPath = Security::SecTranslocate::translocatePathForUser(originalPath,destPath);
+ }
+ catch (...)
+ {
+ exception = current_exception();
+ }
+ });
+ if (exception)
+ {
+ rethrow_exception(exception);
+ }
+ return newPath;
+}
+
// This is intended for use by the host process of the server if necessary
// Destroy the translocation mount at translocatedPath if allowed
bool TranslocatorServer::destroyTranslocatedPathForUser(const string &translocatedPath)
~TranslocatorServer();
string translocatePathForUser(const TranslocationPath &originalPath, const string &destPath) override;
+ string translocatePathForUser(const GenericTranslocationPath &originalPath, const string &destPath) override;
bool destroyTranslocatedPathForUser(const string &translocatedPath) override;
void appLaunchCheckin(pid_t pid) override;
#include <vector>
#include <string>
#include <exception>
+#include <memory>
#include <sys/stat.h>
#include <unistd.h>
#include "SecTranslocateShared.hpp"
#include "SecTranslocateUtilities.hpp"
+#include "SecTranslocateEnumUtils.hpp"
+
+#define NULLM_UNVEIL 0x1ULL << 2
+struct null_mount_conf {
+ uint64_t flags;
+};
namespace Security {
const char* kSecTranslocateXPCMessageFunction = "function";
const char* kSecTranslocateXPCMessageOriginalPath = "original";
const char* kSecTranslocateXPCMessageDestinationPath = "dest";
+const char* kSecTranslocateXPCMessageOptions= "opts";
const char* kSecTranslocateXPCMessagePid = "pid";
/*XPC message reply keys */
static int removeMountPoint(const string &mountpoint, bool force = false);
/* calculate whether a translocation should occur and where from */
-TranslocationPath::TranslocationPath(string originalPath)
+TranslocationPath::TranslocationPath(string originalPath, TranslocationOptions opts)
{
/* To support testing of translocation the policy is as follows:
*/
ExtendedAutoFileDesc fd(originalPath);
-
+
+ options = opts;
should = false;
realOriginalPath = fd.getRealPath();
return ExtendedAutoFileDesc(joinPathUpTo(path, lastGoodIndex));
}
+GenericTranslocationPath::GenericTranslocationPath(const string& path, TranslocationOptions opts) {
+ ExtendedAutoFileDesc fd(path);
+ realOriginalPath = fd.getRealPath();
+ should = false;
+ options = opts;
+
+ /* don't translocate if it already is */
+ /* Nullfs can't translocate other mount's roots so abort if its a mountpoint */
+ if(fd.isFileSystemType(NULLFS_FSTYPE) || fd.isMountPoint()) {
+ return;
+ }
+
+ componentNameToTranslocate = splitPath(path).back();
+
+ should = true;
+}
+
/* 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) ||
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<string> mountFromPath = splitPath(fd.getMountFromPath());
return mntInfo;
}
+static bool pathExistsInMountTable(const GenericTranslocationPath& path, const string& mountpoint)
+{
+ vector <struct statfs> mntbuf = getMountTableSnapshot();
+
+ /* Save the untranslocated inode number*/
+ ExtendedAutoFileDesc::UnixStat untranslocatedStat;
+
+ if (stat(path.getOriginalRealPath().c_str(), &untranslocatedStat))
+ {
+ errno_t err = errno;
+ Syslog::warning("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;
+ Syslog::warning("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
}
}
-/* 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 (const string &mountPoint, const string &outPath)
{
string midPath = mountPoint+"/d";
- string outPath = originalPath.getTranslocatedPathToOriginalPath(midPath+"/"+originalPath.getComponentNameToTranslocate());
-
+
/* ExtendedAutoFileDesc will throw if one of these doesn't exist or isn't accessible */
ExtendedAutoFileDesc mountFd(mountPoint);
ExtendedAutoFileDesc midFd(midPath);
return outFd.getRealPath();
}
+
+static string newAppPath (const string &mountPoint, const GenericTranslocationPath &originalPath)
+{
+ string outPath = mountPoint+"/d/"+originalPath.getComponentNameToTranslocate();
+ return newAppPathFrom(mountPoint, 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 (const string &mountPoint, const TranslocationPath &originalPath)
+{
+ string outPath = originalPath.getTranslocatedPathToOriginalPath(mountPoint+"/d/"+originalPath.getComponentNameToTranslocate());
+ return newAppPathFrom(mountPoint, outPath);
+}
+
+static std::vector<char> getMountData(const string& toTranslocate, TranslocationOptions opts) {
+ std::vector<char> 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<const char*>(&conf), reinterpret_cast<const char*>(&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. */
mountpoint = destMountPoint;
}
- UnixError::check(mount(NULLFS_FSTYPE, mountpoint.c_str(), MNT_RDONLY, (void*)toTranslocate.c_str()));
+ auto mount_data = getMountData(toTranslocate, originalPath.getOptions());
+ UnixError::check(mount(NULLFS_FSTYPE, mountpoint.c_str(), MNT_RDONLY, mount_data.data()));
setMountPointQuarantineIfNecessary(mountpoint, toTranslocate); //throws
return newPath;
}
+string translocatePathForUser(const GenericTranslocationPath &originalPath, const string &destPath)
+{
+ string newPath;
+ exception_ptr exception(0);
+
+ string mountpoint = destPath;
+ bool owned = false;
+ try
+ {
+ const string &toTranslocate = originalPath.getOriginalRealPath();
+ if (pathExistsInMountTable(originalPath, destPath))
+ {
+ /* A mount point exists already so bail*/
+ newPath = newAppPath(mountpoint, originalPath);
+ return newPath; /* exit the block */
+ }
+
+ AutoFileDesc fd(getFDForDirectory(mountpoint, &owned)); //throws, makes the directory if it doesn't exist
+
+ validateMountpoint(mountpoint, owned); //throws
+
+ auto mount_data = getMountData(toTranslocate, originalPath.getOptions());
+ UnixError::check(mount(NULLFS_FSTYPE, mountpoint.c_str(), MNT_RDONLY, mount_data.data()));
+
+ setMountPointQuarantineIfNecessary(mountpoint, toTranslocate); //throws
+
+ newPath = newAppPath(mountpoint, originalPath); //throws
+
+ // log that we created a new mountpoint (we don't log when we are re-using)
+ Syslog::warning("SecTranslocateCreateGeneric: 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());
+ }
+ }
+ }
+
+ /* rethrow outside the dispatch block */
+ if (exception)
+ {
+ rethrow_exception(exception);
+ }
+
+ return newPath;
+}
+
/* Loop through the directory in the specified user directory and delete any that aren't mountpoints */
static void cleanupTranslocationDirForUser(const string &userDir)
{
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
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)
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);
+ inline bool shouldTranslocate() const { return should; };
+ inline const string & getOriginalRealPath() const { return realOriginalPath; };
+ inline const string & getComponentNameToTranslocate() const { return componentNameToTranslocate; };
+ inline TranslocationOptions getOptions() const { return options; };
+private:
+ GenericTranslocationPath() = delete;
+
+ bool should;
+ string realOriginalPath;
+ string componentNameToTranslocate;
+ TranslocationOptions options;
+};
+
class TranslocationPath
{
public:
- TranslocationPath(string originalPath);
+ TranslocationPath(string originalPath, TranslocationOptions opts);
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; };
string getTranslocatedPathToOriginalPath(const string &translocationPoint) const;
+ inline TranslocationOptions getOptions() const { return options; };
private:
TranslocationPath() = delete;
string pathToTranslocate;
string componentNameToTranslocate; //the final component of pathToTranslocate
string pathInsideTranslocationPoint;
+ TranslocationOptions options;
ExtendedAutoFileDesc findOuterMostCodeBundleForFD(ExtendedAutoFileDesc &fd);
};
// 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 GenericTranslocationPath &originalPath, const string &destPath); //throws
bool destroyTranslocatedPathForUser(const string &translocatedPath); //throws
bool destroyTranslocatedPathsForUserOnVolume(const string &volumePath = ""); //throws
void tryToDestroyUnusedTranslocationMounts();
} //namespace SecTranslocate
}// namespace Security
+
#endif /* SecTranslocateShared_hpp */
//Path parsing functions
vector<string> splitPath(const string &path);
string joinPath(vector<string>& path);
- string joinPathUpTo(vector<string> &path, size_t index);
+string joinPathUpTo(vector<string> &path, size_t index);
//File system utlities
string getRealPath(const string &path);
#include "SecTranslocateXPCServer.hpp"
#include "SecTranslocateUtilities.hpp"
#include "SecTranslocateShared.hpp"
+#include "SecTranslocateEnumUtils.hpp"
namespace Security {
namespace SecTranslocate {
{
const char* original = xpc_dictionary_get_string(msg, kSecTranslocateXPCMessageOriginalPath);
const char* dest = xpc_dictionary_get_string(msg, kSecTranslocateXPCMessageDestinationPath);
+ const int64_t opts = xpc_dictionary_get_int64(msg, kSecTranslocateXPCMessageOptions);
string originalPath = original ? original : "";
string destPath = dest ? dest: "";
+ TranslocationOptions options = static_cast<TranslocationOptions>(opts);
- if( originalPath.empty())
+ if (originalPath.empty())
{
Syslog::error("SecTranslocate: XPCServer, doCreate no path to translocate");
UnixError::throwMe(EINVAL);
}
- TranslocationPath tPath(originalPath);
+ string result = originalPath;
+
+ if ((options & TranslocationOptions::Generic) == TranslocationOptions::Generic) {
+ GenericTranslocationPath tPath(originalPath, TranslocationOptions::Unveil);
- string result = tPath.getOriginalRealPath();
+ if(tPath.shouldTranslocate())
+ {
+ result = Security::SecTranslocate::translocatePathForUser(tPath, destPath);
+ }
+ } else {
+ TranslocationPath tPath(originalPath, TranslocationOptions::Default);
- if(tPath.shouldTranslocate())
- {
- result = Security::SecTranslocate::translocatePathForUser(tPath, destPath);
+ if(tPath.shouldTranslocate())
+ {
+ result = Security::SecTranslocate::translocatePathForUser(tPath, destPath);
+ }
}
+
xpc_dictionary_set_string(reply, kSecTranslocateXPCReplySecurePath, result.c_str());
}
//
// 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;
}
// 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 {
}
}
-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)
// 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();
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 *>()));
(*(Allocator **)end)->free(addr);
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 <class T> T *alloc() throw(std::bad_alloc)
+ template <class T> T *alloc()
{ return reinterpret_cast<T *>(malloc(sizeof(T))); }
- template <class T> T *alloc(UInt32 count) throw(std::bad_alloc)
+ template <class T> T *alloc(UInt32 count)
{
size_t bytes = 0;
if (__builtin_mul_overflow(sizeof(T), count, &bytes)) {
}
- template <class T> T *alloc(T *old, UInt32 count) throw(std::bad_alloc)
+ template <class T> T *alloc(T *old, UInt32 count)
{
size_t bytes = 0;
if (__builtin_mul_overflow(sizeof(T), count, &bytes)) {
// Happier malloc/realloc for any type. Note that these still have
// the original (byte-sized) argument profile.
//
- template <class T> T *malloc(size_t size) throw(std::bad_alloc)
+ template <class T> T *malloc(size_t size)
{ return reinterpret_cast<T *>(malloc(size)); }
- template <class T> T *realloc(void *addr, size_t size) throw(std::bad_alloc)
+ template <class T> T *realloc(void *addr, size_t size)
{ return reinterpret_cast<T *>(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)) {
}
// compare Allocators for identity
- virtual bool operator == (const Allocator &alloc) const throw();
+ virtual bool operator == (const Allocator &alloc) const _NOEXCEPT;
public:
// allocator chooser options
// Use this to cleanly destroy things.
//
template <class T>
-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);
}
//
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<void> is perfectly valid, unlike its auto_ptr look-alike.
+// Note that CssmAutoPtr<void> is perfectly valid, unlike its unique_ptr look-alike.
// You can't dereference it, naturally.
//
template <class T>
~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; }
~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; }
//
// 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); }
}
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;
void
-CFClass::finalizeType(CFTypeRef cf) throw()
+CFClass::finalizeType(CFTypeRef cf) _NOEXCEPT
{
/*
We need to control the lifetime of the object. This means
}
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 {
}
CFHashCode
-CFClass::hashType(CFTypeRef cf) throw()
+CFClass::hashType(CFTypeRef cf) _NOEXCEPT
{
try {
return SecCFObject::optional(cf)->hash();
}
CFStringRef
-CFClass::copyFormattingDescType(CFTypeRef cf, CFDictionaryRef dict) throw()
+CFClass::copyFormattingDescType(CFTypeRef cf, CFDictionaryRef dict) _NOEXCEPT
{
try {
return SecCFObject::optional(cf)->copyFormattingDesc(dict);
}
CFStringRef
-CFClass::copyDebugDescType(CFTypeRef cf) throw()
+CFClass::copyDebugDescType(CFTypeRef cf) _NOEXCEPT
{
try {
return SecCFObject::optional(cf)->copyDebugDesc();
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);
};
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)
namespace Security {
namespace Daemon {
-
//
// Daemonize this process, the UNIX way.
//
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
namespace Daemon {
bool incarnate(bool doFork=true);
-bool executeSelf(char **argv);
} // end namespace Daemon
} // end namespace Security
// 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, "...");
strlcpy(whatBuffer, source.whatBuffer, whatBufferSize);
}
-CommonError::~CommonError() throw ()
+CommonError::~CommonError() _NOEXCEPT
{
}
}
}
-const char *UnixError::what() const throw ()
+const char *UnixError::what() const _NOEXCEPT
{
return whatBuffer;
}
}
}
-const char *MacOSError::what() const throw ()
+const char *MacOSError::what() const _NOEXCEPT
{
return whatBuffer;
}
LogBacktrace();
}
-const char *CFError::what() const throw ()
+const char *CFError::what() const _NOEXCEPT
{ return "CoreFoundation error"; }
OSStatus CFError::osStatus() const
CommonError();
CommonError(const CommonError &source);
public:
- virtual ~CommonError() throw ();
+ virtual ~CommonError() _NOEXCEPT;
virtual OSStatus osStatus() const = 0;
virtual int unixError() const = 0;
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));
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));
public:
virtual OSStatus osStatus() const;
virtual int unixError() const;
- virtual const char *what () const throw ();
+ virtual const char *what () const _NOEXCEPT;
template <class T>
static void check(const T &p) { if (!p) throwMe(); }
//
// The Error class thrown if Nexus operations fail
//
-GlobalNexus::Error::~Error() throw()
+GlobalNexus::Error::~Error() _NOEXCEPT
{
}
{
const char *env = getenv(identifier);
if (env == NULL) { // perhaps we're first...
- auto_ptr<Store> store(new Store);
+ unique_ptr<Store> store(new Store);
char form[2*sizeof(Store *) + 2];
sprintf(form, "*%p", &store);
setenv(identifier, form, 0); // do NOT overwrite...
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; }
};
};
secnotice("security_exception", "mach error: %d", err);
}
-Error::~Error() throw()
+Error::~Error() _NOEXCEPT
{ }
{
// 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
// 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;
// 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)); }
};
-//
-// 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)); }
public:
ReceivePort() { allocate(); }
ReceivePort(const char *name, const Bootstrap &bootstrap, bool tryCheckin = true);
- ~ReceivePort() { destroy(); }
+ ~ReceivePort() { modRefs(MACH_PORT_RIGHT_RECEIVE, -1); }
};
// 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)
MachO* Universal::make(MachO* macho) const
{
- auto_ptr<MachO> mo(macho); // safe resource
+ unique_ptr<MachO> mo(macho); // safe resource
uint32_t type = mo->type();
if (type == 0) // not a recognized Mach-O type
UnixError::throwMe(ENOEXEC);
for (unsigned n = 0; n < mArchCount; n++)
archs.insert(mArchList[n]);
} else {
- auto_ptr<MachO> macho(architecture());
+ unique_ptr<MachO> macho(architecture());
archs.insert(macho->architecture());
}
}
Universal::Architectures archList;
architectures(archList);
for (Universal::Architectures::const_iterator it = archList.begin(); it != archList.end(); ++it) {
- auto_ptr<MachO> macho(architecture(*it));
+ unique_ptr<MachO> macho(architecture(*it));
if (macho->isSuspicious())
return true;
}
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
}
-const char *Error::what() const throw ()
+const char *Error::what() const _NOEXCEPT
{
return msc_error(error);
}
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();
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);
}
-const char *Error::what() const throw ()
+const char *Error::what() const _NOEXCEPT
{
return pcsc_stringify_error((int32_t)error);
}
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);
RefPointer& operator = (const RefPointer<Sub>& 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; }
// SecCFObject
//
SecCFObject *
-SecCFObject::optional(CFTypeRef cfTypeRef) throw()
+SecCFObject::optional(CFTypeRef cfTypeRef) _NOEXCEPT
{
if (!cfTypeRef)
return NULL;
}
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);
}
void
-SecCFObject::operator delete(void *object) throw()
+SecCFObject::operator delete(void *object) _NOEXCEPT
{
CFTypeRef cfType = reinterpret_cast<CFTypeRef>(reinterpret_cast<const uint8_t *>(object) - kAlignedRuntimeSize);
}
CFTypeRef
-SecCFObject::handle(bool retain) throw()
+SecCFObject::handle(bool retain) _NOEXCEPT
{
CFTypeRef cfType = *this;
if (retain && !isNew()) CFRetain(cfType);
#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) \
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);
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<CFTypeRef>(reinterpret_cast<const uint8_t *>(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();
T *yield() { T *result = static_cast<T *>(ptr); ptr = NULL; return result; }
// dereference operations
- T* get () const { return static_cast<T*>(ptr); } // mimic auto_ptr
+ T* get () const { return static_cast<T*>(ptr); } // mimic unique_ptr
operator T * () const { return static_cast<T*>(ptr); }
T * operator -> () const { return static_cast<T*>(ptr); }
T & operator * () const { return *static_cast<T*>(ptr); }
+
+ SecPointer& operator=(const SecPointer& other) { SecPointerBase::operator=(other); return *this; }
};
template <class T>
#include "errors.h"
#include <sys/param.h>
#include <stdlib.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include <stdexcept>
#include <security_utilities/debugging.h>
#include <CoreFoundation/CFData.h>
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;
#include <security_utilities/blob.h>
#include <map>
+#include <sstream>
#include <vector>
namespace Security {
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;
}
// 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)
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();
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
#include <security_utilities/debugging.h>
#include <signal.h>
+#include <sstream>
namespace Security {
namespace UnixPlusPlus {
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:
} 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) {
#include <string>
#include <string.h>
+#include <security_utilities/simulatecrash_assert.h>
+
namespace Security
{
#define _H_UTILITY_CONFIG
#include <CoreFoundation/CFBase.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
//
// Decide what io apis we'll be using
#include <string.h>
#include <stdlib.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include "sec_xdr.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include "sec_xdr.h"
static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr_reference.c,v 1.11 2002/03/22 21:53:26 obrien Exp $";
#endif
#include <sys/cdefs.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
/*
* xdr_reference.c, Generic XDR routines impelmentation.
*
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
-#include <assert.h>
bool_t
xdr_AuthorizationItem(XDR *xdrs, AuthorizationItem *objp)
#include <architecture/byte_order.h>
#include <string.h> /* bzero() */
#include <stdlib.h> /* exit() */
-#include <assert.h> /* assert() */
+#include <security_utilities/simulatecrash_assert.h> /* assert() */
#include <stdio.h> /* XXX/gh because utilities/debugging.h doesn't */
#include <security_utilities/debugging.h>
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 */
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);
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"
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";
}
}
#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. */
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... */
})
-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
--- /dev/null
+/*
+ * 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 <stdint.h>
+
+/* 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 */
#include <Security/SecOTRSession.h>
#include <Security/SecInternal.h>
#include <Security/SecBasePriv.h>
+#include <Security/SecKey.h>
+#include <Security/SecItem.h>
+#include <utilities/SecCFWrappers.h>
+#include <Security/SecOTRIdentityPriv.h>
static void RegressionsLogError(CFErrorRef error) {
if (error == NULL) {
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);
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);
CFReleaseSafe(failIDInflate2);
CFReleaseSafe(testInteropImport);
CFReleaseSafe(interopIDInflate);
+
+ otr_00_identity_MessageProtectionKeys();
}
+
+
int otr_00_identity(int argc, char *const *argv)
{
plan_tests(kTestTestCount);
"trust is kSecTrustResultOtherError");
}
SecKeyRef pub_key_leaf;
- isnt(pub_key_leaf = SecTrustCopyPublicKey(trust), NULL, "get leaf pub key");
+ 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, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1, sha1Data, signature, &error),
+++ /dev/null
-/*
- * Copyright (c) 2006-2018 Apple Inc. All Rights Reserved.
- */
-
-#include <AssertMacros.h>
-#include <CoreFoundation/CoreFoundation.h>
-#include <Security/SecCertificate.h>
-#include <Security/SecCertificatePriv.h>
-#include <Security/SecPolicyPriv.h>
-#include <Security/SecTrustPriv.h>
-#include <utilities/array_size.h>
-#include <utilities/SecCFRelease.h>
-#include <stdlib.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <unistd.h>
-#include <string.h>
-
-#include "shared_regressions.h"
-
-#include "si-23-sectrust-ocsp.h"
-
-static void tests(void)
-{
- SecTrustRef trust;
- SecCertificateRef cert0, cert1;
- isnt(cert0 = SecCertificateCreateWithBytes(NULL, _ocsp_c0, sizeof(_ocsp_c0)),
- NULL, "create cert0");
- isnt(cert1 = SecCertificateCreateWithBytes(NULL, _ocsp_c1, sizeof(_ocsp_c1)),
- NULL, "create cert1");
- CFMutableArrayRef certs = CFArrayCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeArrayCallBacks);
- CFArrayAppendValue(certs, cert0);
- CFArrayAppendValue(certs, cert1);
-
- SecPolicyRef sslPolicy = SecPolicyCreateSSL(true, CFSTR("www.apple.com"));
- SecPolicyRef ocspPolicy = SecPolicyCreateRevocation(kSecRevocationOCSPMethod);
- const void *v_policies[] = { sslPolicy, ocspPolicy };
- CFArrayRef policies = CFArrayCreate(NULL, v_policies,
- 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);
- ok_status(SecTrustSetVerifyDate(trust, date), "set date");
-
- is(SecTrustGetVerifyTime(trust), 577000000.0, "get date");
-
- SecTrustResultType trustResult;
- ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust");
- is_status(trustResult, kSecTrustResultUnspecified,
- "trust is kSecTrustResultUnspecified");
-
- /* Certificates are only EV if they are also CT. */
- CFDictionaryRef info = SecTrustCopyInfo(trust);
- CFBooleanRef ev = (CFBooleanRef)CFDictionaryGetValue(info,
- kSecTrustInfoExtendedValidationKey);
- ok(ev, "extended validation succeeded");
-
- CFReleaseSafe(info);
- CFReleaseSafe(trust);
- CFReleaseSafe(policies);
- CFReleaseSafe(certs);
- CFReleaseSafe(cert0);
- CFReleaseSafe(cert1);
- CFReleaseSafe(date);
-}
-
-static void test_ocsp_responder_policy() {
- SecCertificateRef leaf = NULL, subCA = NULL, responderCert = NULL;
- CFMutableArrayRef certs = CFArrayCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeArrayCallBacks);
- SecTrustRef trust = NULL;
- SecPolicyRef ocspSignerPolicy = NULL;
- SecTrustResultType trustResult = kSecTrustResultInvalid;
-
- /* August 14, 2018 at 9:26:40 PM PDT */
- CFDateRef date = CFDateCreate(NULL, 556000000.0);
-
- 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);
-
- ok(ocspSignerPolicy = SecPolicyCreateOCSPSigner(),
- "create ocspSigner 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");
- is_status(trustResult, kSecTrustResultRecoverableTrustFailure,
- "trust is kSecTrustResultRecoverableTrustFailure");
-
- isnt(responderCert = SecCertificateCreateWithBytes(NULL, _responderCert,
- sizeof(_responderCert)), NULL, "create responderCert");
- 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");
- is_status(trustResult, kSecTrustResultUnspecified,
- "trust is kSecTrustResultUnspecified");
-
- CFReleaseNull(leaf);
- CFReleaseNull(subCA);
- CFReleaseNull(responderCert);
- CFReleaseNull(certs);
- CFReleaseNull(trust);
- CFReleaseSafe(ocspSignerPolicy);
- CFReleaseNull(date);
-}
-
-static void test_revocation() {
- SecTrustRef trust;
- SecCertificateRef rcert0, rcert1;
- isnt(rcert0 = SecCertificateCreateWithBytes(NULL,
- revoked_ist_certificate, sizeof(revoked_ist_certificate)),
- NULL, "create rcert0");
- isnt(rcert1 = SecCertificateCreateWithBytes(NULL,
- ist_intermediate_certificate, sizeof(ist_intermediate_certificate)),
- NULL, "create rcert1");
- CFMutableArrayRef rcerts = CFArrayCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeArrayCallBacks);
- CFArrayAppendValue(rcerts, rcert0);
- CFArrayAppendValue(rcerts, rcert1);
-
- SecPolicyRef sslPolicy = SecPolicyCreateSSL(true, CFSTR("revoked.geotrust-global-ca.test-pages.certificatemanager.apple.com"));
- SecPolicyRef ocspPolicy = SecPolicyCreateRevocation(kSecRevocationOCSPMethod);
- const void *v_policies[] = { sslPolicy, ocspPolicy };
- CFArrayRef policies = CFArrayCreate(NULL, v_policies,
- array_size(v_policies), &kCFTypeArrayCallBacks);
- CFRelease(sslPolicy);
- CFRelease(ocspPolicy);
- ok_status(SecTrustCreateWithCertificates(rcerts, policies, &trust),
- "create trust");
- /* Feb 5th 2015. */
- CFDateRef date = CFDateCreate(NULL, 444900000);
- ok_status(SecTrustSetVerifyDate(trust, date), "set date");
- CFReleaseSafe(date);
-
- 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);
- CFDictionaryRef results = SecTrustCopyResult(trust);
- CFTypeRef revoked = NULL;
- if (results) {
- CFArrayRef perCertResults = CFDictionaryGetValue(results, CFSTR("TrustResultDetails"));
- if (perCertResults) {
- CFDictionaryRef leafResults = CFArrayGetValueAtIndex(perCertResults, 0);
- if (leafResults) {
- revoked = CFDictionaryGetValue(leafResults, CFSTR("Revocation"));
- }
- }
- }
- is(revoked != NULL, true, "revoked result is %@", revoked);
- CFReleaseSafe(results);
-
-
- /* Now verify the cert at a date in the past relative to the previous
- date, but still within the cert's validity period. Although the
- cached response from our prior attempt will appear to have been
- produced in the future, it should still be honored since it's
- validly signed.
- */
- /* Dec 11th 2014. */
- date = CFDateCreate(NULL, 440000000);
- ok_status(SecTrustSetVerifyDate(trust, date), "set date");
- CFReleaseSafe(date);
-
- 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);
- results = SecTrustCopyResult(trust);
- revoked = NULL;
- if (results) {
- CFArrayRef perCertResults = CFDictionaryGetValue(results, CFSTR("TrustResultDetails"));
- if (perCertResults) {
- CFDictionaryRef leafResults = CFArrayGetValueAtIndex(perCertResults, 0);
- if (leafResults) {
- revoked = CFDictionaryGetValue(leafResults, CFSTR("Revocation"));
- }
- }
- }
- is(revoked != NULL, true, "revoked result is %@", revoked);
- CFReleaseSafe(results);
-
- CFReleaseSafe(trust);
- CFReleaseSafe(policies);
- CFReleaseSafe(rcerts);
- CFReleaseSafe(rcert0);
- CFReleaseSafe(rcert1);
-}
-
-static void test_forced_revocation()
-{
- /*
- * 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);
- }
-
- // 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;
- 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;
- 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"));
-
-#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");
- 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.");
- }
-#pragma clang diagnostic pop
-
-errOut:
- CFReleaseNull(leaf);
- CFReleaseNull(policy);
- CFReleaseNull(trust);
- CFReleaseNull(certs);
- CFReleaseNull(verifyDate);
- CFReleaseNull(error);
-}
-
-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.");
- }
-#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;
- CFArrayRef certs = NULL, anchors = NULL, policies = NULL;
- CFDateRef verifyDate = NULL;
- CFErrorRef error = NULL;
-
- leaf = SecCertificateCreateWithBytes(NULL, _ocsp_c0, sizeof(_ocsp_c0));
- subCA = SecCertificateCreateWithBytes(NULL, _ocsp_c1, sizeof(_ocsp_c1));
- root = SecCertificateCreateWithBytes(NULL, _ocsp_c2, sizeof(_ocsp_c2));
-
- sslPolicy = SecPolicyCreateSSL(true, CFSTR("www.apple.com"));
- ocspPolicy = SecPolicyCreateRevocation(kSecRevocationOCSPMethod);
-
- 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, 577000000.0); // April 14, 2019 at 10:46:40 PM 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"
- 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 */
- CFDictionaryRef result = SecTrustCopyResult(trust);
- isnt(result, NULL, "failed to copy result dictionary");
- if (result) {
- is(CFDictionaryGetValue(result, kSecTrustRevocationChecked), kCFBooleanTrue, "expected revocation checked flag");
- CFDateRef validUntil = CFDictionaryGetValue(result, kSecTrustRevocationValidUntilDate);
- isnt(validUntil, NULL, "expected revocation valid until date");
- if (validUntil) {
- ok(CFDateGetAbsoluteTime(validUntil) > CFAbsoluteTimeGetCurrent(), "expected valid until date in the future");
- } else {
- fail("did not get valid until date");
- }
- }
- CFReleaseNull(result);
-#pragma clang diagnostic pop
-
-errOut:
- CFReleaseNull(leaf);
- CFReleaseNull(subCA);
- CFReleaseNull(root);
- CFReleaseNull(ocspPolicy);
- CFReleaseNull(sslPolicy);
- CFReleaseNull(trust);
- CFReleaseNull(certs);
- CFReleaseNull(anchors);
- CFReleaseNull(policies);
- CFReleaseNull(verifyDate);
- 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);
- }
-
- 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_23_sectrust_ocsp(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",
- "ocsp.entrust.net",
- "ocsp.digicert.com",
- };
-
- unsigned host_cnt = 0;
-
- plan_tests(105);
-
- 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;
- }
- }
-
- tests();
- test_ocsp_responder_policy();
- test_aia();
- test_aia_https();
- test_revocation();
- test_forced_revocation();
- test_results_dictionary_revocation_reason();
- test_results_dictionary_revocation_checked();
-
- return 0;
-}
+++ /dev/null
-/*
- * 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_ */
"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");
+ 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, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1, sha1Data, signature, &error),
}
print_plist(plist);
- CFRelease(plist);
+ CFReleaseNull(plist);
}
static void tests(void)
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);
+++ /dev/null
-/*
- * Copyright (c) 2016 Apple Inc. All Rights Reserved.
- */
-
-#ifndef si_28_sectrustsettings_h
-#define si_28_sectrustsettings_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 */
-unsigned char _trustSettingsRoot[1008]={
- 0x30,0x82,0x03,0xEC,0x30,0x82,0x02,0xD4,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00,
- 0xEE,0xAD,0xE6,0x5E,0x2C,0x5C,0x7C,0x40,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,
- 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,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,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,
- 0x2C,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,
- 0x54,0x72,0x75,0x73,0x74,0x20,0x53,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x20,0x54,
- 0x65,0x73,0x74,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,
- 0x36,0x30,0x33,0x31,0x39,0x32,0x33,0x33,0x30,0x34,0x34,0x5A,0x17,0x0D,0x32,0x36,
- 0x30,0x33,0x31,0x37,0x32,0x33,0x33,0x30,0x34,0x34,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,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,
- 0x70,0x70,0x6C,0x65,0x2C,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,0x54,0x72,0x75,0x73,0x74,0x20,0x53,0x65,0x74,0x74,0x69,0x6E,
- 0x67,0x73,0x20,0x54,0x65,0x73,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,
- 0xC6,0xB5,0x94,0x9F,0x10,0xC7,0x49,0x4F,0xAF,0xA5,0xE4,0x98,0xEE,0xEB,0x9C,0x39,
- 0xCA,0xF0,0x47,0x54,0xCA,0x26,0x4A,0xDD,0x6E,0x1E,0x33,0x4F,0x5E,0xF5,0x9F,0x4A,
- 0x41,0x3F,0xC3,0xCF,0xEB,0x30,0x51,0xD8,0x85,0xAB,0xD6,0xDD,0x45,0xBF,0x0D,0x67,
- 0x0D,0xDA,0x88,0x07,0xD8,0xB2,0x6D,0x6C,0x56,0xEE,0x27,0x74,0xDE,0x81,0xAC,0x35,
- 0x9F,0xBC,0x9E,0x4A,0x97,0x0E,0xB4,0x84,0xA4,0xFA,0x24,0x21,0xBE,0x74,0x40,0xB4,
- 0x9E,0xFC,0x81,0x9B,0xE6,0x82,0xB8,0xB6,0xAD,0x33,0x88,0xEC,0x30,0x5B,0x88,0x56,
- 0x7E,0x3D,0x03,0x7A,0xC7,0xC2,0x58,0xF9,0x7C,0x68,0x77,0x75,0x8B,0x59,0x82,0x28,
- 0xFC,0x0B,0x69,0x25,0x61,0x1E,0xCA,0x1F,0x7C,0x4D,0x3E,0x74,0xE5,0xE1,0xA0,0xDD,
- 0xB3,0xD8,0xBD,0x11,0x4A,0x57,0xB9,0xAA,0xB3,0x92,0x53,0x9C,0x2A,0xE5,0x91,0xD8,
- 0x57,0xCC,0xAD,0xB9,0x7F,0x4B,0x94,0x0F,0xCD,0xE0,0xEF,0xF7,0xE9,0x2A,0xE4,0x90,
- 0xEF,0xA2,0x69,0x53,0x46,0x68,0x5D,0x39,0xD5,0x08,0x24,0x33,0x3D,0x81,0xF5,0x34,
- 0xCD,0x06,0xC4,0xDB,0xC7,0x59,0xF9,0x9C,0xD9,0x00,0xD1,0x33,0x8F,0xE5,0x9D,0xF5,
- 0x7A,0xD0,0x91,0x3A,0x1F,0xE2,0x5C,0x24,0xB4,0xFD,0xF1,0x86,0x04,0x66,0x10,0xEC,
- 0x8F,0xB5,0x50,0xEF,0xBC,0x13,0xC2,0x32,0x52,0xFD,0x55,0x8D,0x9A,0x3E,0xB1,0xA0,
- 0x94,0x02,0x96,0xF4,0x64,0xE3,0x23,0x4F,0x18,0x19,0xAF,0x82,0xD0,0x25,0xA2,0x8C,
- 0x76,0x6B,0xDA,0xBA,0xF9,0xE8,0x0D,0xBA,0x32,0x74,0xF1,0x2F,0xB9,0xE3,0xD2,0x93,
- 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,0x03,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,0x68,0x31,0x64,0x1E,0x5C,0x68,0x6A,0x83,
- 0xBD,0x39,0x22,0x44,0xF6,0xD3,0x6C,0x70,0xF7,0xDD,0x22,0x53,0x30,0x0D,0x06,0x09,
- 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,
- 0x01,0xDF,0xE1,0x02,0xED,0x2A,0x55,0xC3,0xFF,0x9A,0xD7,0x43,0xCF,0xD9,0x5F,0x3C,
- 0xD5,0xAF,0xB1,0xEF,0x1F,0xF1,0x15,0x88,0x17,0x37,0x69,0x25,0xC1,0x42,0xFC,0xE3,
- 0x18,0xBC,0x02,0x6A,0x0B,0xAD,0xDB,0x49,0xE0,0xCB,0xBE,0x84,0xC0,0xF8,0x26,0xD0,
- 0xA6,0x4C,0xCB,0x3D,0xF4,0x52,0xBA,0xF2,0x3B,0x2C,0x3F,0xD6,0x46,0xAA,0xC8,0xE7,
- 0xE5,0x4A,0x41,0x7D,0xCA,0xC3,0x3A,0xEF,0xD0,0xFF,0xA2,0x1A,0x07,0x4E,0x18,0x70,
- 0xC6,0xBD,0xA2,0x37,0xD9,0x72,0xFB,0x95,0xC9,0x0A,0x4E,0x39,0x0D,0x67,0x45,0xF2,
- 0x92,0x34,0x2E,0x94,0x02,0x51,0x97,0x96,0x82,0x75,0x1C,0x7D,0x14,0x40,0x15,0x38,
- 0xB5,0x4D,0x17,0xBE,0xCE,0xDB,0x54,0x12,0x68,0xF6,0xCE,0xFA,0xE0,0x73,0xD3,0x3B,
- 0x7B,0x01,0xDC,0x43,0x17,0x46,0x00,0x2F,0x82,0x1F,0x4D,0x09,0x78,0x22,0x84,0x76,
- 0x2B,0xB6,0xA4,0xA8,0x87,0xC3,0x3F,0x13,0x4D,0x99,0xEF,0x23,0x52,0x92,0xCE,0x65,
- 0x1C,0x00,0x4A,0xCC,0xEE,0x3B,0x73,0xEB,0x52,0x86,0xA3,0xBC,0x22,0xAF,0xE2,0x88,
- 0x5A,0xED,0x34,0x51,0xC4,0x67,0x9F,0xA2,0x7E,0x4B,0xCC,0x65,0xFC,0xD6,0x38,0x42,
- 0x5A,0x24,0xB8,0x02,0x6F,0x99,0xA0,0xF7,0x38,0x86,0x8A,0x02,0xCD,0x28,0x9B,0xEA,
- 0xD9,0xA0,0x24,0x57,0x1E,0x40,0x02,0x89,0x29,0x4C,0x3F,0xF5,0xEF,0x8F,0xE7,0x4C,
- 0xDB,0x42,0xFA,0x8D,0x4C,0xD3,0x30,0xF7,0x71,0x7F,0xC2,0x41,0x66,0x19,0x7D,0x47,
- 0x99,0x26,0xF5,0x74,0x39,0xFE,0xB8,0xDF,0x60,0x36,0x02,0x0E,0x77,0x28,0x12,0x84,
-};
-
-/* subject:/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=Trust Settings Test Sub CA */
-/* issuer :/C=US/ST=California/L=Cupertino/O=Apple, Inc./OU=Security Engineering/CN=Trust Settings Test Root CA */
-unsigned char _trustSettingsInt[1016]={
- 0x30,0x82,0x03,0xF4,0x30,0x82,0x02,0xDC,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00,
- 0xBE,0x29,0xEC,0x6D,0x40,0x7E,0x44,0x9A,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,
- 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,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,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,
- 0x2C,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,
- 0x54,0x72,0x75,0x73,0x74,0x20,0x53,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x20,0x54,
- 0x65,0x73,0x74,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,
- 0x36,0x30,0x33,0x31,0x39,0x32,0x33,0x34,0x30,0x31,0x33,0x5A,0x17,0x0D,0x31,0x37,
- 0x30,0x33,0x31,0x39,0x32,0x33,0x34,0x30,0x31,0x33,0x5A,0x30,0x7C,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,
- 0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,
- 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,0x54,
- 0x72,0x75,0x73,0x74,0x20,0x53,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x20,0x54,0x65,
- 0x73,0x74,0x20,0x53,0x75,0x62,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,0xC3,0x98,0xDB,0xB7,0x52,0xC3,
- 0xC9,0xD3,0xB8,0x35,0x57,0xAE,0xF4,0x93,0x21,0xDD,0xAD,0x17,0xA8,0xE3,0x39,0xB0,
- 0x27,0xF3,0x9F,0x12,0x77,0xF3,0xF0,0x03,0xED,0xAE,0xE7,0x79,0x86,0x17,0x07,0x1C,
- 0xDE,0x34,0x41,0x25,0x39,0xCA,0xFE,0xD1,0x13,0x3B,0xBB,0x7E,0x77,0x7E,0x32,0x99,
- 0xDD,0xEB,0xBA,0xDC,0x6D,0xB9,0xF5,0x8A,0x1C,0x19,0x71,0xE3,0xE4,0x7F,0x39,0x0C,
- 0x3F,0x09,0x46,0x22,0x28,0x60,0x1A,0x42,0xA2,0x6E,0xE4,0x64,0xCF,0x02,0x68,0xAC,
- 0x74,0xD1,0xBD,0xE4,0xC7,0x69,0x90,0xA5,0xA4,0x4F,0x1C,0x6E,0x08,0x79,0x28,0xE8,
- 0x3E,0xE3,0x62,0x15,0xF8,0xB9,0xC1,0x56,0x1A,0xB0,0xE3,0x27,0x02,0xC6,0x29,0x20,
- 0x7B,0x34,0x54,0xCC,0x0F,0xDB,0x5B,0x5E,0x81,0x0F,0x20,0xB7,0xB4,0x43,0xB3,0x29,
- 0xE7,0xB7,0x83,0xCB,0x01,0xB3,0x57,0x3E,0x7B,0xBC,0x21,0x2F,0xED,0x24,0x99,0xB4,
- 0xCD,0x64,0x9F,0x47,0xA3,0x5E,0x7B,0x99,0x69,0x8D,0xEB,0x6C,0x9D,0x60,0x7C,0x2F,
- 0x2D,0xF5,0xC9,0x9D,0x11,0x7B,0x61,0x4A,0x0D,0x70,0x11,0x14,0x6C,0xE1,0xCB,0xC1,
- 0x20,0xAF,0x55,0xBF,0xBE,0x8B,0xB6,0x9A,0x03,0x6C,0xFD,0x7A,0xCF,0xFB,0x92,0xD1,
- 0x85,0xEE,0x5B,0x1E,0xEA,0xDC,0x58,0xF3,0xF1,0x0B,0x88,0x9E,0xA5,0xB4,0xD2,0xCD,
- 0x74,0x47,0x18,0xA8,0xE3,0xFD,0x45,0xC2,0xE1,0x4D,0x97,0x77,0x89,0x48,0xF9,0x66,
- 0xA4,0xEF,0x9E,0x33,0x3E,0xF0,0xED,0x55,0xF7,0x92,0xF4,0x1B,0xF7,0xF6,0xF9,0x90,
- 0xCE,0xD5,0xA1,0x3F,0xE7,0xB7,0x2E,0x33,0x8F,0x9D,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,0xFD,
- 0x26,0x89,0x9C,0xA6,0x9A,0xF6,0x33,0x48,0xA9,0x5D,0x0B,0xF6,0x90,0x2F,0xA6,0xC8,
- 0x22,0x30,0x70,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,
- 0x68,0x31,0x64,0x1E,0x5C,0x68,0x6A,0x83,0xBD,0x39,0x22,0x44,0xF6,0xD3,0x6C,0x70,
- 0xF7,0xDD,0x22,0x53,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,
- 0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0xA0,0xCA,0xAB,0x34,0xCF,0x6A,0x97,0x40,
- 0x58,0x49,0xEE,0xA5,0x03,0x98,0xDB,0x6B,0x8D,0x19,0x11,0x83,0x5C,0x52,0xA5,0xD0,
- 0xA2,0x3B,0x5E,0x59,0x13,0x53,0xCA,0xAA,0x6B,0x26,0x6D,0x14,0x4A,0x6D,0x8A,0x61,
- 0xA7,0xDD,0x3E,0x2D,0x8B,0x4A,0x62,0xA4,0x3D,0x06,0xEE,0x76,0xB5,0x6F,0x93,0x30,
- 0xD1,0x29,0xEA,0x34,0x01,0xB3,0x6B,0x1A,0xF3,0xCA,0x26,0x1E,0x76,0x2E,0x46,0xB3,
- 0x73,0xE1,0x97,0x95,0x2F,0x16,0xC8,0x1F,0xF8,0x79,0x0E,0xEA,0x36,0xB0,0xEA,0x49,
- 0xBE,0x5A,0x40,0xFE,0x83,0x51,0x94,0x78,0x74,0xD0,0x22,0x87,0x34,0xF5,0xEE,0x44,
- 0x55,0x4B,0x4A,0xFF,0xF9,0xCD,0x84,0x68,0x32,0x94,0x98,0xCF,0xE0,0x51,0x66,0xEC,
- 0x93,0x12,0x26,0x37,0xBD,0xA1,0x71,0x3B,0xF6,0x7A,0x40,0x48,0x62,0xC8,0xDD,0xE8,
- 0x74,0x2C,0x14,0x09,0x18,0xDA,0x23,0x85,0xFF,0x2A,0x65,0xBF,0x0E,0x72,0x32,0xE2,
- 0xD8,0x89,0x36,0x99,0x51,0x00,0xBD,0x16,0x48,0x46,0xFB,0x02,0xFA,0x7A,0xC3,0x73,
- 0xBC,0x3B,0xB4,0x34,0x1C,0xBD,0x63,0x8D,0x12,0x97,0x66,0x8E,0x89,0x6C,0x79,0x8C,
- 0xA9,0x77,0x49,0x92,0x7E,0xB2,0xF8,0xDE,0x58,0xB9,0xF1,0xEA,0xAF,0x74,0x94,0x46,
- 0x1A,0x7B,0x5F,0x65,0x8D,0x08,0x38,0xBA,0xE4,0xB2,0xC2,0x27,0x05,0x76,0x38,0x1F,
- 0x2B,0xFD,0x29,0x86,0xDA,0x38,0xB3,0x1E,0x37,0x38,0xE4,0x6F,0x81,0x35,0xA7,0x82,
- 0x85,0xF5,0x8B,0xEC,0x24,0xD1,0xA1,0x12,0xFB,0x54,0xC4,0x51,0xA4,0x97,0xF2,0x0B,
- 0xD4,0xE5,0x79,0x49,0x60,0x27,0x0D,0x5D,
-};
-
-/* subject:/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=Trust Settings Test SSL Leaf */
-/* issuer :/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=Trust Settings Test Sub CA */
-unsigned char _trustSettingsSSLLeaf[1059]={
- 0x30,0x82,0x04,0x1F,0x30,0x82,0x03,0x07,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00,
- 0x81,0x94,0x54,0x10,0xDC,0xA5,0x98,0x17,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,
- 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x7C,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,0x14,0x30,0x12,0x06,
- 0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,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,0x54,0x72,0x75,0x73,0x74,
- 0x20,0x53,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x20,0x54,0x65,0x73,0x74,0x20,0x53,
- 0x75,0x62,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x36,0x30,0x33,0x32,0x30,0x30,
- 0x30,0x31,0x30,0x35,0x37,0x5A,0x17,0x0D,0x31,0x37,0x30,0x33,0x32,0x30,0x30,0x30,
- 0x31,0x30,0x35,0x37,0x5A,0x30,0x7E,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,0x14,0x30,0x12,0x06,0x03,0x55,
- 0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,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,0x54,0x72,0x75,0x73,0x74,0x20,0x53,
- 0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x20,0x54,0x65,0x73,0x74,0x20,0x53,0x53,0x4C,
- 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,0xBC,0x1C,0xAC,0x0E,0x78,0xFC,0xFA,0x63,0x97,0x5B,
- 0xE3,0xFB,0xE9,0x31,0x60,0x9C,0xAE,0x81,0x9F,0xE1,0x19,0x95,0xF1,0xE2,0x27,0x14,
- 0x33,0x86,0xA3,0x11,0x16,0x35,0x36,0x93,0x05,0xB6,0x88,0xC1,0x97,0x52,0xAB,0x0D,
- 0xA6,0x22,0xF2,0x5E,0xDF,0x9E,0x27,0x9F,0x82,0x4F,0x0B,0xAD,0x96,0x9D,0xD4,0x7A,
- 0x85,0xEA,0x62,0x89,0x6E,0xD5,0xC1,0x0D,0xCD,0x0D,0x15,0x4D,0x66,0x1F,0xA9,0xA8,
- 0xB3,0xFA,0xC1,0x59,0x74,0x69,0xE6,0xA5,0x4A,0xF2,0xA3,0xC9,0x5F,0x29,0x7D,0x9E,
- 0x49,0x5B,0x02,0x41,0x11,0x80,0x5C,0xD0,0x69,0x41,0x7C,0x05,0xFB,0xBA,0x0B,0xB6,
- 0x10,0x6D,0x30,0xF3,0xB7,0x76,0x4A,0x32,0xCE,0xF0,0x50,0x74,0x70,0x1C,0x7A,0xE7,
- 0x05,0x2A,0x01,0x00,0xB0,0xBB,0x22,0xB0,0xAD,0x7C,0x19,0xFD,0x5A,0xE3,0xC5,0xCD,
- 0x51,0x15,0x97,0xF4,0xE4,0xEF,0x60,0x56,0x2C,0x92,0xB1,0xD4,0x9D,0xF9,0x26,0x1F,
- 0x0C,0x11,0x2F,0x2F,0xA5,0xFA,0xD6,0x8E,0x87,0x1D,0xCC,0xA7,0xA0,0x3C,0x23,0xBB,
- 0x52,0x30,0x11,0x13,0x43,0x7C,0xFE,0x63,0xEE,0xAE,0xAF,0xE6,0xED,0x07,0xD2,0x89,
- 0xCB,0xC0,0xFE,0xF1,0xBF,0x75,0x18,0xA8,0xFF,0x34,0x9A,0x5C,0x28,0xEC,0x18,0x55,
- 0x68,0xF7,0x24,0x30,0x94,0x49,0x23,0xCB,0xF1,0xE3,0xBE,0x1D,0x51,0xA3,0x2B,0x21,
- 0x7D,0xFC,0x6E,0x93,0x19,0xE7,0xA5,0x26,0xFE,0xE2,0x5D,0xED,0x4A,0xD4,0xB9,0x60,
- 0xE4,0xE7,0x77,0xA8,0xFF,0x13,0x06,0x0D,0x58,0x82,0x25,0x6D,0xEB,0xAC,0xA9,0x56,
- 0xF9,0x2C,0x60,0xBB,0x66,0x77,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0xA1,0x30,0x81,
- 0x9E,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,
- 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,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,0xC6,0xED,0xD2,0x4E,0x23,0xC9,
- 0xA9,0xC8,0x64,0x3A,0x55,0x51,0x0F,0x27,0x52,0xD6,0x18,0x12,0x66,0xC8,0x30,0x1F,
- 0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xFD,0x26,0x89,0x9C,0xA6,
- 0x9A,0xF6,0x33,0x48,0xA9,0x5D,0x0B,0xF6,0x90,0x2F,0xA6,0xC8,0x22,0x30,0x70,0x30,
- 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,
- 0x01,0x01,0x00,0xB1,0x56,0x55,0xC7,0x1F,0xF6,0x15,0x59,0xA6,0x0B,0xC4,0xBB,0x48,
- 0x53,0x1B,0xE7,0xC1,0x7F,0x72,0x65,0x0E,0xE9,0x08,0x22,0xF6,0x30,0x9C,0xB3,0xCA,
- 0xCF,0xDE,0x16,0x2C,0x90,0x30,0x59,0xC4,0xB2,0xE7,0x1E,0xD2,0xF3,0xD6,0x29,0x94,
- 0xA3,0xD5,0xFA,0x98,0xC1,0xBF,0xD7,0xC3,0x52,0xBC,0xFF,0x6D,0xB6,0xE1,0xCE,0x1A,
- 0x59,0xF9,0x68,0x6D,0x98,0x8B,0x48,0x7D,0xE6,0xD0,0x1F,0xFE,0xF7,0x9C,0x73,0x09,
- 0x73,0x9B,0x5D,0xAF,0x88,0x37,0x35,0x1C,0x3F,0x9A,0x07,0xE0,0x3B,0x29,0x24,0x7F,
- 0x04,0x9A,0xD2,0x3F,0xDE,0xF3,0x68,0x1D,0x16,0x8D,0xD0,0x4F,0xB6,0x83,0x19,0x70,
- 0xBB,0x1F,0x21,0x91,0x49,0x3F,0x12,0x89,0xF6,0x88,0x8A,0x2F,0xDC,0x55,0x54,0xBE,
- 0x78,0xDD,0x2F,0xC9,0x0C,0x7B,0x8C,0xA8,0x33,0x33,0x1D,0xA0,0x6D,0xA4,0xA6,0x6A,
- 0xA4,0x49,0xD6,0x37,0x6D,0x95,0x15,0x0C,0xFA,0xA5,0xCF,0x5A,0x28,0xD9,0x37,0x5D,
- 0xC5,0xC5,0x3A,0x30,0x8D,0x54,0xE4,0xAB,0x19,0x7A,0xF0,0x33,0xAE,0x64,0xA9,0x42,
- 0x83,0xD2,0xF2,0x68,0x39,0xA2,0xE1,0x71,0x68,0x19,0x81,0x5A,0x9B,0xB4,0xDD,0xBC,
- 0xA6,0xC7,0x19,0x40,0x87,0x50,0x6F,0x49,0xD2,0xC1,0x92,0x57,0xE4,0x5B,0x5F,0x41,
- 0x85,0x22,0x33,0x8D,0xC7,0x0B,0x3F,0x55,0xC1,0x46,0x2C,0xB6,0xDE,0xF7,0x80,0x54,
- 0xA5,0x62,0x0E,0xA3,0x24,0x14,0x9B,0xF1,0xEE,0x9D,0x7F,0x65,0xA2,0x1D,0x0C,0x32,
- 0x86,0x81,0xDE,0xDC,0xD7,0xB6,0x06,0x3A,0xF6,0xF0,0x81,0x6A,0xBE,0xC4,0xA0,0x87,
- 0xEA,0x6A,0x6C,
-};
-
-/* subject:/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=Trust Settings Test SMIME Leaf */
-/* issuer :/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=Trust Settings Test Sub CA */
-unsigned char _trustSettingsSMIMELeaf[1050]={
- 0x30,0x82,0x04,0x16,0x30,0x82,0x02,0xFE,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00,
- 0x81,0x94,0x54,0x10,0xDC,0xA5,0x98,0x18,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,
- 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x7C,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,0x14,0x30,0x12,0x06,
- 0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,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,0x54,0x72,0x75,0x73,0x74,
- 0x20,0x53,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x20,0x54,0x65,0x73,0x74,0x20,0x53,
- 0x75,0x62,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x36,0x30,0x33,0x32,0x30,0x30,
- 0x30,0x31,0x31,0x35,0x32,0x5A,0x17,0x0D,0x31,0x37,0x30,0x33,0x32,0x30,0x30,0x30,
- 0x31,0x31,0x35,0x32,0x5A,0x30,0x81,0x80,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,0x14,0x30,0x12,0x06,0x03,
- 0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,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,0x75,0x73,0x74,0x20,
- 0x53,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x20,0x54,0x65,0x73,0x74,0x20,0x53,0x4D,
- 0x49,0x4D,0x45,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,0xE7,0x42,0xF7,0x3B,0x41,0xB4,0x91,
- 0xF6,0xC3,0x4F,0x5B,0x52,0x9C,0x4D,0x1E,0x0D,0x1F,0x1A,0xE8,0x07,0x14,0x00,0x48,
- 0x00,0x18,0x13,0xA6,0xD0,0xC4,0x49,0x6A,0xC7,0x47,0xBE,0xC6,0x07,0x9F,0xED,0x81,
- 0xC8,0x49,0x7C,0xC8,0x69,0x14,0x2D,0xAD,0xD4,0x98,0x58,0x1A,0x6D,0xCC,0x28,0x54,
- 0xA1,0x13,0xAF,0x2A,0xB5,0xF5,0x4B,0x6F,0x97,0x85,0x33,0xE0,0x12,0xF8,0x06,0x95,
- 0xA0,0x57,0x81,0xD1,0x51,0x4E,0x1B,0x29,0x80,0x9F,0x3C,0x49,0x34,0x28,0x61,0x59,
- 0x6A,0x56,0xA1,0x13,0x52,0x1B,0x41,0x6E,0xE2,0xA7,0xE1,0x6E,0x10,0xCC,0x07,0x48,
- 0x0C,0x36,0x25,0x35,0xD3,0xBB,0x8F,0x45,0xF9,0x37,0x4D,0xB4,0xC7,0x9E,0xFA,0x7F,
- 0x99,0xFC,0xB5,0x35,0xD7,0x96,0xC6,0xF7,0xF0,0x19,0x34,0xB6,0xD9,0x3C,0x82,0x38,
- 0xBF,0x23,0x04,0x21,0x4A,0xFC,0xC1,0x8C,0x89,0xB1,0x45,0xFC,0x9B,0x4D,0xAE,0x28,
- 0x4F,0xF6,0xD3,0x69,0xBB,0x3B,0xC5,0x5F,0x72,0xC7,0xD3,0xDF,0x70,0x97,0x7B,0xEE,
- 0xD6,0x09,0xD6,0x21,0xF3,0xCF,0x8D,0x50,0xAF,0x48,0xDA,0x2C,0xEB,0x90,0x8E,0x1D,
- 0xEE,0x94,0xA7,0xAB,0x21,0x0E,0xC8,0xE2,0xA1,0x7F,0x36,0x98,0x1A,0x99,0xDD,0x85,
- 0x3A,0xEE,0xF0,0xE6,0x34,0x15,0x98,0x6D,0xA8,0x22,0x4E,0x4F,0x54,0x06,0xF1,0x1F,
- 0xE0,0xDD,0x8E,0xB1,0xA5,0x94,0xA2,0xC5,0xD2,0xA3,0xEA,0xD9,0xD9,0x28,0x1B,0x4B,
- 0x98,0x82,0x89,0x18,0x2D,0x7B,0x17,0xD6,0x92,0x5F,0x20,0x44,0xAF,0xD5,0x27,0x02,
- 0x2C,0x2E,0x8F,0x14,0x20,0x70,0xA1,0xD4,0x65,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,
- 0x95,0x30,0x81,0x92,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,
- 0x30,0x00,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,
- 0x06,0x01,0x05,0x05,0x07,0x03,0x04,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,
- 0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x1D,0x06,0x03,0x55,0x1D,0x11,0x04,0x16,
- 0x30,0x14,0x81,0x12,0x75,0x73,0x65,0x72,0x6E,0x61,0x6D,0x65,0x40,0x61,0x70,0x70,
- 0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,
- 0x14,0xC6,0xD8,0x0B,0xD7,0xD4,0x9E,0x84,0x41,0xB3,0x59,0x05,0x41,0xDF,0xC3,0x2A,
- 0x77,0xBB,0x41,0x20,0x85,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,
- 0x80,0x14,0xFD,0x26,0x89,0x9C,0xA6,0x9A,0xF6,0x33,0x48,0xA9,0x5D,0x0B,0xF6,0x90,
- 0x2F,0xA6,0xC8,0x22,0x30,0x70,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,
- 0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x4B,0x02,0x37,0x7F,0xBA,0x3D,
- 0xD5,0xDF,0xE9,0xD6,0x52,0x6D,0x39,0x23,0x83,0x1B,0xFB,0x17,0x15,0x1A,0x45,0x9E,
- 0xF2,0x55,0xA3,0x2C,0x18,0xF1,0x01,0xA1,0x2D,0xAA,0x78,0x39,0xA8,0x5A,0xD5,0x9E,
- 0x37,0xE4,0x50,0x31,0x7A,0x07,0x61,0xD8,0xE9,0x2A,0x32,0x1F,0x04,0x3F,0x27,0x03,
- 0xDC,0x77,0x7F,0x1B,0xD7,0x45,0x55,0x1F,0x5B,0xCC,0x7A,0xF1,0x5C,0x74,0x9E,0xA5,
- 0x2A,0xA3,0xAC,0x63,0xBE,0x8B,0xEB,0x38,0x39,0xEC,0x53,0x9E,0x09,0x5A,0x86,0x2D,
- 0x25,0x9C,0x78,0x85,0x02,0x07,0xE5,0xE2,0x98,0xB3,0x70,0x50,0x1A,0xAE,0x4F,0xF4,
- 0x9F,0x89,0xA9,0x84,0xBF,0x6F,0x03,0x42,0x6B,0x12,0x0A,0x15,0x73,0x3F,0xC6,0x8B,
- 0x32,0xDA,0x52,0x17,0xC5,0xC2,0x96,0x68,0xF7,0x31,0x1B,0x5D,0xB1,0x49,0x4C,0x2D,
- 0xE7,0x3E,0x42,0xD6,0xF1,0x14,0xA9,0xBE,0x2F,0xD9,0x65,0xEB,0x0F,0x51,0x58,0x09,
- 0x7D,0x4D,0x07,0x4B,0xE4,0x49,0x13,0x8B,0x70,0xA9,0x90,0x6C,0x9F,0x10,0xD2,0x8B,
- 0x90,0xBE,0x63,0xF9,0x8E,0xF8,0x73,0x22,0xBE,0x54,0xEE,0x96,0x56,0x66,0xBC,0x2F,
- 0x2A,0xC6,0x6B,0x84,0x67,0x4D,0xD8,0xF7,0xBA,0xCD,0x75,0x3B,0x73,0xEF,0x05,0x46,
- 0x52,0xA4,0xF9,0xA7,0x03,0x29,0xA4,0x9A,0x11,0xAE,0x79,0xE5,0x53,0x3E,0xC5,0xD7,
- 0x75,0x39,0x2D,0x82,0xC3,0x60,0x5F,0x12,0x9B,0x90,0x19,0xD6,0xB1,0xA4,0xF7,0x8B,
- 0x62,0xF9,0x44,0x4E,0x15,0xA5,0xD3,0xFF,0x75,0x4E,0x44,0x84,0x78,0xCF,0x68,0x18,
- 0xFE,0x46,0xEB,0xFE,0x0E,0x11,0xCB,0x34,0x53,0xAB,
-};
-
-/* subject:/CN=Apple Corporate Root CA/OU=Certification Authority/O=Apple Inc./C=US */
-/* issuer :/CN=Apple Corporate Root CA/OU=Certification Authority/O=Apple Inc./C=US */
-uint8_t _corporateRoot[] = {
- 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,
-};
-
-/* subject:/CN=Apple Corporate Server CA 1/OU=Certification Authority/O=Apple Inc./C=US */
-/* issuer :/CN=Apple Corporate Root CA/OU=Certification Authority/O=Apple Inc./C=US */
-uint8_t _corporateServerCA[] = {
- 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,
-};
-
-/* subject:/CN=bbasile-test.scv.apple.com/OU=management:idms.group.631731/O=Apple Inc./ST=California/C=US */
-/* issuer :/CN=Apple Corporate Server CA 1/OU=Certification Authority/O=Apple Inc./C=US */
-uint8_t _corporateServerCert[] = {
- 0x30,0x82,0x05,0xF4,0x30,0x82,0x04,0xDC,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x54,
- 0x32,0x9C,0xE6,0xE6,0xD7,0x87,0x7E,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,0x31,0x38,0x30,0x39,0x32,0x37,0x30,0x34,0x32,0x30,
- 0x34,0x31,0x5A,0x17,0x0D,0x32,0x30,0x31,0x30,0x32,0x36,0x30,0x34,0x32,0x30,0x34,
- 0x31,0x5A,0x30,0x81,0x83,0x31,0x23,0x30,0x21,0x06,0x03,0x55,0x04,0x03,0x0C,0x1A,
- 0x62,0x62,0x61,0x73,0x69,0x6C,0x65,0x2D,0x74,0x65,0x73,0x74,0x2E,0x73,0x63,0x76,
- 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,0x33,0x31,0x37,0x33,
- 0x31,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,0xAF,0x8C,0xB9,0x3F,0x56,0x41,0xF9,
- 0xA5,0x93,0x89,0x95,0x58,0x31,0x90,0x84,0xD5,0x3E,0xBB,0xE4,0x7C,0x68,0xD4,0x5B,
- 0x95,0x97,0x04,0xEF,0xE6,0x3C,0x8E,0x6A,0x98,0xD0,0xAD,0xDD,0x7A,0xF1,0x5E,0x4D,
- 0xCF,0x40,0xEF,0x05,0xF7,0x02,0x8C,0x01,0x0B,0x74,0x9D,0x0C,0x7E,0xD1,0xF8,0x80,
- 0x6E,0xAA,0xBF,0x96,0xB3,0x50,0x8F,0xB4,0x68,0x0C,0xFA,0xD0,0xDB,0xE7,0x93,0xA0,
- 0x6A,0x84,0xF2,0xA3,0x90,0x62,0x54,0xBD,0xB0,0xB3,0x1F,0xD6,0x0E,0xD1,0x2B,0xBA,
- 0x13,0x38,0x0A,0xD1,0x84,0x36,0x75,0x77,0xFB,0x3B,0x1E,0x61,0x1B,0x85,0x22,0xA9,
- 0xF9,0x42,0xD6,0xA2,0x9B,0xCB,0x34,0x76,0xC0,0xAE,0x2B,0xB0,0x64,0x95,0x5B,0xC7,
- 0x61,0x2A,0x0B,0x81,0xE0,0x01,0x34,0xB8,0x50,0xDC,0x26,0x77,0x55,0xF7,0x95,0xE1,
- 0xEC,0x01,0x4F,0xA8,0x0E,0x89,0x25,0xFE,0x8E,0xAB,0x40,0x6E,0x17,0x14,0xAA,0xA8,
- 0x6C,0x79,0x52,0xDC,0xE3,0xDA,0x15,0xBF,0xAF,0x3C,0x96,0x2B,0xA3,0x4D,0xFA,0xC5,
- 0xB5,0x36,0xCD,0x2F,0x88,0xFF,0xD1,0x1E,0xB1,0xE6,0x7C,0x0E,0xBD,0x60,0x0A,0x78,
- 0xF7,0x8A,0x22,0x86,0xAD,0xC7,0x43,0x73,0xD7,0x22,0x64,0x32,0xA8,0xEC,0xEB,0x4F,
- 0x41,0x90,0xCC,0x2F,0xB5,0x1A,0xA4,0xE6,0x91,0x34,0x86,0xCA,0x0A,0x17,0x0B,0x28,
- 0x5F,0x94,0xAE,0x4C,0xDB,0x94,0x7A,0xD9,0xC3,0x4A,0x09,0x11,0xFA,0x33,0x6A,0x99,
- 0x85,0x66,0x12,0x0A,0x70,0x7D,0x99,0x88,0xBE,0xC8,0x4E,0xCF,0x01,0xD8,0xD1,0x54,
- 0x46,0x85,0x66,0x31,0x37,0xB3,0x7E,0x0F,0x45,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,
- 0x02,0x82,0x30,0x82,0x02,0x7E,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,0x25,0x06,0x03,0x55,
- 0x1D,0x11,0x04,0x1E,0x30,0x1C,0x82,0x1A,0x62,0x62,0x61,0x73,0x69,0x6C,0x65,0x2D,
- 0x74,0x65,0x73,0x74,0x2E,0x73,0x63,0x76,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,
- 0x62,0xF3,0x37,0xB1,0x58,0x48,0x8F,0x49,0xEA,0x12,0x39,0x93,0x4C,0x17,0x91,0x07,
- 0x2F,0x71,0x09,0x4B,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,0xE3,0xCE,0x7C,0xAC,0x0A,0xDE,0x21,0xB9,
- 0xB0,0x9E,0x1C,0xE9,0x6B,0xD5,0xBC,0xB7,0x53,0xE7,0x16,0x62,0xB0,0x1D,0x3E,0x53,
- 0xFE,0x47,0x1A,0x1A,0xA3,0x7A,0x69,0xC5,0xC0,0x8B,0xC9,0x0B,0xE1,0xBC,0xF6,0xE6,
- 0xAC,0x7E,0x05,0x60,0xC2,0xC2,0x3C,0xBA,0xB4,0x39,0xF7,0xDD,0xA4,0x60,0xC8,0x5B,
- 0x29,0x90,0x59,0x29,0xCF,0xC1,0x6D,0x38,0x38,0x83,0x81,0xFA,0x8A,0xB6,0x13,0xE6,
- 0xC6,0xDA,0x64,0xD5,0x19,0x40,0x82,0x8C,0x38,0xC9,0xBE,0xC4,0x81,0xBA,0x88,0xC6,
- 0x62,0xEC,0x42,0xED,0xCE,0x22,0xD2,0x52,0xE2,0x96,0x8C,0x3C,0xBC,0xCA,0xD4,0xF0,
- 0xC8,0x24,0x09,0xA1,0xC6,0xD3,0x44,0x4F,0x22,0x36,0xF8,0x6F,0x28,0x20,0x9C,0x0C,
- 0x71,0x10,0xCC,0x13,0x46,0x40,0xCF,0x15,0xF6,0x16,0x59,0xB2,0xC4,0xE6,0xDA,0x3D,
- 0x9C,0xB4,0x01,0x33,0x4E,0x01,0x87,0xFC,0xEB,0x4B,0x45,0x0E,0x6C,0x14,0x93,0x48,
- 0xA0,0x78,0xFA,0x0C,0x01,0xB0,0xEB,0xF1,0x6F,0x7B,0xE9,0xF4,0xED,0x42,0x92,0x07,
- 0x3B,0xFC,0x14,0x15,0x69,0xE7,0x1E,0x33,0xD8,0x7C,0xE1,0xD6,0x37,0xBB,0x13,0x50,
- 0x3E,0x3C,0x4A,0xD4,0x29,0xC7,0x29,0x3B,0x99,0x79,0xD5,0x92,0x96,0x64,0x28,0x0A,
- 0x7A,0x4F,0x8C,0x4A,0x32,0xC6,0x49,0x9D,0x05,0x0E,0x25,0x2F,0x46,0x6D,0x60,0x83,
- 0xA6,0x06,0x05,0x07,0x3F,0x50,0xFF,0x01,0x6C,0x3E,0xE2,0x71,0x09,0x74,0xD2,0x94,
- 0xEB,0x17,0xF4,0xE7,0x2B,0xB0,0xFD,0x41,0x52,0xEF,0x25,0x71,0x9C,0x1C,0x36,0xA6,
- 0x05,0x15,0xA6,0xD5,0x1E,0x23,0xB7,0xC2,
-};
-
-#endif /* si_28_sectrustsettings_h */
+++ /dev/null
-/*
- * Copyright (c) 2008-2010,2012,2016 Apple Inc. All Rights Reserved.
- */
-
-#include <Foundation/Foundation.h>
-#include <Security/SecCertificate.h>
-#include <Security/SecCertificatePriv.h>
-#include <Security/SecItem.h>
-#include <Security/SecItemPriv.h>
-#include <Security/SecPolicy.h>
-#include <Security/SecPolicyPriv.h>
-#include <Security/SecTrust.h>
-#include <Security/SecTrustSettings.h>
-#include <Security/SecTrustSettingsPriv.h>
-#include <Security/SecTrustPriv.h>
-#include <utilities/SecCFRelease.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#if TARGET_OS_IPHONE
-#include <Security/SecTrustStore.h>
-#else
-#include <Security/SecKeychain.h>
-#endif
-
-#include "shared_regressions.h"
-
-#include "si-28-sectrustsettings.h"
-
-/* 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) \
-{ \
- ok_status(SecTrustStoreSetTrustSettings(defaultStore, cert, settings), \
- "set trust settings"); \
-}
-#else
-/* Use admin store on OS X to avoid user prompts.
- * Sleep a little so trustd has time to get the KeychainEvent. */
-#define setTS(cert, settings) \
-{ \
- ok_status(SecTrustSettingsSetTrustSettings(cert, kSecTrustSettingsDomainAdmin, \
- settings), "set trust settings"); \
- usleep(20000); \
-}
-#endif
-
-#if TARGET_OS_IPHONE
-#define setTSFail(cert, settings) \
-{ \
- is(SecTrustStoreSetTrustSettings(defaultStore, cert, settings), errSecParam, \
- "set trust settings"); \
-}
-#else
-#define setTSFail(cert, settings) \
-{ \
- is(SecTrustSettingsSetTrustSettings(cert, kSecTrustSettingsDomainAdmin, \
- settings), errSecParam, "set trust settings"); \
-}
-#endif
-
-/* each call is 1 test */
-#define kNumberRemoveTSTests 1
-#if TARGET_OS_IPHONE
-#define removeTS(cert) \
-{ \
- ok_status(SecTrustStoreRemoveCertificate(defaultStore, cert), \
- "remove trust settings"); \
-}
-#else
-#define removeTS(cert) \
-{ \
- ok_status(SecTrustSettingsRemoveTrustSettings(cert, kSecTrustSettingsDomainAdmin), \
- "remove trust settings"); \
-}
-#endif
-
-/* each call is 4 tests */
-#define kNumberCheckTrustTests 4
-#define check_trust(certs, policy, valid_date, expected) \
-{ \
- SecTrustRef trust = NULL; \
- SecTrustResultType trust_result; \
- ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), \
- "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"); \
- is(trust_result, expected, \
- "check trust result for " #policy " policy"); \
- CFReleaseSafe(trust); \
-}
-
-static SecCertificateRef cert0 = NULL;
-static SecCertificateRef cert1 = NULL;
-static SecCertificateRef cert2 = NULL;
-static SecCertificateRef cert3 = NULL;
-static SecPolicyRef sslPolicy = NULL;
-static SecPolicyRef smimePolicy = NULL;
-static SecPolicyRef basicPolicy = NULL;
-static CFArrayRef sslChain = NULL;
-static CFArrayRef smimeChain = NULL;
-static NSDate *verify_date = nil;
-
-#if TARGET_OS_IPHONE
-static SecTrustStoreRef defaultStore = NULL;
-#else
-#define kSystemLoginKeychainPath "/Library/Keychains/System.keychain"
-static NSMutableArray *deleteMeCertificates = NULL;
-#endif
-
-
-static void setup_globals(void) {
-
- cert0 = SecCertificateCreateWithBytes(NULL, _trustSettingsRoot, sizeof(_trustSettingsRoot));
- cert1 = SecCertificateCreateWithBytes(NULL, _trustSettingsInt, sizeof(_trustSettingsInt));
- cert2 = SecCertificateCreateWithBytes(NULL, _trustSettingsSSLLeaf, sizeof(_trustSettingsSSLLeaf));
- cert3 = SecCertificateCreateWithBytes(NULL, _trustSettingsSMIMELeaf, sizeof(_trustSettingsSMIMELeaf));
-
- sslPolicy = SecPolicyCreateSSL(true, CFSTR("testserver.apple.com"));
- smimePolicy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME, CFSTR("username@apple.com"));
- basicPolicy = SecPolicyCreateBasicX509();
-
- const void *v_certs1[] = { cert2, cert1, cert0 };
- sslChain = CFArrayCreate(NULL, v_certs1, sizeof(v_certs1)/sizeof(*v_certs1), &kCFTypeArrayCallBacks);
-
- const void *v_certs2[] = { cert3, cert1, cert0 };
- smimeChain = CFArrayCreate(NULL, v_certs2, sizeof(v_certs2)/sizeof(*v_certs2), &kCFTypeArrayCallBacks);
-
- verify_date = [NSDate dateWithTimeIntervalSinceReferenceDate:482000000.0]; // Apr 10 2016
-
-#if TARGET_OS_IPHONE
- defaultStore = SecTrustStoreForDomain(kSecTrustStoreDomainUser);
-#else
- /* Since we're putting trust settings in the admin domain,
- * we need to add the certs to the system keychain. */
- SecKeychainRef kcRef = NULL;
- CFArrayRef certRef = NULL;
- NSDictionary *attrs = nil;
-
- SecKeychainOpen(kSystemLoginKeychainPath, &kcRef);
- if (!kcRef) {
- goto out;
- }
-
- deleteMeCertificates = [[NSMutableArray alloc] init];
-
- attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)cert0,
- (__bridge NSString*)kSecUseKeychain: (__bridge id)kcRef,
- (__bridge NSString*)kSecReturnPersistentRef: @YES};
- if (SecItemAdd((CFDictionaryRef)attrs, (void *)&certRef) == 0)
- [deleteMeCertificates addObject:(__bridge NSArray *)certRef];
- CFReleaseNull(certRef);
-
- attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)cert1,
- (__bridge NSString*)kSecUseKeychain: (__bridge id)kcRef,
- (__bridge NSString*)kSecReturnPersistentRef: @YES};
- if (SecItemAdd((CFDictionaryRef)attrs, (void *)&certRef) == 0)
- [deleteMeCertificates addObject:(__bridge NSArray *)certRef];
- CFReleaseNull(certRef);
-
- attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)cert2,
- (__bridge NSString*)kSecUseKeychain: (__bridge id)kcRef,
- (__bridge NSString*)kSecReturnPersistentRef: @YES};
- if (SecItemAdd((CFDictionaryRef)attrs, (void *)&certRef) == 0)
- [deleteMeCertificates addObject:(__bridge NSArray *)certRef];
- CFReleaseNull(certRef);
-
- attrs = @{(__bridge NSString*)kSecValueRef: (__bridge id)cert3,
- (__bridge NSString*)kSecUseKeychain: (__bridge id)kcRef,
- (__bridge NSString*)kSecReturnPersistentRef: @YES};
- if (SecItemAdd((CFDictionaryRef)attrs, (void *)&certRef) == 0)
- [deleteMeCertificates addObject:(__bridge NSArray *)certRef];
- CFReleaseNull(certRef);
-
- out:
- CFReleaseNull(kcRef);
-#endif
-}
-
-static void cleanup_globals(void) {
-#if !TARGET_OS_IPHONE
- [deleteMeCertificates enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
- SecItemDelete((CFDictionaryRef)@{ (__bridge NSString*)kSecValuePersistentRef: [obj objectAtIndex:0]});
- }];
-#endif
-
- CFReleaseNull(cert0);
- CFReleaseNull(cert1);
- CFReleaseNull(cert2);
- CFReleaseNull(cert3);
- CFReleaseNull(sslPolicy);
- CFReleaseNull(smimePolicy);
- CFReleaseNull(basicPolicy);
- CFReleaseNull(sslChain);
- CFReleaseNull(smimeChain);
-}
-
-#define kNumberNoConstraintsTests (17+7*4)
-static void test_no_constraints(void) {
- /* root with the default TrustRoot result succeeds */
- setTS(cert0, NULL);
- check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
- removeTS(cert0);
-
- /* intermediate with the default TrustRoot result fails */
- setTSFail(cert1, NULL);
-
- /* root with TrustRoot result succeeds */
- NSDictionary *trustRoot = @{ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)};
- setTS(cert0, (__bridge CFDictionaryRef)trustRoot);
- check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
- removeTS(cert0);
-
- /* intermediate with TrustRoot fails to set */
- setTSFail(cert1, (__bridge CFDictionaryRef)trustRoot);
-
- /* root with TrustAsRoot fails to set */
- NSDictionary *trustAsRoot = @{ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot)};
- setTSFail(cert0, (__bridge CFDictionaryRef)trustAsRoot);
-
- /* intermediate with TrustAsRoot result succeeds */
- setTS(cert1, (__bridge CFDictionaryRef)trustAsRoot);
- check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
- removeTS(cert1);
-
- /* trusting the root but denying the intermediate fails */
- NSDictionary *deny = @{ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny)};
- setTS(cert0, NULL);
- setTS(cert1, (__bridge CFDictionaryRef)deny);
- check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultDeny);
- removeTS(cert1);
- removeTS(cert0);
-
- /* the unspecified result gives us default behavior */
- NSDictionary *unspecified = @{ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)};
- setTS(cert1, (__bridge CFDictionaryRef)unspecified);
- check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
- removeTS(cert1);
-
- /* trusting one leaf doesn't make other leaf trusted */
- setTS(cert2, (__bridge CFDictionaryRef)trustAsRoot);
- check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
- check_trust(smimeChain, basicPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
- removeTS(cert2);
-}
-
-#define kNumberPolicyConstraintsTests (2+3*4)
-static void test_policy_constraints(void) {
- /* Trust only for SSL server. SSL server policy succeeds. */
- NSDictionary *sslServerAllowed = @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy,
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot) };
- setTS(cert1, (__bridge CFDictionaryRef)sslServerAllowed);
- check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultProceed);
-
- /* SSL client policy fails. */
- SecPolicyRef sslClient = SecPolicyCreateSSL(false, NULL);
- check_trust(sslChain, sslClient, verify_date, kSecTrustResultRecoverableTrustFailure);
- CFReleaseNull(sslClient);
-
- /* Basic policy fails */
- check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
- removeTS(cert1);
-}
-
-#define kNumberPolicyStringConstraintsTests (4+6*4)
-static void test_policy_string_constraints(void) {
- NSArray *hostnameAllowed = @[ @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy,
- (__bridge NSString*)kSecTrustSettingsPolicyString: @("wrongname.apple.com"),
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny) },
- @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy,
- (__bridge NSString*)kSecTrustSettingsPolicyString: @("testserver.apple.com"),
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot) }
- ];
- setTS(cert2, (__bridge CFArrayRef)hostnameAllowed);
- /* evaluating against trusted hostname passes */
- check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultProceed);
-
- /* evaluating against hostname not in trust settings is recoverable failure */
- SecPolicyRef weirdnamePolicy = SecPolicyCreateSSL(true, CFSTR("weirdname.apple.com"));
- check_trust(sslChain, weirdnamePolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
- CFReleaseNull(weirdnamePolicy);
-
- /* evaluating against hostname denied by trust settings is denied */
- SecPolicyRef wrongnamePolicy = SecPolicyCreateSSL(true, CFSTR("wrongname.apple.com"));
- check_trust(sslChain, wrongnamePolicy, verify_date, kSecTrustResultDeny);
- CFReleaseNull(wrongnamePolicy);
- removeTS(cert2);
-
- NSArray *emailAllowed = @[ @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)smimePolicy,
- (__bridge NSString*)kSecTrustSettingsPolicyString: @("wrongemail@apple.com"),
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny) },
- @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)smimePolicy,
- (__bridge NSString*)kSecTrustSettingsPolicyString: @("username@apple.com"),
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot) }
- ];
- setTS(cert3, (__bridge CFArrayRef)emailAllowed);
- /* evaluating against trusted email passes */
- check_trust(smimeChain, smimePolicy, verify_date, kSecTrustResultProceed);
-
- /* evaluating against hostname not in trust settings is recoverable failure */
- SecPolicyRef weirdemailPolicy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME, CFSTR("weirdemail@apple.com"));
- check_trust(smimeChain, weirdemailPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
- CFReleaseNull(weirdemailPolicy);
-
- /* evaluating against hostname denied by trust settings is denied */
- SecPolicyRef wrongemailPolicy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME, CFSTR("wrongemail@apple.com"));
- check_trust(smimeChain, wrongemailPolicy, verify_date, kSecTrustResultDeny);
- CFReleaseNull(wrongemailPolicy);
- removeTS(cert3);
-}
-
-#if TARGET_OS_IPHONE
-#define kNumberApplicationsConstraintsTests 0
-static void test_application_constraints(void) {}
-#else
-#include <Security/SecTrustedApplicationPriv.h>
-#define kNumberApplicationsConstraintsTests (2+4+2*4)
-static void test_application_constraints(void) {
- SecTrustedApplicationRef thisApp = NULL, someOtherApp = NULL;
-
- ok_status(SecTrustedApplicationCreateFromPath(NULL, &thisApp),
- "create TrustedApplicationRef for this app");
- ok_status(SecTrustedApplicationCreateFromPath("/Applications/Safari.app", &someOtherApp),
- "create TrustedApplicationRef for Safari");
-
- NSDictionary *thisAppTS = @{ (__bridge NSString*)kSecTrustSettingsApplication: (__bridge id)thisApp,
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)};
-
- NSDictionary *someOtherAppTS = @{ (__bridge NSString*)kSecTrustSettingsApplication: (__bridge id)someOtherApp,
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)};
-
- /* This application Trust Setting succeeds */
- setTS(cert0, (__bridge CFDictionaryRef)thisAppTS);
- check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
- removeTS(cert0);
-
- /* Some other application Trust Setting fails */
- setTS(cert0, (__bridge CFDictionaryRef)someOtherAppTS);
- check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
- removeTS(cert0);
-
- CFReleaseNull(thisApp);
- CFReleaseNull(someOtherApp);
-}
-#endif
-
-#define kNumberKeyUsageConstraintsTests (14+11*4)
-static void test_key_usage_constraints(void) {
- /* any key usage succeeds */
- NSDictionary *anyKeyUse = @{ (__bridge NSString*)kSecTrustSettingsKeyUsage: @(kSecTrustSettingsKeyUseAny),
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)};
- setTS(cert0, (__bridge CFDictionaryRef)anyKeyUse);
- check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
- removeTS(cert0);
-
- /* signCert key usage on an intermediate or root succeeds */
- NSDictionary *signCertUseRoot = @{ (__bridge NSString*)kSecTrustSettingsKeyUsage: @(kSecTrustSettingsKeyUseSignCert),
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)};
- setTS(cert0, (__bridge CFDictionaryRef)signCertUseRoot);
- check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
- removeTS(cert0)
-
- NSDictionary *signCertUseInt = @{ (__bridge NSString*)kSecTrustSettingsKeyUsage: @(kSecTrustSettingsKeyUseSignCert),
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot)};
- setTS(cert1, (__bridge CFDictionaryRef)signCertUseInt);
- check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
- removeTS(cert1);
-
- /* intermediate without signCert key usage fails */
- NSDictionary *signatureUse = @{ (__bridge NSString*)kSecTrustSettingsKeyUsage: @(kSecTrustSettingsKeyUseSignature),
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot)};
- setTS(cert1, (__bridge CFDictionaryRef)signatureUse);
- check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
- removeTS(cert1);
-
- /* brief interlude to create a bunch of SMIME policies with different key usages */
- SecPolicyRef smimeSignature = SecPolicyCreateSMIME(kSecSignSMIMEUsage, CFSTR("username@apple.com"));
- SecPolicyRef smimeDataEncrypt = SecPolicyCreateSMIME(kSecDataEncryptSMIMEUsage, CFSTR("username@apple.com"));
- SecPolicyRef smimeKeyEncrypt = SecPolicyCreateSMIME(kSecKeyEncryptSMIMEUsage, CFSTR("username@apple.com"));
- SecPolicyRef smimeKeyExchange = SecPolicyCreateSMIME(kSecKeyExchangeBothSMIMEUsage, CFSTR("username@apple.com"));
- SecPolicyRef smimeMultiple = SecPolicyCreateSMIME((kSecSignSMIMEUsage | kSecKeyEncryptSMIMEUsage),
- CFSTR("username@apple.com"));
-
- /* signature smime policy passes for signature use TS*/
- setTS(cert3, (__bridge CFDictionaryRef)signatureUse);
- check_trust(smimeChain, smimeSignature, verify_date, kSecTrustResultProceed);
-
- /* any use policy fails for signature use TS */
- check_trust(smimeChain, smimePolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
-
- /* multiple use smime policy against signature use */
- check_trust(smimeChain, smimeMultiple, verify_date, kSecTrustResultRecoverableTrustFailure);
- removeTS(cert3);
-
- /* key encrypt smime policy passes for key encrypt use */
- NSDictionary *keyEncryptUse = @{ (__bridge NSString*)kSecTrustSettingsKeyUsage: @(kSecTrustSettingsKeyUseEnDecryptKey),
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot)};
- setTS(cert3, (__bridge CFDictionaryRef)keyEncryptUse);
- check_trust(smimeChain, smimeKeyEncrypt, verify_date, kSecTrustResultProceed);
- removeTS(cert3);
-
- /* multiple use smime policy against multiple uses */
- NSDictionary *multipleUse = @{ (__bridge NSString*)kSecTrustSettingsKeyUsage: @(kSecTrustSettingsKeyUseEnDecryptKey |
- kSecTrustSettingsKeyUseSignature),
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot)};
- setTS(cert3, (__bridge CFDictionaryRef)multipleUse)
- check_trust(smimeChain, smimeMultiple, verify_date, kSecTrustResultProceed);
-
- /* signature smime policy against multiple uses */
- check_trust(smimeChain, smimeSignature, verify_date, kSecTrustResultRecoverableTrustFailure);
-
- /* any use smime policy against multiple uses */
- check_trust(smimeChain, smimePolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
- removeTS(cert3);
-
- CFReleaseNull(smimeSignature);
- CFReleaseNull(smimeDataEncrypt);
- CFReleaseNull(smimeKeyEncrypt);
- CFReleaseNull(smimeKeyExchange);
- CFReleaseNull(smimeMultiple);
-}
-
-#define kNumberAllowedErrorsTests (14+8*4)
-static void test_allowed_errors(void) {
- setTS(cert0, NULL);
-
- /* allow expired errors */
- NSDate *expired_date = [NSDate dateWithTimeIntervalSinceReferenceDate:520000000.0]; // Jun 24 2017
- check_trust(sslChain, basicPolicy, expired_date, kSecTrustResultRecoverableTrustFailure);
-
- NSDictionary *allowExpired = @{ (__bridge NSString*)kSecTrustSettingsAllowedError: @(-2147409654),
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)};
- setTS(cert1, (__bridge CFDictionaryRef)allowExpired)
- setTS(cert2, (__bridge CFDictionaryRef)allowExpired);
- check_trust(sslChain, basicPolicy, expired_date, kSecTrustResultProceed);
- removeTS(cert2);
- removeTS(cert1);
-
- /* allow hostname mismatch errors */
- SecPolicyRef wrongNameSSL = NULL;
- wrongNameSSL = SecPolicyCreateSSL(true, CFSTR("wrongname.apple.com"));
- check_trust(sslChain, wrongNameSSL, verify_date, kSecTrustResultRecoverableTrustFailure);
-
- NSDictionary *allowHostnameMismatch = @{ (__bridge NSString*)kSecTrustSettingsAllowedError: @(-2147408896),
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified) };
- setTS(cert2, (__bridge CFDictionaryRef)allowHostnameMismatch);
- sleep(1); // sleep a little extra so trustd gets trust settings event before evaluating leaf
- check_trust(sslChain, wrongNameSSL, verify_date, kSecTrustResultProceed);
- removeTS(cert2);
- CFReleaseNull(wrongNameSSL);
-
- /* allow email mismatch errors */
- SecPolicyRef wrongNameSMIME = NULL;
- wrongNameSMIME = SecPolicyCreateSMIME(kSecAnyEncryptSMIME, CFSTR("test@apple.com"));
- check_trust(smimeChain, wrongNameSMIME, verify_date, kSecTrustResultRecoverableTrustFailure);
-
- NSDictionary *allowEmailMismatch = @{ (__bridge NSString*)kSecTrustSettingsAllowedError: @(-2147408872),
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified) };
- setTS(cert3, (__bridge CFDictionaryRef)allowEmailMismatch);
- sleep(1); // sleep a little extra so trustd gets trust settings event before evaluating leaf
- check_trust(smimeChain, wrongNameSMIME, verify_date, kSecTrustResultProceed);
- removeTS(cert3);
- CFReleaseNull(wrongNameSMIME);
-
- /* allowed error with a policy constraint */
- NSDictionary *allowExpiredConstrained = @{ (__bridge NSString*)kSecTrustSettingsAllowedError: @(-2147409654),
- (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy,
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)};
- setTS(cert1, (__bridge CFDictionaryRef)allowExpiredConstrained)
- setTS(cert2, (__bridge CFDictionaryRef)allowExpiredConstrained);
- check_trust(sslChain, sslPolicy, expired_date, kSecTrustResultProceed);
- check_trust(sslChain, basicPolicy, expired_date, kSecTrustResultRecoverableTrustFailure);
- removeTS(cert2);
- removeTS(cert1);
-
- removeTS(cert0);
-}
-
-#define kNumberMultipleConstraintsTests (8+9*4)
-static void test_multiple_constraints(void) {
- /* deny all but */
- NSArray *denyAllBut = @[
- @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy ,
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)},
- @{(__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny) }
- ];
- setTS(cert0, (__bridge CFArrayRef)denyAllBut);
- check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultDeny);
- check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultProceed);
- removeTS(cert0);
-
- /* allow all but */
- NSArray *allowAllBut = @[
- @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy ,
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)},
- @{(__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot) }
- ];
- setTS(cert0, (__bridge CFArrayRef)allowAllBut);
- check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
- check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
- removeTS(cert0);
-
- /* different results for specific policies */
- NSArray *specifyPolicyResult = @[
- @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy,
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny)},
- @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)basicPolicy,
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot) }
- ];
- setTS(cert0, (__bridge CFArrayRef)specifyPolicyResult);
- check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
- check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultDeny);
- check_trust(smimeChain, smimePolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
- removeTS(cert0);
-
- /* different results for additional constraint with same policy */
- NSArray *policyConstraintResult = @[
- @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy,
- (__bridge NSString*)kSecTrustSettingsPolicyString: @("wrongname.apple.com"),
- (__bridge NSString*)kSecTrustSettingsAllowedError: @(-2147408896),
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot)},
- @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy,
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified) }
- ];
- SecPolicyRef wrongNameSSL = NULL;
- wrongNameSSL = SecPolicyCreateSSL(true, CFSTR("wrongname.apple.com"));
- setTS(cert2, (__bridge CFArrayRef)policyConstraintResult);
- sleep(1); // sleep a little extra so trustd gets trust settings event before evaluating leaf
- check_trust(sslChain, wrongNameSSL, verify_date, kSecTrustResultProceed);
- check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
- removeTS(cert2);
- CFReleaseNull(wrongNameSSL);
-
-}
-
-#define kNumberChangeConstraintsTests (2*kNumberSetTSTests + kNumberRemoveTSTests + 4*kNumberCheckTrustTests)
-static void test_change_constraints(void) {
- /* allow all but */
- NSArray *allowAllBut = @[
- @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy ,
- (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)},
- @{(__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot) }
- ];
- setTS(cert0, (__bridge CFArrayRef)allowAllBut);
- check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
- check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
-
- /* Don't clear trust settings. Just change them. */
-
- /* root with the default TrustRoot result succeeds */
- setTS(cert0, NULL);
- check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
- check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultProceed);
- removeTS(cert0);
-}
-
-#define kNumberPolicyNamePinnningConstraintsTests (kNumberSetTSTests + kNumberRemoveTSTests + 5)
-static void test_policy_name_pinning_constraints(void) {
- /* allow all but */
- NSArray *allowAllBut = @[
- @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslPolicy ,
- (__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(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");
- CFReleaseSafe(trust);
-
- removeTS(cert0);
-}
-
-
-int si_28_sectrustsettings(int argc, char *const *argv)
-{
- 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;
-}
#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 */
+/* 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,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,
+ 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,
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,
+ 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 */
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
+ verifyDate = [NSDate dateWithTimeIntervalSinceReferenceDate:622000000.0]; //September 16, 2020 at 6:46:40 PM PDT
CFReleaseNull(leaf);
CFReleaseNull(intermediate);
{
SecPolicyRef policy = NULL;
- policy = SecPolicyCreateSSL(true, CFSTR("openmarket.ess.apple.com"));
+ // 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("openmarket.ess.apple.com"), NULL);
+ 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");
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 *)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("openmarket.ess.apple.com"));
+ 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");
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;
-
- port=80;
+ int port = 80;
+ int retries = 5; // tries 5 times then gived up
+ char **h_addr_list = NULL;
- //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);
}
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) {
};
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,
__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);
+++ /dev/null
-/*
- * 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 <CoreFoundation/CoreFoundation.h>
-#include <Security/SecCertificate.h>
-#include <Security/SecCertificatePriv.h>
-#include <Security/SecPolicyPriv.h>
-#include <Security/SecTrust.h>
-#include <stdlib.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <unistd.h>
-#include <string.h>
-
-#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;
-}
+++ /dev/null
-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;
+++ /dev/null
-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;
+++ /dev/null
-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;
+++ /dev/null
-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;
+++ /dev/null
-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;
+++ /dev/null
-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;
+++ /dev/null
-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;
+++ /dev/null
-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;
+++ /dev/null
-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;
+++ /dev/null
-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;
+++ /dev/null
-/*
- * 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 <CoreFoundation/CoreFoundation.h>
-#include <Security/SecCertificate.h>
-#include <Security/SecCertificatePriv.h>
-#include <Security/SecItem.h>
-#include <Security/SecItemPriv.h>
-#include <Security/SecIdentityPriv.h>
-#include <Security/SecIdentity.h>
-#include <Security/SecPolicy.h>
-#include <Security/SecPolicyPriv.h>
-#include <Security/SecTrust.h>
-#include <Security/SecTrustPriv.h>
-#include <Security/SecCMS.h>
-#include <utilities/SecCFRelease.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#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;
-}
-
#include <Security/SecBase.h>
#include <utilities/array_size.h>
#include <utilities/SecCFWrappers.h>
+#include <os/feature_private.h>
#include "Security_regressions.h"
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);
}
+++ /dev/null
-/*
- * si-84-sectrust-allowlist.c
- * Security
- *
- * Copyright (c) 2015-2017 Apple Inc. All Rights Reserved.
- */
-
-#include <AssertMacros.h>
-#import <Foundation/Foundation.h>
-#include <CoreFoundation/CoreFoundation.h>
-#include <Security/Security.h>
-#include <Security/SecCertificatePriv.h>
-#include <Security/SecPolicyPriv.h>
-#include <utilities/SecCFRelease.h>
-#include <AssertMacros.h>
-
-#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: <rdar://32792206> */
- /* 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: <rdar://32792206> */
- /* 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: <rdar://32792206> */
- /* 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: <rdar://32792206> */
- /* 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: <rdar://32792206> */
- /* 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;
-}
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");
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,
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)
*/
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,
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,
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) {
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);
//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;
//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;
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;
#include "SecBase64.h"
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include <string.h>
#include <stdbool.h>
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",
.getAlgorithmID = SecCTKGetAlgorithmID,
.copyPublic = SecCTKKeyCopyPublicOctets,
.copyOperationResult = SecCTKKeyCopyOperationResult,
+ .isEqual = SecCTKKeyIsEqual,
.createDuplicate = SecCTKKeyCreateDuplicate,
.setParameter = SecCTKKeySetParameter,
};
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);
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()) {
}
}
}
+
+ // Sanitize some important attributes.
+ CFDictionarySetValue(SecCFDictionaryCOWGetMutable(&kd->attributes), kSecClass, kSecClassKey);
+ CFDictionarySetValue(SecCFDictionaryCOWGetMutable(&kd->attributes), kSecAttrKeyClass, kSecAttrKeyClassPrivate);
+
result = (SecKeyRef)CFRetain(key);
out:
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) {
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;
}, 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);
#include "AppleiPhoneDeviceCACertificates.h"
#include <ipc/securityd_client.h>
#include <Security/SecKeyInternal.h>
+#include "AppleExternalRootCertificates.h"
+#include <Security/SecInternalReleasePriv.h>
#pragma clang diagnostic ignored "-Wformat=2"
#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;
return (hashCode + der_length + sig_length);
}
-#if 1
-
/************************************************************************/
/************************* General Name Parsing *************************/
/************************************************************************/
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 **************************/
/************************************************************************/
}
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,
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,
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;
appendCRLDPFromGeneralNames);
require_noerr_quiet(drtn, badDER);
}
+ crldp_count++;
+ require_quiet(crldp_count < MAX_CRL_DPS, badDER);
}
require_quiet(drtn == DR_EndOfSequence, badDER);
return true;
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");
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,
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");
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,
free(mappings);
}
certificate->_policyMappings.present = false;
- secwarning("Invalid CertificatePolicies Extension");
+ secwarning("Invalid PolicyMappings Extension");
return false;
}
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;
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;
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;
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);
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);
string = s;
} else {
string = localizedName;
- CFRetain(string);
+ CFRetainSafe(string);
}
}
mask >>= 1;
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);
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
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;
+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;
+ }
+ }
+ 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;
-}
+ CFArrayRef ipAddresses = SecCertificateCopyIPAddressDatas(certificate);
+ if (!ipAddresses) {
+ return NULL;
+ }
-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);
+ // 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) {
- CFDataRef data = NULL;
- if (convertIPAddress(string, &data)) {
- CFArrayAppendValue(addrs, data);
- CFReleaseNull(data);
- }
+ CFArrayAppendValue(result, string);
CFRelease(string);
- } else {
- return errSecInvalidCertificate;
}
+ });
+ CFReleaseNull(ipAddresses);
+ if (CFArrayGetCount(result) == 0) {
+ CFReleaseNull(result);
}
- return errSecSuccess;
+
+ return result;
}
-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 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 addrs;
+ return ipAddresses;
}
static OSStatus appendDNSNamesFromGeneralNames(void *context, SecCEGeneralNameType gnType,
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);
}
});
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;
- }
- 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. */
+ /* 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);
+ }
+
+ /* 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);
}
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)
}
#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
{
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;
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) {
}
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;
+}
__BEGIN_DECLS
+SecSignatureHashAlgorithm SecSignatureHashAlgorithmForAlgorithmOid(const DERItem *algOid);
+
CFDataRef SecCertificateGetAuthorityKeyID(SecCertificateRef certificate);
CFDataRef SecCertificateGetSubjectKeyID(SecCertificateRef certificate);
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);
/*
- * 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,
* 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 (src > 128)
ptr = mod128_oid_encoding_ptr(ptr, src / 128, false);
-
+
unsigned char octet = src % 128;
if (!final)
octet |= 128;
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;
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;
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;
}
/* 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;
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;
}
require(entry_count > 0, out);
-
+
require(key,out);
require(CFGetTypeID(key) == CFStringGetTypeID(), out);
capacity *= 2;
else
capacity = 10;
-
+
void * new_array = PORT_ArenaZNewArray(gn->poolp, SecAsn1Item, capacity);
if (gn->names)
memcpy(new_array, gn->names, gn->capacity);
}
else
goto out;
-
+
if (gn_values) {
for (entry_ix = 0; entry_ix < entry_count; entry_ix++) {
CFTypeRef entry_value = CFArrayGetValueAtIndex(gn_values, entry_ix);
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);
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) {
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);
}
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) {
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);
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;
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;
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) {
return signature;
}
-CFDataRef SecGenerateCertificateRequestWithParameters(SecRDN *subject,
+CFDataRef SecGenerateCertificateRequestWithParameters(SecRDN *subject,
CFDictionaryRef parameters, SecKeyRef publicKey, SecKeyRef privateKey)
{
if (subject == NULL || *subject == NULL) {
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)
+
+ if (!poolp) {
return NULL;
+ }
- NSSCertRequest certReq;
- memset(&certReq, 0, sizeof(certReq));
+ NSSCertRequest certReq;
+ memset(&certReq, 0, sizeof(certReq));
/* version */
unsigned char version = 0;
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];
}
rdnps[rdn_num] = NULL;
certReq.reqInfo.subject.rdns = rdnps;
-
+
/* public key info */
realPublicKey = SecKeyCopyPublicKey(privateKey);
if (!realPublicKey) {
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);
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);
return csr;
}
-CFDataRef SecGenerateCertificateRequest(CFArrayRef subject,
+CFDataRef SecGenerateCertificateRequest(CFArrayRef subject,
CFDictionaryRef parameters, SecKeyRef publicKey, SecKeyRef privateKey)
{
CFDataRef csr = NULL;
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)
+
+ if (!poolp) {
return NULL;
+ }
- NSSCertRequest certReq;
- memset(&certReq, 0, sizeof(certReq));
+ NSSCertRequest certReq;
+ memset(&certReq, 0, sizeof(certReq));
/* version */
unsigned char version = 0;
/* subject */
certReq.reqInfo.subject.rdns = make_subject(poolp, (CFArrayRef)subject);
-
+
/* public key info */
realPublicKey = SecKeyCopyPublicKey(privateKey);
if (!realPublicKey) {
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);
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);
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) {
extensions_item = *attr->attrValue[0];
}
}
-
+
if (subject && subject_item.Length)
*subject = CFDataCreate(kCFAllocatorDefault, subject_item.Data, subject_item.Length);
if (extensions && extensions_item.Length)
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) {
});
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);
}
SecCertificateRef
-SecGenerateSelfSignedCertificate(CFArrayRef subject, CFDictionaryRef parameters,
+SecGenerateSelfSignedCertificate(CFArrayRef subject, CFDictionaryRef parameters,
SecKeyRef __unused publicKey, SecKeyRef privateKey)
{
SecCertificateRef cert = NULL;
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);
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. */
}
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;
static ccoid_t ccoid_secp384r1 = CC_EC_OID_SECP384R1;
static ccoid_t ccoid_secp521r1 = CC_EC_OID_SECP521R1;
+// <rdar://problem/66864716> 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) {
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();
}
}
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;
#if TARGET_OS_OSX
_kSecPolicyAppleiChat
#endif
-_kSecPolicyAppleIDValidationRecordSigningPolicy
_kSecPolicyMacAppStoreReceipt
_kSecPolicyNameAppleAIDCService
_kSecPolicyNameAppleAMPService
_kSecPolicyNameAppleMapsService
_kSecPolicyNameAppleMMCSService
_kSecPolicyNameAppleParsecService
+_kSecPolicyNameApplePushCertPortal
_kSecPolicyNameApplePPQService
_kSecPolicyNameApplePushService
_kSecPolicyNameAppleSiriService
#endif
_SecDNSIsTLD
+_CreateCFDataFromBase64CFString
+_parseNSPinnedDomains
+_SecPolicyReconcilePinningRequiredIfInfoSpecified
#undef POLICYCHECKMACRO
#define __PC_DO_EXPORT_(NAME)
_SecPolicySetOptionsValue
#if TARGET_OS_OSX
_SecPolicyCopy
-_SecPolicyCopyAll
_SecPolicyCreateAppleTimeStampingAndRevocationPolicies
_SecPolicyCreateItemImplInstance
_SecPolicyCreateWithOID
_SecTrustCopyFilteredDetails
_SecTrustCopyInfo
_SecTrustCopyInputCertificates
+_SecTrustCopyKey
_SecTrustCopyPolicies
_SecTrustCopyProperties
_SecTrustCopyPublicKey
_SecTrustSetSignedCertificateTimestamps
_SecTrustSetTrustedLogs
_SecTrustSetVerifyDate
+_SecTrustTriggerValidUpdate
#if TARGET_OS_OSX
_SecTrustCopyAnchorCertificates
_SecTrustCopyExtendedResult
_SecTrustSettingsCopyModificationDate
_SecTrustSettingsCopyQualifiedCerts
_SecTrustSettingsCopyTrustSettings
+_SecTrustSettingsCopyTrustSettings_Cached
_SecTrustSettingsCopyUnrestrictedRoots
_SecTrustSettingsCreateExternalRepresentation
_SecTrustSettingsEvaluateCert
_SecTrustSettingsImportExternalRepresentation
+_SecTrustSettingsPurgeCache
_SecTrustSettingsPurgeUserAdminCertsCache
_SecTrustSettingsRemoveTrustSettings
_SecTrustSettingsSetTrustSettings
_SecTrustSettingsSetTrustSettingsExternal
_SecTrustSettingsSetTrustedCertificateForSSLHost
+_SecTrustSettingsUserAdminDomainsContain
_SecTrustedApplicationCopyData
_SecTrustedApplicationCopyExternalRepresentation
_SecTrustedApplicationCopyRequirement
#endif
-#if TARGET_OS_IPHONE
_SecTrustStoreContains
_SecTrustStoreCopyAll
_SecTrustStoreCopyUsageConstraints
_SecTrustStoreGetSettingsAssetVersionNumber
_SecTrustStoreRemoveCertificate
_SecTrustStoreSetTrustSettings
+#if TARGET_OS_IPHONE
_SecTrustGetExceptionResetCount
_SecTrustIncrementExceptionResetCount
#endif
_SecTrustStoreSetCTExceptions
_SecTrustStoreCopyCTExceptions
+_SecTrustStoreSetCARevocationAdditions
+_SecTrustStoreCopyCARevocationAdditions
_kSecCTExceptionsCAsKey
_kSecCTExceptionsDomainsKey
_kSecCTExceptionsHashAlgorithmKey
_kSecCTExceptionsSPKIHashKey
+_kSecCARevocationAdditionsKey
+_kSecCARevocationHashAlgorithmKey
+_kSecCARevocationSPKIHashKey
//
// Identity
_kSecCertificateEscrowFileName
_kSecCertificateProductionEscrowKey
_kSecCertificateProductionPCSEscrowKey
+_SecCertificateCopyAppleExternalRoots
_SecCertificateCopyAttributeDictionary
_SecCertificateCopyCommonName
_SecCertificateCopyCommonNames
_SecCertificateCopyCTLogForKeyID
_SecCertificateCopyDNSNames
_SecCertificateCopyDNSNamesFromSAN
-_SecCertificateCopyDNSNamesFromSubject
_SecCertificateCopyData
_SecCertificateCopyEmailAddresses
_SecCertificateCopyEscrowRoots
_SecCertificateCopyExtensionValue
_SecCertificateCopyiAPAuthCapabilities
_SecCertificateCopyiAPSWAuthCapabilities
+_SecCertificateCopyIPAddressDatas
_SecCertificateCopyIPAddresses
-_SecCertificateCopyIPAddressesFromSubject
_SecCertificateCopyiPhoneDeviceCAChain
_SecCertificateCopyIssuerSHA1Digest
_SecCertificateCopyIssuerSequence
_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
_SecCertificateVersion
_SecDistinguishedNameCopyNormalizedContent
_SecDistinguishedNameCopyNormalizedSequence
+_SecSignatureHashAlgorithmForAlgorithmOid
_SecCertificateArrayCopyXPCArray
_SecCertificateAppendToXPCArray
_SecCertificateSetPreferred
#endif
-//
-// CertificateBundle
-//
-
-#if TARGET_OS_OSX
-_SecCertifcateBundleExport
-_SecCertificateBundleExport
-_SecCertificateBundleImport
-#endif /* TARGET_OS_OSX */
-
#if TARGET_OS_IPHONE
//
// SCEP
//
_SecOTRPacketTypeString
-_SecOTRSEndSession
_SecOTRSPrecalculateKeys
_SecOTRSessionCreateRemote
_SecOTRSessionProcessPacketRemote
_SecOTRSessionIsSessionInAwaitingState
_SecOTRFullIdentityCreateFromSecKeyRef
+_SecOTRFullIdentityCreateFromSecKeyRefSOS
_SecOTRSIsForKeys
_SecOTRPublicIdentityCreateFromSecKeyRef
_SecOTRSAppendRestartPacket
_kSecAttrPCSPlaintextPublicIdentity
_kSecAttrSHA1
+_kSecDataInetExtraNotes
+_kSecDataInetExtraHistory
+_kSecDataInetExtraClientDefined0
+_kSecDataInetExtraClientDefined1
+_kSecDataInetExtraClientDefined2
+_kSecDataInetExtraClientDefined3
+
#include "keychain/SecureObjectSync/SOSViews.exp-in"
_kSecClass
_kSecReturnRef
_SecItemAdd
_SecItemCertificateExists
-_SecItemCopyDisplayNames
_SecItemCopyMatching
_SecItemCopyParentCertificates_ios
_SecItemDelete
__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
__SecSyncBubbleTransfer
__SecSystemKeychainTransfer
__SecSyncDeleteUserViews
-_SecItemUpdateTokenItems
+_SecItemUpdateTokenItemsForAccessGroups
_SecItemDeleteAllWithAccessGroups
_SecTokenItemValueCopy
_sSecDERErrorDomain
_der_sizeof_plist
_der_encode_plist
+_der_encode_plist_repair
_der_decode_plist
_CFPropertyListCreateDERData
_CFPropertyListCreateWithDERData
_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
_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
_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_experiment_identifier
_sec_protocol_metadata_get_experiment_identifier
_sec_protocol_options_create_config
_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
_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
_SSLCiphersuiteGroupToCiphersuiteList
_SSLCiphersuiteMaximumTLSVersion
_SSLCiphersuiteMinimumTLSVersion
-
-#if __OBJC2__ && (TARGET_OS_IPHONE || (TARGET_OS_OSX && __x86_64__))
-_OBJC_CLASS_$_SFSignInAnalytics
-#endif //__OBJC2__ && IPHONE || OSX
#endif
#include "SecFramework.h"
-#include <dispatch/dispatch.h>
#include <CoreFoundation/CFBundle.h>
-#include <CoreFoundation/CFURLAccess.h>
-#include <Security/SecRandom.h>
-#include <CommonCrypto/CommonRandomSPI.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <utilities/debugging.h>
#include <utilities/SecCFWrappers.h>
-#include <Security/SecBase.h>
-#include <inttypes.h>
/* Security.framework's bundle id. */
#if TARGET_OS_IPHONE
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;
-}
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);
#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")
#include <utilities/SecXPCError.h>
#include <utilities/der_plist.h>
#include <utilities/der_plist_internal.h>
-#include <assert.h>
-#include <dlfcn.h>
+#include <utilities/simulatecrash_assert.h>
#include <libaks_acl_cf_keys.h>
#include <os/activity.h>
#include <pthread.h>
#include <os/lock.h>
+#include <os/feature_private.h>
#include <Security/SecInternal.h>
#include "keychain/SecureObjectSync/SOSInternal.h"
#include <coreauthd_spi.h>
#include <LocalAuthentication/LAPrivateDefines.h>
-#include <LocalAuthentication/LACFSupport.h>
#include <ctkclient/ctkclient.h>
+#include "SecItemRateLimit.h"
+
/*
* See corresponding definition in SecDbKeychainItemV7. This is the unserialized
* maximum, so the daemon's limit is not exactly the same.
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,
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);
}
}
-static CFDataRef CreateTokenPersistentRefData(CFTypeRef class, CFDictionaryRef attributes)
-{
+static CFDataRef CreateTokenPersistentRefData(CFTypeRef class, CFDictionaryRef attributes) {
CFDataRef tokenPersistentRef = NULL;
- CFStringRef tokenId;
+ CFStringRef tokenID = NULL;
+ CFDataRef tokenData = NULL;
+ CFDataRef oid = NULL;
CFDictionaryRef itemValue = NULL;
- require_quiet(tokenId = CFCast(CFString, CFDictionaryGetValue(attributes, kSecAttrTokenID)), out);
- 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_quiet(itemValue, out);
- CFDataRef oid = CFDictionaryGetValue(itemValue, kSecTokenValueObjectIDKey);
- require_quiet(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:
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);
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);
}
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")));
CFTypeRef value = CFDictionaryGetValue(plist, kSecTokenValueObjectIDKey);
require_action_quiet(CFCast(CFData, value) != NULL, out,
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) {
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.
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.
}
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);
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);
ok = true;
out:
- if (la_lib != NULL) {
- dlclose(la_lib);
- }
CFReleaseSafe(ac_data);
CFReleaseSafe(acm_context);
return ok;
}
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) {
+ // <rdar://problem/60642633> 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);
}, 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;
}
return ok;
}
+static void countReadOnlyAPICall() {
+ if (!isReadOnlyAPIRateWithinLimits()) {
+ }
+}
+
+static void countModifyingAPICall() {
+ if (!isModifyingAPIRateWithinLimits()) {
+ }
+}
+
OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result) {
__block SecCFDictionaryCOW attrs = { attributes };
OSStatus status;
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);
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
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 {
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 {
});
}
-#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;
#include <Security/SecItemPriv.h>
#include <Security/SecItemInternal.h>
#include <utilities/SecCFRelease.h>
+#import <utilities/debugging.h>
#include <os/activity.h>
__block CFTypeRef raw_result = NULL;
__block CFErrorRef raw_error = NULL;
- id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(^(NSError *error) {
+ id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(false, ^(NSError *error) {
syncCallback(false, (__bridge CFErrorRef)error);
});
if (rpc == NULL) {
os_activity_scope(activity);
@autoreleasepool {
- id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(^(NSError *error) {
+ id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(false, ^(NSError *error) {
complete((__bridge CFErrorRef) error);
});
[rpc secItemSetCurrentItemAcrossAllDevices:(__bridge NSData*)newCurrentItemReference
os_activity_scope(activity);
@autoreleasepool {
- id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(^(NSError *error) {
+ id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(false, ^(NSError *error) {
complete(NULL, (__bridge CFErrorRef) error);
});
[rpc secItemFetchCurrentItemAcrossAllDevices:(__bridge NSString*)accessGroup
os_activity_t activity = os_activity_create("_SecItemFetchDigests", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
os_activity_scope(activity);
- id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(^(NSError *error) {
+ id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(false, ^(NSError *error) {
complete(NULL, error);
});
[rpc secItemDigest:itemClass accessGroup:accessGroup complete:complete];
uuid_t musrUUID;
[uuid getUUIDBytes:musrUUID];
- id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(^(NSError *error) {
+ id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(false, ^(NSError *error) {
complete(false, error);
});
[rpc secKeychainDeleteMultiuser:[NSData dataWithBytes:musrUUID length:sizeof(uuid_t)] complete:^(bool status, NSError *error) {
void(^completion)(NSDictionary<NSString*, NSString*>* results, NSError* error))
{
@autoreleasepool {
- id<SecuritydXPCProtocol> rpc = SecuritydXPCProxyObject(^(NSError *error) {
+ id<SecuritydXPCProtocol> 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<SecuritydXPCProtocol> 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;
+}
});
}
+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;
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);
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"));
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, ^{
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
@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);
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");
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_ */
--- /dev/null
+#ifndef SECITEMRATELIMIT_H_
+#define SECITEMRATELIMIT_H_
+
+#include <stdbool.h>
+
+bool isReadOnlyAPIRateWithinLimits(void);
+bool isModifyingAPIRateWithinLimits(void);
+
+#endif // SECITEMRATELIMIT_H_
--- /dev/null
+/*
+ * 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 <utilities/debugging.h>
+#import <utilities/SecInternalReleasePriv.h>
+#import "ipc/securityd_client.h"
+
+#import <sys/codesign.h>
+#import <os/feature_private.h>
+
+// 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];
+}
--- /dev/null
+/*
+ * 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 <Foundation/Foundation.h>
+
+// 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 */
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);
#define SecItemCopyMatching SecItemCopyMatching_ios
#define SecItemUpdate SecItemUpdate_ios
#define SecItemDelete SecItemDelete_ios
-#define SecItemUpdateTokenItems SecItemUpdateTokenItems_ios
#define SecKeyGeneratePair SecKeyGeneratePair_ios
#define SecKeyCreateRandomKey SecKeyCreateRandomKey_ios
if (!persistentRef) {
secerror("SecKeyCopyPersistentRef: Need a persistentRef pointer for this to work");
return errSecParam;
- }
+ }
CFDictionaryRef query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
kSecReturnPersistentRef, kCFBooleanTrue,
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);
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);
@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;
* 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);
#include <corecrypto/ccsha1.h>
#include <corecrypto/ccec_priv.h>
#include <corecrypto/ccec.h>
-
-#include <CommonCrypto/CommonRandomSPI.h>
+#include <corecrypto/ccrng.h>
#define kECKeySize 256
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
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;
--*size;
require_noerr_quiet(status = SecOTRFICreateKeysFromReadPersistentRefAndPublicKey(bytes, size, &newID->publicSigningKey, &newID->privateSigningKey, &newID->privateKeyPersistentRef, &CreateECPublicKeyFrom), fail);
-
+ newID->isMessageProtectionKey = false;
+
return status;
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;
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);
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);
}
}
+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)
{
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 {
SecKeyRef publicSigningKey;
SecKeyRef privateSigningKey;
CFDataRef privateKeyPersistentRef;
-
+
+ bool isMessageProtectionKey;
uint8_t publicIDHash[kMPIDHashSize];
};
#include <AssertMacros.h>
+#include <security_utilities/simulatecrash_assert.h>
+
__BEGIN_DECLS
-static CC_NONNULL((1,2))
-OSStatus ReadAndVerifyByte(const uint8_t**bytes, size_t*size, uint8_t expected);
+CF_ASSUME_NONNULL_BEGIN
+
+static
+OSStatus ReadAndVerifyByte(const uint8_t *_Nonnull *_Nonnull bytes, size_t*size, uint8_t expected);
-static CC_NONNULL((1,2))
-OSStatus ReadAndVerifyShort(const uint8_t**bytes, size_t*size, uint16_t expected);
+static
+OSStatus ReadAndVerifyShort(const uint8_t *_Nonnull *_Nonnull bytes, size_t*size, uint16_t expected);
-static CC_NONNULL((1,2))
-OSStatus ReadAndVerifyMessageType(const uint8_t**bytes, size_t*size, OTRMessageType expected);
+static
+OSStatus ReadAndVerifyMessageType(const uint8_t *_Nonnull *_Nonnull bytes, size_t*size, OTRMessageType 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 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((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);
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);
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;
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);
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);
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);
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;
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;
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);
}
-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);
}
-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);
}
-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;
//
// 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);
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);
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);
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);
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);
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;
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);
AppendMessageType(appendTo, type);
}
+CF_ASSUME_NONNULL_END
+
__END_DECLS
#endif
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;
}
-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) {
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);
#include <utilities/array_size.h>
#include <ipc/securityd_client.h>
#include <os/variant_private.h>
+#include <MobileGestalt.h>
#include <utilities/SecInternalReleasePriv.h>
+#include <Security/SecBase64.h>
+
#undef POLICYCHECKMACRO
#define POLICYCHECKMACRO(NAME, TRUSTRESULT, SUBTYPE, LEAFCHECK, PATHCHECK, LEAFONLY, CSSMERR, OSSTATUS) \
const CFStringRef kSecPolicyCheck##NAME = CFSTR(#NAME);
#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");
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
policy = SecPolicyCreateAppleBasicAttestationUser(rootDigest);
} else if (CFEqual(policyIdentifier, kSecPolicyAppleComponentCertificate)) {
policy = SecPolicyCreateAppleComponentCertificate(rootDigest);
+ } else if (CFEqual(policyIdentifier, kSecPolicyAppleAggregateMetricTransparency)) {
+ policy = SecPolicyCreateAggregateMetricTransparency(!client);
}
/* For a couple of common patterns we use the macro, but some of the
* policies are deprecated (or not yet available), so we need to ignore the warning. */
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;
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 true;
+ return result;
}
//
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
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);
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) {
errOut:
CFReleaseSafe(options);
- CFReleaseSafe(appleAnchorOptions);
return result;
}
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;
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),
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;
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);
/* Require id-kp-OCSPSigning extendedKeyUsage to be present, not optional. */
add_eku(options, &oidExtendedKeyUsageOCSPSigning);
+ /* Check for digitalSignature KU and CA:FALSE. See <rdar://problem/65354714> */
+ add_ku(options, kSecKeyUsageDigitalSignature);
+ CFDictionarySetValue(options, kSecPolicyCheckNotCA, kCFBooleanTrue);
+
require(result = SecPolicyCreate(kSecPolicyAppleOCSPSigner,
kSecPolicyNameOCSPSigner, options), errOut);
if (smimeUsage & kSecSignSMIMEUsage) {
add_ku(options, kSecKeyUsageUnspecified);
add_ku(options, kSecKeyUsageDigitalSignature);
- add_ku(options, kSecKeyUsageNonRepudiation);
}
if (smimeUsage & kSecKeyEncryptSMIMEUsage) {
add_ku(options, kSecKeyUsageKeyEncipherment);
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) {
+ /* <rdar://57130017> */
+ 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
return CreateConfigurationProfileSigner(false);
}
-
SecPolicyRef SecPolicyCreateQAConfigurationProfileSigner(void)
{
-#if RC_SEED_BUILD
- // Seed builds permit the QA signer
- return CreateConfigurationProfileSigner(true);
-#else // !RC_SEED_BUILD
- if (os_variant_has_internal_diagnostics("com.apple.security")) {
- // Internal builds permit the QA signer
- return CreateConfigurationProfileSigner(true);
+ CFStringRef releaseType = MGCopyAnswer(kMGQReleaseType, NULL);
+ SecPolicyRef result = NULL;
+ if (releaseType == NULL) {
+ // customer variants do not trust the QA signer
+ result = CreateConfigurationProfileSigner(false);
} else {
- // GM builds do not trust the QA signer
- return CreateConfigurationProfileSigner(false);
+ // all other variants (beta, carrier, internal, etc) allow the QA signer
+ result = CreateConfigurationProfileSigner(true);
}
-#endif // !RC_SEED_BUILD
+ CFReleaseNull(releaseType);
+ return result;
}
SecPolicyRef SecPolicyCreateOSXProvisioningProfileSigning(void)
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,
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,
&kCFTypeDictionaryValueCallBacks), errOut);
SecPolicyAddBasicCertOptions(options);
- SecPolicyAddAnchorSHA1Options(options, kTestAppleRootCA_ECC_SHA1);
+ SecPolicyAddAnchorSHA256Options(options, kTestAppleRootCA_ECC_SHA256);
require(SecPolicyAddChainLengthOptions(options, 3), errOut);
CFDictionaryAddValue(options, kSecPolicyCheckIssuerCommonName,
const DERItem *leafMarkerOID,
const DERItem *UATLeafMarkerOID)
{
- CFMutableDictionaryRef appleAnchorOptions = NULL;
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
CFDataRef oid = NULL, uatoid = NULL;
require(result, errOut);
errOut:
- CFReleaseSafe(appleAnchorOptions);
CFReleaseSafe(options);
CFReleaseSafe(oid);
CFReleaseSafe(uatoid);
*/
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);
}
/*!
}
SecPolicyRef SecPolicyCreateAppleHomeKitServerAuth(CFStringRef hostname) {
- CFMutableDictionaryRef appleAnchorOptions = NULL;
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
CFDataRef oid = NULL;
require(result, errOut);
errOut:
- CFReleaseSafe(appleAnchorOptions);
CFReleaseSafe(options);
CFReleaseSafe(oid);
return result;
SecPolicyRef SecPolicyCreateAppleWarsaw(void) {
CFMutableDictionaryRef options = NULL;
SecPolicyRef result = NULL;
-#if TARGET_OS_BRIDGE
- CFMutableDictionaryRef appleAnchorOptions = NULL;
-#endif
require(options = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
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);
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;
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;
+}
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)
POLICYMACRO(LegacySSL, 94, E, legacySSL, , , LegacySSL)
POLICYMACRO(Alisha, 95, E, Alisha, , Y, Alisha)
POLICYMACRO(MeasuredBootPolicySigning, 96, E, MeasuredBootPolicySigning, , Y, MeasuredBootPolicySigning)
-// 97-99 used on master
+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)
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
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
/********************************************************
*********** Unverified Intermediate Checks *************
/********************************************************
************** 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 **************
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
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
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;
}
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);
return true;
}
+bool SecPolicyCheckCertNotCA(SecCertificateRef cert, CFTypeRef pvcValue) {
+ if (SecCertificateIsCA(cert)) {
+ return false;
+ }
+ return true;
+}
+
/*
* MARK: SecLeafPVC functions
*/
{
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);
#import <corecrypto/cchkdf.h>
#import <corecrypto/ccsha2.h>
#import <corecrypto/ccec.h>
+#import <corecrypto/ccrng.h>
#import <utilities/SecCFWrappers.h>
-#import <CommonCrypto/CommonRandomSPI.h>
#import <AssertMacros.h>
status = ccec_generate_key_deterministic(cp,
CFDataGetLength(derivedSecret), CFDataGetBytePtr(derivedSecret),
- ccDRBGGetRngState(),
+ ccrng(NULL),
CCEC_GENKEY_DETERMINISTIC_COMPACT,
fullKey);
require_noerr(status, fail);
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?")));
/*
- * Copyright (c) 2014-2016 Apple Inc. All Rights Reserved.
+ * Copyright (c) 2014-2020 Apple Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
/* 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,
}
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);
return status;
}
+#endif /* !TARGET_OS_OSX || !TARGET_OS_MACCATALYST */
#endif /* SHAREDWEBCREDENTIALS */
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,
}
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);
return status;
}
+#endif /* !TARGET_OS_OSX || !TARGET_OS_MACCATALYST */
#endif /* SHAREDWEBCREDENTIALS */
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);
}
CFReleaseSafe(error);
});
-#endif
+#endif /* SHAREDWEBCREDENTIALS */
}
--- /dev/null
+/*
+ * 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 <Security/SecSharedCredential.h>
+#include <Security/SecBasePriv.h>
+#include <utilities/SecCFError.h>
+#include <utilities/SecCFWrappers.h>
+#include "SecItemInternal.h"
+#include <dlfcn.h>
+
+#import <Foundation/Foundation.h>
+#import <AuthenticationServices/AuthenticationServices.h>
+
+// 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
+ <ASAuthorizationControllerDelegate,
+ ASAuthorizationControllerPresentationContextProviding>
+
+-(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: <rdar://problem/59958701>
+ _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;
+}
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;
}
});
}
- 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) {
} 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;
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;
/*
- * 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,
* 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@
*/
#define kSecTrustTrustedLogsKey "trustedLogs"
#define kSecTrustVerifyDateKey "verifyDate"
#define kSecTrustExceptionsKey "exceptions"
+#define kSecTrustRevocationAdditionsKey "revocationCheck"
/* args_out keys. */
#define kSecTrustDetailsKey "details"
/*
- * 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,
* 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 <Security/SecTrustStore.h>
require(ts, errOut);
require(digest = SecCertificateGetSHA1Digest(certificate), errOut);
-
+
ok = (SecOSStatusWith(^bool (CFErrorRef *error) {
return TRUSTD_XPC(sec_trust_store_contains, string_data_to_bool_bool_error, ts, digest, &contains, error);
}) == errSecSuccess);
-
+
errOut:
return ok && contains;
}
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);
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);
});
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);
}
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 = CFSTR("HashAlgorithm");
+const CFStringRef kSecCARevocationSPKIHashKey = CFSTR("SubjectPublicKeyInfoHash");
+
+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
+}
return CFSTR("RejectApplicants");
case kSecXPCOpRemoveThisDeviceFromCircle:
return CFSTR("RemoveThisDeviceFromCircle");
- case kSecXPCOpRemoveThisDeviceFromCircleWithAnalytics:
- return CFSTR("RemoveThisDeviceFromCircleWithAnalytics");
case kSecXPCOpRemovePeersFromCircle:
return CFSTR("RemovePeersFromCircle");
- case kSecXPCOpRemovePeersFromCircleWithAnalytics:
- return CFSTR("RemovePeersFromCircleWithAnalytics");
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 kSecXPCOpRollKeys:
return CFSTR("SetUserCredentials");
case kSecXPCOpSetUserCredentialsAndDSID:
return CFSTR("SetUserCredentialsAndDSID");
- case kSecXPCOpSetUserCredentialsAndDSIDWithAnalytics:
- return CFSTR("SetUserCredentialsAndDSIDWithAnalytics");
case kSecXPCOpTryUserCredentials:
return CFSTR("TryUserCredentials");
case kSecXPCOpValidateUserPublic:
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:
return CFSTR("WhoAmI");
case kSecXPCOpTransmogrifyToSyncBubble:
return CFSTR("TransmogrifyToSyncBubble");
- 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");
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");
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;
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);
}
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);
void SecAccessGroupsSetCurrent(CFArrayRef accessGroups);
CFArrayRef SecAccessGroupsGetCurrent(void);
+void SecSecurityClientRegularToAppClip(void);
+void SecSecurityClientAppClipToRegular(void);
+void SecSecurityClientSetApplicationIdentifier(CFStringRef identifier);
#include <os/log_private.h>
extern os_log_t secLogObjForScope(const char *scope);
#include "p12pbegen.h"
+#include <security_utilities/simulatecrash_assert.h>
+
static uint8_t *concatenate_to_blocksize(const uint8_t *data, size_t data_length,
size_t blocksize, size_t *blocklength)
{
#include <MobileCoreServices/LSApplicationProxy.h>
#endif
-#if TARGET_OS_IPHONE && !TARGET_OS_WATCH
+#if TARGET_OS_IPHONE && !TARGET_OS_WATCH && !TARGET_OS_TV
#include <dlfcn.h>
#include <WebUI/WBUAutoFillData.h>
#import <LocalAuthentication/LocalAuthentication.h>
#import <LocalAuthentication/LAContext+Private.h>
#import <MobileGestalt.h>
-#import <ManagedConfiguration/MCProfileConnection.h>
+#import <ManagedConfiguration/ManagedConfiguration.h>
#endif
static NSString *swca_string_table = @"SharedWebCredentials";
/*
- * 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@
*
#include <vproc_priv.h>
#include <xpc/xpc.h>
#include <xpc/private.h>
+#include <os/feature_private.h>
#include <CoreFoundation/CoreFoundation.h>
#include <Security/SecItem.h>
/* 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;
gClient.activeUser = 501;
gClient.musr = NULL;
#endif
+ gClient.applicationIdentifier = NULL;
+ gClient.isAppClip = false;
});
return &gClient;
}
// 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
case kSecXPCOpCopyCTExceptions:
case sec_trust_get_exception_reset_count_id:
case sec_trust_increment_exception_reset_count_id:
+ case kSecXPCOpSetCARevocationAdditions:
+ case kSecXPCOpCopyCARevocationAdditions:
+ case kSecXPCOpValidUpdate:
return true;
default:
break;
#import <Foundation/NSXPCConnection_Private.h>
#import <objc/runtime.h>
#import <utilities/debugging.h>
+#import <Security/SecXPCHelper.h>
#include <ipc/securityd_client.h>
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<Class> *errClasses = [SecXPCHelper safeErrorClasses];
@try {
[rpcCallbackInterface setClasses:errClasses forSelector:@selector(callCallback:error:) argumentIndex:1 ofReply:NO];
[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:
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
}
}
@end
-id<SecuritydXPCProtocol> SecuritydXPCProxyObject(void (^rpcErrorHandler)(NSError *))
+id<SecuritydXPCProtocol> SecuritydXPCProxyObject(bool synchronous, void (^rpcErrorHandler)(NSError *))
{
if (gSecurityd && gSecurityd->secd_xpc_server) {
return (__bridge id<SecuritydXPCProtocol>)gSecurityd->secd_xpc_server;
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];
+ }
}
}
<key>Interval</key>
<real>86400</real>
</dict>
+ <key>com.apple.securityd.prng</key>
+ <dict>
+ <key>Priority</key>
+ <string>Maintenance</string>
+ <key>Interval</key>
+ <real>3600</real>
+ <key>RequiresClassC</key>
+ <false/>
+ </dict>
</dict>
</dict>
</dict>
<key>NetworkTransferDirection</key>
<string>Bidirectional</string>
</dict>
+ <key>com.apple.securityd.prng</key>
+ <dict>
+ <key>Priority</key>
+ <string>Maintenance</string>
+ <key>Interval</key>
+ <real>3600</real>
+ <key>RequiresClassC</key>
+ <false/>
+ </dict>
</dict>
<key>com.apple.notifyd.matching</key>
<dict>
/*
- * Copyright (c) 2007-2018 Apple Inc. All Rights Reserved.
+ * Copyright (c) 2007-2020 Apple Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
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,
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,
kSecXPCOpSetNewPublicBackupKey,
kSecXPCOpSetBagForAllSlices,
kSecXPCOpWaitForInitialSync,
- kSecXPCOpWaitForInitialSyncWithAnalytics,
kSecXPCOpCheckPeerAvailability,
kSecXPCOpCopyApplication,
kSecXPCOpCopyCircleJoiningBlob,
kSecXPCOpWhoAmI,
kSecXPCOpTransmogrifyToSyncBubble,
kSecXPCOpTransmogrifyToSystemKeychain,
- 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,
kSecXPCOpOTASecExperimentGetNewAsset,
sec_trust_get_exception_reset_count_id,
sec_trust_increment_exception_reset_count_id,
+ kSecXPCOpSetCARevocationAdditions,
+ kSecXPCOpCopyCARevocationAdditions,
+ kSecXPCOpValidUpdate,
};
bool inMultiUser;
int activeUser;
#endif
+ bool isAppClip;
+ CFStringRef applicationIdentifier;
} SecurityClient;
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);
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);
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_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);
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);
bool (*soscc_PeerAvailability)(CFErrorRef *error);
SOSPeerInfoRef (*soscc_CopyApplicant)(CFErrorRef *error);
CFDataRef (*soscc_CopyCircleJoiningBlob)(SOSPeerInfoRef applicant, CFErrorRef *error);
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);
};
extern struct trustd *gTrustd;
- (void)secItemVerifyBackupIntegrity:(BOOL)lightweight
completion:(void (^)(NSDictionary<NSString*, NSString*>* 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;
@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<SecuritydXPCProtocol> SecuritydXPCProxyObject(void (^rpcErrorHandler)(NSError *));
+id<SecuritydXPCProtocol> 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<SecuritydXPCProtocol> SecCreateLocalSecuritydXPCServer(void) NS_RETURNS_RETAINED;
#include <os/transaction_private.h>
#include <os/variant_private.h>
+#include <corecrypto/ccec.h>
#include "keychain/SecureObjectSync/SOSPeerInfoDER.h"
#include <Security/SecureObjectSync/SOSCloudCircle.h>
#include <Security/SecureObjectSync/SOSCloudCircleInternal.h>
#include "trust/trustd/SecTrustStoreServer.h"
#include "keychain/securityd/iCloudTrace.h"
#include "keychain/securityd/spi.h"
+#include <utilities/SecAKSWrappers.h>
#include <utilities/SecCFError.h>
#include <utilities/SecCFWrappers.h>
#include <utilities/SecDb.h>
#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
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);
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;
.allowSyncBubbleKeychain = false,
.isNetworkExtension = false,
.canAccessNetworkExtensionAccessGroups = false,
+ .applicationIdentifier = NULL,
+ .isAppClip = false,
};
secdebug("serverxpc", "entering");
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);
}
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);
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);
}
}
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;
}
}
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)) {
});
}
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) {
});
}
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:
SOSCCRequestToJoinCircle_Server(&error));
}
break;
- case kSecXPCOpRequestToJoinWithAnalytics:
- if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
- CFDataRef parentEvent = NULL;
- SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error);
- xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRequestToJoinCircleWithAnalytics_Server(parentEvent, &error));
- CFReleaseNull(parentEvent);
- }
- break;
case kSecXPCOpAccountHasPublicKey:
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 kSecXPCOpRequestDeviceID:
case kSecXPCOpSetDeviceID:
case kSecXPCOpHandleIDSMessage:
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);
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,
SOSCCCopyViewUnawarePeerInfo_Server(&error),
&error);
}
- break;
+ break;
case kSecXPCOpCopyEngineState:
{
if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
}
}
break;
- case kSecXPCOpCopyPeerPeerInfo:
+ case kSecXPCOpCopyPeerPeerInfo:
if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
SOSCCCopyPeerPeerInfo_Server(&error),
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 kSecXPCOpPeersHaveViewsEnabled:
{
CFArrayRef viewSet = SecXPCDictionaryCopyArray(event, kSecXPCKeyArray, &error);
}
}
break;
-
case kSecXPCOpKVSKeyCleanup:
- if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
+ if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
bool retval = SOSCCCleanupKVSKeys_Server(&error);
xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, retval);
}
break;
-
case kSecXPCOpMessageFromPeerIsPending:
{
SOSPeerInfoRef peer = SecXPCDictionaryCopyPeerInfo(event, kSecXPCKeyPeerInfo, &error);
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);
}
});
#endif
+ 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")) {
// <rdar://problem/22425706> 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;
});
#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;
securityd_init_server();
securityd_xpc_init(serviceName);
-
SecCreateSecuritydXPCServer();
+
#if SECUREOBJECTSYNC
SOSControlServerInitialize();
#endif
+
#if OCTAGON
CKKSControlServerInitialize();
OctagonControlServerInitialize();
#endif
// <rdar://problem/22425706> 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
self->_client.inMultiUser = existingClient->inMultiUser;
self->_client.activeUser = existingClient->activeUser;
#endif
+ self->_client.applicationIdentifier = CFRetainSafe(existingClient->applicationIdentifier);
+ self->_client.isAppClip = existingClient->isAppClip;
}
return self;
}
CFReleaseNull(self->_client.task);
CFReleaseNull(self->_client.accessGroups);
CFReleaseNull(self->_client.musr);
+ CFReleaseNull(self->_client.applicationIdentifier);
}
@end
#include <Security/SecTaskPriv.h>
#include "ipc/securityd_client.h"
#include <Security/SecEntitlements.h>
+#include "sectask/SystemEntitlements.h"
#include <Security/SecItem.h>
#include "utilities/SecCFRelease.h"
#include "utilities/SecCFWrappers.h"
#include "utilities/debugging.h"
+#include <os/feature_private.h>
CFStringRef SecTaskCopyStringForEntitlement(SecTaskRef task,
CFStringRef entitlement)
}
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
{
CFMutableArrayRef groups = NULL;
+ bool onDemandInstallable = SecTaskGetBooleanValueForEntitlement(task, kSystemEntitlementOnDemandInstallCapable);
+
CFArrayRef keychainAccessGroups, appleSecurityApplicationGroups;
CFStringRef appID;
CFArrayRef associatedAppIDs;
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);
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",
}
}
+ // 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,
*/
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);
// Testing support
void SecAccessGroupsSetCurrent(CFArrayRef accessGroups);
+void SecSecurityClientRegularToAppClip(void);
+void SecSecurityClientAppClipToRegular(void);
+void SecSecurityClientSetApplicationIdentifier(CFStringRef identifier);
#endif /* server_security_helpers_h */
#include <Security/SecTaskPriv.h>
#include "ipc/securityd_client.h"
#include <Security/SecEntitlements.h>
+#include "sectask/SystemEntitlements.h"
#include <utilities/SecInternalReleasePriv.h>
#include <sys/codesign.h>
#include <Security/SecItem.h>
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;
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) {
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);
}
#endif
if (!sanityCheckClientAccessGroups(client)) {
+ CFReleaseNull(client->task);
+ CFReleaseNull(client->accessGroups);
+ CFReleaseNull(client->musr);
+ CFReleaseNull(client->applicationIdentifier);
return false;
}
}
}
}
+ 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];
(__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);
[[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));
+}
+
@end
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>DEFAULT-OPTIONS</key>
+ <dict>
+ <key>Default-Privacy-Setting</key>
+ <string>Public</string>
+ <key>Enabled</key>
+ <string>True</string>
+ <key>Persist</key>
+ <string>Default</string>
+ <key>Enable-Oversize-Messages</key>
+ <true/>
+ <key>TTL</key>
+ <string>Default</string>
+ <key>Development</key>
+ <dict>
+ <key>Enabled</key>
+ <string>True</string>
+ <key>Persist</key>
+ <string>Default</string>
+ <key>TTL</key>
+ <string>Default</string>
+ </dict>
+ <key>Debug</key>
+ <dict>
+ <key>Enabled</key>
+ <string>True</string>
+ <key>Persist</key>
+ <string>True</string>
+ <key>TTL</key>
+ <string>2</string>
+ </dict>
+ </dict>
+</dict>
+</plist>
<string>30</string>
</dict>
</dict>
+ <key>itemDelete</key>
+ <dict>
+ <key>Default-Privacy-Setting</key>
+ <string>Public</string>
+ <key>Enabled</key>
+ <string>True</string>
+ <key>Persist</key>
+ <string>True</string>
+ <key>TTL</key>
+ <string>10d</string>
+ <key>Development</key>
+ <dict>
+ <key>Enabled</key>
+ <string>True</string>
+ <key>Persist</key>
+ <string>True</string>
+ <key>TTL</key>
+ <string>10d</string>
+ </dict>
+ </dict>
</dict>
</plist>
<string>123456.test.group</string>
<string>123456.test.group2</string>
</array>
+ <key>com.apple.private.AuthorizationServices</key>
+ <array>
+ <string>com.apple.trust-settings.admin</string>
+ </array>
+ <key>com.apple.private.security.storage.Keychains</key>
+ <true/>
</dict>
</plist>
/* Don't prevent multiple inclusion of this file. */
#include <libsecurity_ssl/regressions/ssl_regressions.h>
#include <libsecurity_keychain/regressions/keychain_regressions.h>
-#include <Breadcrumb/breadcrumb_regressions.h>
#include <libsecurity_cms/regressions/cms_regressions.h>
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_28_sectrustsettings)
ONE_TEST(si_29_cms_chain_mode)
ONE_TEST(si_32_sectrust_pinning_required)
ONE_TEST(si_34_cms_timestamp)
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)
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<array>
+ <dict>
+ <key>PlistDirectory</key>
+ <string>si-20-sectrust-policies-data</string>
+ <key>PlistFileName</key>
+ <string>NSPinnedDomains_ca</string>
+ <key>ExpectedProperties</key>
+ <dict>
+ <key>NSPinnedLeafIdentities</key>
+ <false/>
+ <key>NSPinnedCAIdentities</key>
+ <true/>
+ <key>NSPinnedCAIdentitiesCount</key>
+ <integer>1</integer>
+ <key>NSIncludesSubdomains</key>
+ <true/>
+ </dict>
+ </dict>
+ <dict>
+ <key>PlistDirectory</key>
+ <string>si-20-sectrust-policies-data</string>
+ <key>PlistFileName</key>
+ <string>NSPinnedDomains_leaf</string>
+ <key>ExpectedProperties</key>
+ <dict>
+ <key>NSPinnedLeafIdentities</key>
+ <true/>
+ <key>NSPinnedLeafIdentitiesCount</key>
+ <integer>2</integer>
+ <key>NSPinnedCAIdentities</key>
+ <false/>
+ </dict>
+ </dict>
+ <dict>
+ <key>PlistDirectory</key>
+ <string>si-20-sectrust-policies-data</string>
+ <key>PlistFileName</key>
+ <string>NSPinnedDomains_leaf_and_ca</string>
+ <key>ExpectedProperties</key>
+ <dict>
+ <key>NSPinnedLeafIdentities</key>
+ <true/>
+ <key>NSPinnedLeafIdentitiesCount</key>
+ <integer>1</integer>
+ <key>NSPinnedCAIdentities</key>
+ <true/>
+ <key>NSPinnedCAIdentitiesCount</key>
+ <integer>2</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>PlistDirectory</key>
+ <string>si-20-sectrust-policies-data</string>
+ <key>PlistFileName</key>
+ <string>NSPinnedDomains_without_spki</string>
+ <key>ExpectedProperties</key>
+ <dict>
+ <key>NSPinnedLeafIdentities</key>
+ <false/>
+ <key>NSPinnedCAIdentities</key>
+ <false/>
+ </dict>
+ </dict>
+ <dict>
+ <key>PlistDirectory</key>
+ <string>si-20-sectrust-policies-data</string>
+ <key>PlistFileName</key>
+ <string>NSPinnedDomains_with_empty_spki</string>
+ <key>ExpectedProperties</key>
+ <dict>
+ <key>NSPinnedLeafIdentities</key>
+ <true/>
+ <key>NSPinnedLeafIdentitiesCount</key>
+ <integer>0</integer>
+ <key>NSPinnedCAIdentities</key>
+ <false/>
+ </dict>
+ </dict>
+ <dict>
+ <key>PlistDirectory</key>
+ <string>si-20-sectrust-policies-data</string>
+ <key>PlistFileName</key>
+ <string>NSPinnedDomains_with_invalid_spki</string>
+ <key>ExpectedProperties</key>
+ <dict>
+ <key>NSPinnedLeafIdentities</key>
+ <true/>
+ <key>NSPinnedLeafIdentitiesCount</key>
+ <integer>0</integer>
+ <key>NSPinnedCAIdentities</key>
+ <true/>
+ <key>NSPinnedCAIdentitiesCount</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+</array>
+</plist>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>NSAppTransportSecurity</key>
+ <dict>
+ <key>NSPinnedDomains</key>
+ <dict>
+ <key>example.org</key>
+ <dict>
+ <key>NSIncludesSubdomains</key>
+ <true/>
+ <key>NSPinnedCAIdentities</key>
+ <array>
+ <dict>
+ <key>SPKI-SHA256-BASE64</key>
+ <string>r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=</string> <!-- DigiCert Root -->
+ </dict>
+ </array>
+ </dict> <!-- example.org -->
+ </dict> <!-- NSPinnedDomains -->
+ </dict> <!-- NSAppTransportSecurity -->
+</dict>
+</plist>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>NSAppTransportSecurity</key>
+ <dict>
+ <key>NSPinnedDomains</key>
+ <dict>
+ <key>example.org</key>
+ <dict>
+ <key>NSPinnedLeafIdentities</key>
+ <array>
+ <dict>
+ <key>SPKI-SHA256-BASE64</key>
+ <string>i9HalScvf6T/skE3/A7QOq5n5cTYs8UHNOEFCnkguSI=</string> <!-- example.org (Serial Number 0f:d0:78:dd:48:f1:a2:bd:4d:0f:2b:a9:6b:60:38:fe) -->
+ </dict>
+ <dict>
+ <key>SPKI-SHA256-BASE64</key>
+ <string>i9HalScvf6T/skE3/A7QOq5n5cTYs8UHNOEFCnkguSI=</string>
+ </dict>
+ </array>
+ </dict> <!-- example.org -->
+ </dict> <!-- NSPinnedDomains -->
+ </dict> <!-- NSAppTransportSecurity -->
+</dict>
+</plist>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>NSAppTransportSecurity</key>
+ <dict>
+ <key>NSPinnedDomains</key>
+ <dict>
+ <key>example.org</key>
+ <dict>
+ <key>NSPinnedCAIdentities</key>
+ <array>
+ <dict>
+ <key>SPKI-SHA256-BASE64</key>
+ <string>5kJvNEMw0KjrCAu7eXY5HZdvyCS13BbA0VJG1RSP91w=</string> <!-- DigiCert Intermediate -->
+ </dict>
+ <dict>
+ <key>SPKI-SHA256-BASE64</key>
+ <string>r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=</string> <!-- DigiCert Root -->
+ </dict>
+ </array>
+ <key>NSPinnedLeafIdentities</key>
+ <array>
+ <dict>
+ <key>SPKI-SHA256-BASE64</key>
+ <string>i9HalScvf6T/skE3/A7QOq5n5cTYs8UHNOEFCnkguSI=</string> <!-- example.org (Serial Number 0f:d0:78:dd:48:f1:a2:bd:4d:0f:2b:a9:6b:60:38:fe) -->
+ </dict>
+ </array>
+ </dict> <!-- example.org -->
+ </dict> <!-- NSPinnedDomains -->
+ </dict> <!-- NSAppTransportSecurity -->
+</dict>
+</plist>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>NSAppTransportSecurity</key>
+ <dict>
+ <key>NSPinnedDomains</key>
+ <dict>
+ <key>example.org</key>
+ <dict>
+ <key>NSPinnedLeafIdentities</key>
+ <array>
+ </array>
+ </dict> <!-- example.org -->
+ </dict> <!-- NSPinnedDomains -->
+ </dict> <!-- NSAppTransportSecurity -->
+</dict>
+</plist>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>NSAppTransportSecurity</key>
+ <dict>
+ <key>NSPinnedDomains</key>
+ <dict>
+ <key>example.org</key>
+ <dict>
+ <key>NSPinnedCAIdentities</key>
+ <array>
+ <string>r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=</string> <!-- DigiCert Root (Bad syntax) -->
+ </array>
+ <key>NSPinnedLeafIdentities</key>
+ <string>i9HalScvf6T/skE3/A7QOq5n5cTYs8UHNOEFCnkguSI=</string> <!-- example.org (Bad syntax) (Serial Number 0f:d0:78:dd:48:f1:a2:bd:4d:0f:2b:a9:6b:60:38:fe) -->
+ </dict> <!-- example.org -->
+ </dict> <!-- NSPinnedDomains -->
+ </dict> <!-- NSAppTransportSecurity -->
+</dict>
+</plist>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>NSAppTransportSecurity</key>
+ <dict>
+ <key>NSPinnedDomains</key>
+ <dict>
+ <key>example.org</key>
+ <dict>
+ </dict> <!-- example.org -->
+ </dict> <!-- NSPinnedDomains -->
+ </dict> <!-- NSAppTransportSecurity -->
+</dict>
+</plist>
<key>CertDirectory</key>
<string>si-20-sectrust-policies-data</string>
<key>MajorTestName</key>
- <string>iPhoneProfileSigning</string>
+ <string>iPhoneProfileApplicationSigning</string>
<key>MinorTestName</key>
<string>PositiveTest</string>
<key>Policies</key>
<key>Properties</key>
<dict>
<key>SecPolicyName</key>
- <string>openmarket.ess.apple.com</string>
+ <string>init.ess.apple.com</string>
</dict>
</dict>
<key>Leaf</key>
<key>ChainLength</key>
<integer>3</integer>
<key>VerifyDate</key>
- <date>2019-02-08T21:00:00Z</date>
+ <date>2020-09-15T00:00:00Z</date>
</dict>
<dict>
<key>CertDirectory</key>
<key>MajorTestName</key>
<string>Systemwide-Baseline</string>
<key>MinorTestName</key>
- <string>IDS-IST</string>
+ <string>IDS-PublicTrust</string>
<key>Policies</key>
<dict>
<key>PolicyIdentifier</key>
<key>Properties</key>
<dict>
<key>SecPolicyName</key>
- <string>static.ess.apple.com</string>
+ <string>pds-init.ess.apple.com</string>
</dict>
</dict>
<key>Leaf</key>
- <string>ids_ist_static</string>
+ <string>ids_init_public</string>
<key>Intermediates</key>
- <string>AppleISTCA2G1</string>
+ <string>ApplePublicServerRSA12-G1</string>
<key>Anchors</key>
- <string>GeoTrustGlobalCA</string>
+ <string>AAACertificateServices</string>
<key>ExpectedResult</key>
<integer>4</integer>
<key>ChainLength</key>
<integer>3</integer>
<key>VerifyDate</key>
- <date>2017-12-08T21:00:00Z</date>
+ <date>2020-09-15T00:00:00Z</date>
</dict>
<dict>
<key>CertDirectory</key>
<key>ChainLength</key>
<integer>3</integer>
<key>VerifyDate</key>
- <date>2019-02-08T21:00:00Z</date>
+ <date>2020-09-15T00:00:00Z</date>
</dict>
<dict>
<key>CertDirectory</key>
<key>Properties</key>
<dict>
<key>SecPolicyName</key>
- <string>openmarket.ess.apple.com</string>
+ <string>init.ess.apple.com</string>
<key>SecPolicyPolicyName</key>
<string>IDS</string>
</dict>
<key>ChainLength</key>
<integer>3</integer>
<key>VerifyDate</key>
- <date>2019-02-08T21:00:00Z</date>
+ <date>2020-09-15T00:00:00Z</date>
</dict>
<dict>
<key>CertDirectory</key>
<string>si-20-sectrust-policies-data</string>
+ <key>BridgeOSDisable</key>
+ <true/>
<key>MajorTestName</key>
<string>Systemwide-PolicyName</string>
<key>MinorTestName</key>
<key>Properties</key>
<dict>
<key>SecPolicyName</key>
- <string>static.ess.apple.com</string>
+ <string>pds-init.ess.apple.com</string>
<key>SecPolicyPolicyName</key>
<string>IDS</string>
</dict>
</dict>
<key>Leaf</key>
- <string>ids_ist_static</string>
+ <string>ids_init_public</string>
<key>Intermediates</key>
- <string>AppleISTCA2G1</string>
+ <string>ApplePublicServerRSA12-G1</string>
<key>Anchors</key>
- <string>GeoTrustGlobalCA</string>
+ <string>AAACertificateServices</string>
<key>ExpectedResult</key>
<integer>5</integer>
<key>VerifyDate</key>
- <date>2017-02-08T21:00:00Z</date>
+ <date>2020-09-15T00:00:00Z</date>
</dict>
<dict>
<key>CertDirectory</key>
<key>ChainLength</key>
<integer>3</integer>
<key>VerifyDate</key>
- <date>2019-02-08T21:00:00Z</date>
+ <date>2020-09-15T00:00:00Z</date>
</dict>
<dict>
<key>CertDirectory</key>
<key>Properties</key>
<dict>
<key>SecPolicyName</key>
- <string>static.ess.apple.com</string>
+ <string>init.ess.apple.com</string>
</dict>
</dict>
<key>Leaf</key>
- <string>ids_ist_static</string>
+ <string>ids_test</string>
<key>Intermediates</key>
- <string>AppleISTCA2G1</string>
+ <string>TestAppleServerAuthentication</string>
<key>Anchors</key>
- <string>GeoTrustGlobalCA</string>
+ <string>TestAppleRootCA</string>
<key>ExpectedResult</key>
<integer>4</integer>
<key>VerifyDate</key>
- <date>2017-04-08T20:00:00Z</date>
+ <date>2020-09-15T00:00:00Z</date>
</dict>
<dict>
<key>CertDirectory</key>
<key>VerifyDate</key>
<date>2017-02-20T21:00:00Z</date>
</dict>
+ <dict>
+ <key>CertDirectory</key>
+ <string>si-20-sectrust-policies-data</string>
+ <key>BridgeOSDisable</key>
+ <true/>
+ <key>MajorTestName</key>
+ <string>Systemwide-Both</string>
+ <key>MinorTestName</key>
+ <string>Precedence</string>
+ <key>Policies</key>
+ <dict>
+ <key>PolicyIdentifier</key>
+ <string>1.2.840.113635.100.1.3</string>
+ <key>Properties</key>
+ <dict>
+ <key>SecPolicyName</key>
+ <string>identity.ess.apple.com</string>
+ <key>SecPolicyPolicyName</key>
+ <string>APN</string>
+ </dict>
+ </dict>
+ <key>Leaf</key>
+ <string>ids_test</string>
+ <key>Intermediates</key>
+ <string>TestAppleServerAuthentication</string>
+ <key>Anchors</key>
+ <string>TestAppleRootCA</string>
+ <key>ExpectedResult</key>
+ <integer>5</integer>
+ <key>VerifyDate</key>
+ <date>2020-09-15T00:00:00Z</date>
+ </dict>
<dict>
<key>CertDirectory</key>
<string>si-20-sectrust-policies-data</string>
<key>ChainLength</key>
<integer>3</integer>
</dict>
+ <dict>
+ <key>CertDirectory</key>
+ <string>si-20-sectrust-policies-data</string>
+ <key>MajorTestName</key>
+ <string>iPhoneProfileApplicationSigning</string>
+ <key>MinorTestName</key>
+ <string>PositiveTest</string>
+ <key>Policies</key>
+ <dict>
+ <key>PolicyIdentifier</key>
+ <string>1.2.840.113635.100.1.55</string>
+ </dict>
+ <key>Leaf</key>
+ <string>test_iphone_distribution</string>
+ <key>Intermediates</key>
+ <string>TestAppleWWDR-G3</string>
+ <key>Anchors</key>
+ <string>TestAppleRootCA</string>
+ <key>VerifyDate</key>
+ <date>2020-03-01T20:00:00Z</date>
+ <key>ExpectedResult</key>
+ <integer>4</integer>
+ <key>ChainLength</key>
+ <integer>3</integer>
+ </dict>
+ <dict>
+ <key>CertDirectory</key>
+ <string>si-20-sectrust-policies-data</string>
+ <key>MajorTestName</key>
+ <string>OCSP</string>
+ <key>MinorTestName</key>
+ <string>PositiveTest</string>
+ <key>Policies</key>
+ <dict>
+ <key>PolicyIdentifier</key>
+ <string>1.2.840.113635.100.1.66</string>
+ </dict>
+ <key>Leaf</key>
+ <string>ocsp_responder</string>
+ <key>Anchors</key>
+ <string>OCSP_TestCA</string>
+ <key>VerifyDate</key>
+ <date>2020-08-01T20:00:00Z</date>
+ <key>ExpectedResult</key>
+ <integer>4</integer>
+ <key>ChainLength</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>CertDirectory</key>
+ <string>si-20-sectrust-policies-data</string>
+ <key>MajorTestName</key>
+ <string>OCSP</string>
+ <key>MinorTestName</key>
+ <string>NegativeTest-SubCA</string>
+ <key>Policies</key>
+ <dict>
+ <key>PolicyIdentifier</key>
+ <string>1.2.840.113635.100.1.66</string>
+ </dict>
+ <key>Leaf</key>
+ <string>ocsp_subca</string>
+ <key>Anchors</key>
+ <string>OCSP_TestCA</string>
+ <key>VerifyDate</key>
+ <date>2020-08-01T20:00:00Z</date>
+ <key>ExpectedResult</key>
+ <integer>5</integer>
+ <key>ChainLength</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>CertDirectory</key>
+ <string>si-20-sectrust-policies-data</string>
+ <key>MajorTestName</key>
+ <string>OCSP</string>
+ <key>MinorTestName</key>
+ <string>NegativeTest-MissingEKU</string>
+ <key>Policies</key>
+ <dict>
+ <key>PolicyIdentifier</key>
+ <string>1.2.840.113635.100.1.66</string>
+ </dict>
+ <key>Leaf</key>
+ <string>ocsp_missing_eku</string>
+ <key>Anchors</key>
+ <string>OCSP_TestCA</string>
+ <key>VerifyDate</key>
+ <date>2020-08-01T20:00:00Z</date>
+ <key>ExpectedResult</key>
+ <integer>5</integer>
+ <key>ChainLength</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>CertDirectory</key>
+ <string>si-20-sectrust-policies-data</string>
+ <key>MajorTestName</key>
+ <string>OCSP</string>
+ <key>MinorTestName</key>
+ <string>NegativeTest-MissingKU</string>
+ <key>Policies</key>
+ <dict>
+ <key>PolicyIdentifier</key>
+ <string>1.2.840.113635.100.1.66</string>
+ </dict>
+ <key>Leaf</key>
+ <string>ocsp_missing_ku</string>
+ <key>Anchors</key>
+ <string>OCSP_TestCA</string>
+ <key>VerifyDate</key>
+ <date>2020-08-01T20:00:00Z</date>
+ <key>ExpectedResult</key>
+ <integer>5</integer>
+ <key>ChainLength</key>
+ <integer>2</integer>
+ </dict>
+ <dict>
+ <key>CertDirectory</key>
+ <string>si-20-sectrust-policies-data</string>
+ <key>MajorTestName</key>
+ <string>kSecPolicyCheckLeafSPKISHA256</string>
+ <key>MinorTestName</key>
+ <string>leaf-good</string>
+ <key>Policies</key>
+ <dict>
+ <key>PolicyIdentifier</key>
+ <string>1.2.840.113635.100.1.3</string>
+ <key>Properties</key>
+ <dict>
+ <key>SecPolicyName</key>
+ <string>init.ess.apple.com</string>
+ <key>SecPolicyClient</key>
+ <false/>
+ <key>LeafSPKISHA256</key>
+ <array>
+ <string>QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE=</string>
+ <string>+GxzfmXKLWfWePjBrbCey6zjhsMU/KtGFQExWAnFJeQ=</string>
+ </array>
+ </dict>
+ </dict>
+ <key>Leaf</key>
+ <string>ids_test</string>
+ <key>Intermediates</key>
+ <string>TestAppleServerAuthentication</string>
+ <key>Anchors</key>
+ <string>TestAppleRootCA</string>
+ <key>ExpectedResult</key>
+ <integer>4</integer>
+ <key>ChainLength</key>
+ <integer>3</integer>
+ <key>VerifyDate</key>
+ <date>2020-09-15T00:00:00Z</date>
+ </dict>
+ <dict>
+ <key>CertDirectory</key>
+ <string>si-20-sectrust-policies-data</string>
+ <key>MajorTestName</key>
+ <string>kSecPolicyCheckLeafSPKISHA256</string>
+ <key>MinorTestName</key>
+ <string>leaf-empty</string>
+ <key>Policies</key>
+ <dict>
+ <key>PolicyIdentifier</key>
+ <string>1.2.840.113635.100.1.3</string>
+ <key>Properties</key>
+ <dict>
+ <key>SecPolicyName</key>
+ <string>init.ess.apple.com</string>
+ <key>SecPolicyClient</key>
+ <false/>
+ <key>LeafSPKISHA256</key>
+ <array/>
+ </dict>
+ </dict>
+ <key>Leaf</key>
+ <string>ids_test</string>
+ <key>Intermediates</key>
+ <string>TestAppleServerAuthentication</string>
+ <key>Anchors</key>
+ <string>TestAppleRootCA</string>
+ <key>ExpectedResult</key>
+ <integer>5</integer>
+ <key>ChainLength</key>
+ <integer>3</integer>
+ <key>VerifyDate</key>
+ <date>2020-09-15T00:00:00Z</date>
+ </dict>
+ <dict>
+ <key>CertDirectory</key>
+ <string>si-20-sectrust-policies-data</string>
+ <key>MajorTestName</key>
+ <string>kSecPolicyCheckLeafSPKISHA256</string>
+ <key>MinorTestName</key>
+ <string>leaf-bad</string>
+ <key>Policies</key>
+ <dict>
+ <key>PolicyIdentifier</key>
+ <string>1.2.840.113635.100.1.3</string>
+ <key>Properties</key>
+ <dict>
+ <key>SecPolicyName</key>
+ <string>init.ess.apple.com</string>
+ <key>SecPolicyClient</key>
+ <false/>
+ <key>LeafSPKISHA256</key>
+ <array>
+ <string>QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE=</string>
+ </array>
+ </dict>
+ </dict>
+ <key>Leaf</key>
+ <string>ids_test</string>
+ <key>Intermediates</key>
+ <string>TestAppleServerAuthentication</string>
+ <key>Anchors</key>
+ <string>TestAppleRootCA</string>
+ <key>ExpectedResult</key>
+ <integer>5</integer>
+ <key>ChainLength</key>
+ <integer>3</integer>
+ <key>VerifyDate</key>
+ <date>2020-09-15T00:00:00Z</date>
+ </dict>
+ <dict>
+ <key>CertDirectory</key>
+ <string>si-20-sectrust-policies-data</string>
+ <key>MajorTestName</key>
+ <string>kSecPolicyCheckCAspkiSHA256</string>
+ <key>MinorTestName</key>
+ <string>intermediate-good</string>
+ <key>Policies</key>
+ <dict>
+ <key>PolicyIdentifier</key>
+ <string>1.2.840.113635.100.1.3</string>
+ <key>Properties</key>
+ <dict>
+ <key>SecPolicyName</key>
+ <string>init.ess.apple.com</string>
+ <key>SecPolicyClient</key>
+ <false/>
+ <key>CAspkiSHA256</key>
+ <array>
+ <string>QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE=</string>
+ <string>Yc/8PBtv5TPVDELtY0SUFd5zObsSVVzm7WbLz5eIpQM=</string>
+ </array>
+ </dict>
+ </dict>
+ <key>Leaf</key>
+ <string>ids_test</string>
+ <key>Intermediates</key>
+ <string>TestAppleServerAuthentication</string>
+ <key>Anchors</key>
+ <string>TestAppleRootCA</string>
+ <key>ExpectedResult</key>
+ <integer>4</integer>
+ <key>ChainLength</key>
+ <integer>3</integer>
+ <key>VerifyDate</key>
+ <date>2020-09-15T00:00:00Z</date>
+ </dict>
+ <dict>
+ <key>CertDirectory</key>
+ <string>si-20-sectrust-policies-data</string>
+ <key>MajorTestName</key>
+ <string>kSecPolicyCheckCAspkiSHA256</string>
+ <key>MinorTestName</key>
+ <string>intermediate-empty</string>
+ <key>Policies</key>
+ <dict>
+ <key>PolicyIdentifier</key>
+ <string>1.2.840.113635.100.1.3</string>
+ <key>Properties</key>
+ <dict>
+ <key>SecPolicyName</key>
+ <string>init.ess.apple.com</string>
+ <key>SecPolicyClient</key>
+ <false/>
+ <key>CAspkiSHA256</key>
+ <array/>
+ </dict>
+ </dict>
+ <key>Leaf</key>
+ <string>ids_test</string>
+ <key>Intermediates</key>
+ <string>TestAppleServerAuthentication</string>
+ <key>Anchors</key>
+ <string>TestAppleRootCA</string>
+ <key>ExpectedResult</key>
+ <integer>5</integer>
+ <key>ChainLength</key>
+ <integer>3</integer>
+ <key>VerifyDate</key>
+ <date>2020-09-15T00:00:00Z</date>
+ </dict>
+ <dict>
+ <key>CertDirectory</key>
+ <string>si-20-sectrust-policies-data</string>
+ <key>MajorTestName</key>
+ <string>kSecPolicyCheckCAspkiSHA256</string>
+ <key>MinorTestName</key>
+ <string>intermediate-bad</string>
+ <key>Policies</key>
+ <dict>
+ <key>PolicyIdentifier</key>
+ <string>1.2.840.113635.100.1.3</string>
+ <key>Properties</key>
+ <dict>
+ <key>SecPolicyName</key>
+ <string>init.ess.apple.com</string>
+ <key>SecPolicyClient</key>
+ <false/>
+ <key>CAspkiSHA256</key>
+ <array>
+ <string>QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE=</string>
+ </array>
+ </dict>
+ </dict>
+ <key>Leaf</key>
+ <string>ids_test</string>
+ <key>Intermediates</key>
+ <string>TestAppleServerAuthentication</string>
+ <key>Anchors</key>
+ <string>TestAppleRootCA</string>
+ <key>ExpectedResult</key>
+ <integer>5</integer>
+ <key>ChainLength</key>
+ <integer>3</integer>
+ <key>VerifyDate</key>
+ <date>2020-09-15T00:00:00Z</date>
+ </dict>
+ <dict>
+ <key>CertDirectory</key>
+ <string>si-20-sectrust-policies-data</string>
+ <key>MajorTestName</key>
+ <string>kSecPolicyCheckCAspkiSHA256</string>
+ <key>MinorTestName</key>
+ <string>root-good</string>
+ <key>Policies</key>
+ <dict>
+ <key>PolicyIdentifier</key>
+ <string>1.2.840.113635.100.1.3</string>
+ <key>Properties</key>
+ <dict>
+ <key>SecPolicyName</key>
+ <string>init.ess.apple.com</string>
+ <key>SecPolicyClient</key>
+ <false/>
+ <key>CAspkiSHA256</key>
+ <array>
+ <string>QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE=</string>
+ <string>pmuYhKz98VG4gaGpUvi3y7CEl5+yJNGQ8/ARWg4FVnw=</string>
+ </array>
+ </dict>
+ </dict>
+ <key>Leaf</key>
+ <string>ids_test</string>
+ <key>Intermediates</key>
+ <string>TestAppleServerAuthentication</string>
+ <key>Anchors</key>
+ <string>TestAppleRootCA</string>
+ <key>ExpectedResult</key>
+ <integer>4</integer>
+ <key>ChainLength</key>
+ <integer>3</integer>
+ <key>VerifyDate</key>
+ <date>2020-09-15T00:00:00Z</date>
+ </dict>
+ <dict>
+ <key>CertDirectory</key>
+ <string>si-20-sectrust-policies-data</string>
+ <key>MajorTestName</key>
+ <string>kSecPolicyCheckCAspkiSHA256</string>
+ <key>MinorTestName</key>
+ <string>leaf-good-intermediate-good-root-good</string>
+ <key>Policies</key>
+ <dict>
+ <key>PolicyIdentifier</key>
+ <string>1.2.840.113635.100.1.3</string>
+ <key>Properties</key>
+ <dict>
+ <key>SecPolicyName</key>
+ <string>init.ess.apple.com</string>
+ <key>SecPolicyClient</key>
+ <false/>
+ <key>LeafSPKISHA256</key>
+ <array>
+ <string>QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE=</string>
+ <string>+GxzfmXKLWfWePjBrbCey6zjhsMU/KtGFQExWAnFJeQ=</string>
+ </array>
+ <key>CAspkiSHA256</key>
+ <array>
+ <string>QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE=</string>
+ <string>Yc/8PBtv5TPVDELtY0SUFd5zObsSVVzm7WbLz5eIpQM=</string>
+ <string>QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE=</string>
+ <string>pmuYhKz98VG4gaGpUvi3y7CEl5+yJNGQ8/ARWg4FVnw=</string>
+ </array>
+ </dict>
+ </dict>
+ <key>Leaf</key>
+ <string>ids_test</string>
+ <key>Intermediates</key>
+ <string>TestAppleServerAuthentication</string>
+ <key>Anchors</key>
+ <string>TestAppleRootCA</string>
+ <key>ExpectedResult</key>
+ <integer>4</integer>
+ <key>ChainLength</key>
+ <integer>3</integer>
+ <key>VerifyDate</key>
+ <date>2020-09-15T00:00:00Z</date>
+ </dict>
+ <dict>
+ <key>CertDirectory</key>
+ <string>si-20-sectrust-policies-data</string>
+ <key>MajorTestName</key>
+ <string>kSecPolicyCheckCAspkiSHA256</string>
+ <key>MinorTestName</key>
+ <string>leaf-bad-intermediate-good-root-good</string>
+ <key>Policies</key>
+ <dict>
+ <key>PolicyIdentifier</key>
+ <string>1.2.840.113635.100.1.3</string>
+ <key>Properties</key>
+ <dict>
+ <key>SecPolicyName</key>
+ <string>init.ess.apple.com</string>
+ <key>SecPolicyClient</key>
+ <false/>
+ <key>LeafSPKISHA256</key>
+ <array>
+ <string>QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE=</string>
+ </array>
+ <key>CAspkiSHA256</key>
+ <array>
+ <string>QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE=</string>
+ <string>Yc/8PBtv5TPVDELtY0SUFd5zObsSVVzm7WbLz5eIpQM=</string>
+ <string>QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE=</string>
+ <string>pmuYhKz98VG4gaGpUvi3y7CEl5+yJNGQ8/ARWg4FVnw=</string>
+ </array>
+ </dict>
+ </dict>
+ <key>Leaf</key>
+ <string>ids_test</string>
+ <key>Intermediates</key>
+ <string>TestAppleServerAuthentication</string>
+ <key>Anchors</key>
+ <string>TestAppleRootCA</string>
+ <key>ExpectedResult</key>
+ <integer>5</integer>
+ <key>ChainLength</key>
+ <integer>3</integer>
+ <key>VerifyDate</key>
+ <date>2020-09-15T00:00:00Z</date>
+ </dict>
</array>
</plist>
#import <Security/SecKeyPriv.h>
#import <Security/SecAccessControlPriv.h>
#import <libaks_acl_cf_keys.h>
-#if !TARGET_OS_OSX
#import "MobileGestalt.h"
-#else
-#import <RemoteServiceDiscovery/RemoteServiceDiscovery.h>
-#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 {
} 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);
}
}
-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);
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);
- error = nil;
- id sysUikP = CFBridgingRelease(SecKeyCopyAttestationKey(kSecKeyAttestationKeyTypeUIKProposed, (void *)&error));
- ok(sysUikP != nil, "get UIK-proposed key: %@", 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;
- NSData *attUIKC = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikC, (__bridge SecKeyRef)privKey, (void *)&error));
- ok(attUIKC != nil, "Sys-UIK-committed attesting privKey: %@", 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 *attUIKP = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikP, (__bridge SecKeyRef)privKey, (void *)&error));
- ok(attUIKP != nil, "Sys-UIK-proposed attesting privKey: %@", error);
+ NSData *attSysKeyP = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysKeyP, (__bridge SecKeyRef)privKey, (void *)&error));
+ ok(attSysKeyP != nil, "%s-proposed attesting privKey: %@", name, 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");
+ 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)sysUikC, kSecKeyControlLifetimeTypeBump, (void *)&error);
- ok(res, "bumping sys-uik: %@", error);
+ BOOL res = SecKeyControlLifetime((__bridge SecKeyRef)sysKeyC, kSecKeyControlLifetimeTypeBump, (void *)&error);
+ ok(res, "bumping %s: %@", name, error);
+ if (canAttest) {
error = nil;
- NSData *attUIKCN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikC, (__bridge SecKeyRef)privKey, (void *)&error));
- ok(attUIKCN != nil, "Sys-UIK-committed attesting privKey: %@", error);
+ NSData *attSysKeyCN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysKeyC, (__bridge SecKeyRef)privKey, (void *)&error));
+ ok(attSysKeyCN != nil, "%s-committed attesting privKey: %@", name, error);
error = nil;
- NSData *attUIKPN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikP, (__bridge SecKeyRef)privKey, (void *)&error));
- ok(attUIKPN != nil, "Sys-UIK-proposed attesting privKey: %@", error);
+ NSData *attSysKeyPN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysKeyP, (__bridge SecKeyRef)privKey, (void *)&error));
+ ok(attSysKeyPN != nil, "%s-proposed attesting privKey: %@", name, 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");
+ 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)sysUikP, kSecKeyControlLifetimeTypeCommit, (void *)&error);
- ok(res, "committing sys-uik: %@", error);
+ res = SecKeyControlLifetime((__bridge SecKeyRef)sysKeyP, kSecKeyControlLifetimeTypeCommit, (void *)&error);
+ ok(res, "committing %s: %@", name, error);
+ if (canAttest) {
error = nil;
- NSData *attUIKCNN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikC, (__bridge SecKeyRef)privKey, (void *)&error));
- ok(attUIKCNN != nil, "Sys-UIK-committed attesting privKey: %@", error);
+ NSData *attSysKeyCNN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysKeyC, (__bridge SecKeyRef)privKey, (void *)&error));
+ ok(attSysKeyCNN != nil, "%s-committed attesting privKey: %@", name, error);
error = nil;
- NSData *attUIKPNN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysUikP, (__bridge SecKeyRef)privKey, (void *)&error));
- ok(attUIKPNN != nil, "Sys-UIK-proposed attesting privKey: %@", error);
+ NSData *attSysKeyPNN = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sysKeyP, (__bridge SecKeyRef)privKey, (void *)&error));
+ ok(attSysKeyPNN != nil, "%s-proposed attesting privKey: %@", name, 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");
+ 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-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);
+ // 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 *attSIKUIKC = CFBridgingRelease(SecKeyCreateAttestation((__bridge SecKeyRef)sik, (__bridge SecKeyRef)sysUikC, (void *)&error));
- ok(attSIKUIKC != nil, "SIK attesting Sys-UIK-committed, error: %@", 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) {
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;
-#endif
- plan_tests(testPKA ? 119 : 104);
+ NSNumber *hasPKA = CFBridgingRelease(MGCopyAnswer(kMGQHasPKA, NULL));
+ plan_tests(hasPKA.boolValue ? 207 : 113);
secAccessControlDescriptionTest();
- secKeySepTest(testPKA);
- attestationTest(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, NO);
- attestationTest(kSecAttrAccessibleUntilReboot, YES);
+ 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
+
+ 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;
}
// 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];
+++ /dev/null
-/*
- * si-88-sectrust-valid.m
- * Security
- *
- * Copyright (c) 2017-2019 Apple Inc. All Rights Reserved.
- *
- */
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <Security/Security.h>
-#include <Security/SecTrust.h>
-#include <Security/SecPolicy.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <utilities/SecCFWrappers.h>
-
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-
-#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 <Foundation/Foundation.h>
-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;
-}
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);
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);
#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);
#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);
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");
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");
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");
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");
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");
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");
}
}
+#if 0
static CFCalendarRef sZuluCalendar = NULL;
static CFCalendarRef SecCFCalendarGetZulu() {
dispatch_release(dgroup);
return !stop;
}
+#endif
// We expect this to fail until this is fixed:
// <rdar://problem/16372688> CFCalendarDecomposeAbsoluteTime is not thread safe
//
+#if 0
static void testWithUnguardedZuluCalendar() {
const bool useSharedZuluCalendar = true;
__block bool success = true;
ok(success,"unexpected result from CFCalendarDecomposeAbsoluteTime");
}
+#endif
#define kTestsPerTestCase 12
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);
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);
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");
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");
#include <utilities/SecCFRelease.h>
#include <utilities/SecDb.h>
+#include <utilities/SecDbInternal.h>
#include <CoreFoundation/CoreFoundation.h>
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);
}
}
#include <utilities/SecCFWrappers.h>
#include <utilities/SecDb.h>
+#include <utilities/SecDbInternal.h>
#include <utilities/SecDispatchRelease.h>
#include <CoreFoundation/CoreFoundation.h>
#include "utilities_regressions.h"
#include <time.h>
-#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;
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,
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);
+++ /dev/null
-/*
- * 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 <AggregateDictionary/ADClient.h>
-
-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
-}
-
+++ /dev/null
-/*
- * 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@
- */
-
-#ifndef SecADWrapper_h
-#define SecADWrapper_h
-
-#include <TargetConditionals.h>
-#include <CoreFoundation/CoreFoundation.h>
-
-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);
-
-#endif /* SecADWrapper_h */
#include <utilities/SecCFCCWrappers.h>
+#include <utilities/simulatecrash_assert.h>
+
CFDataRef CFDataCreateDigestWithBytes(CFAllocatorRef allocator, const struct ccdigest_info *di, size_t len,
const void *data, CFErrorRef *error) {
CFMutableDataRef digest = CFDataCreateMutable(allocator, di->output_size);
#include <utilities/SecCFRelease.h>
#include <utilities/debugging.h>
#include <notify.h>
-
+#include "keychain/SecureObjectSync/SOSInternal.h"
+#include <Security/OTConstants.h>
//
// OSStatus values we magically know
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 SecError(OSStatus status, CFErrorRef *error, CFStringRef format, ...) {
+ 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);
-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);
+ *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;
-}
-
-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);
- }
return false;
}
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,
{
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;
+
+ 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);
+ }
- *newError = CFErrorCreateWithUserInfoKeysAndValues(kCFAllocatorDefault, domain, errorCode,
- keys, values, numEntriesToUse);
+ CFMutableDictionaryRef newUserInfo = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
- CFReleaseNull(formattedString);
- if (previousError)
- secdebug("error_thee_well", "encapsulated %@ with new error: %@", previousError, *newError);
+ if (previousError) {
+ CFDictionaryAddValue(newUserInfo, kCFErrorUnderlyingErrorKey, previousError);
+ }
+ if (newCount) {
+ CFDictionaryAddValue(newUserInfo, kSOSCountKey, newCount);
+ }
+ if (formattedString) {
+ CFDictionaryAddValue(newUserInfo, kCFErrorDescriptionKey, formattedString);
+ }
+
+ *newError = CFErrorCreate(kCFAllocatorDefault, domain, errorCode, newUserInfo);
- CFReleaseNull(replacing);
+ if (previousError) {
+ secdebug("error_thee_well", "encapsulated %@ with new error: %@", previousError, *newError);
+ }
+ 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;
}
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);
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;
}
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;
}
// 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;
}
// 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;
}
#include <IOKit/IOReturn.h>
-#include <assert.h>
+#include "utilities/simulatecrash_assert.h"
#include <dispatch/dispatch.h>
#include <stdlib.h>
#include <string.h>
// Usage: void foo(CFTypeRef value) { CFDataRef data = CFCast(CFData, value); }
#define CFCast(type, value) \
- ((value != NULL) && CFGetTypeID(value) == type ## GetTypeID() ? (type ## Ref)(value) : NULL)
+ ({ __typeof__(value) _v = (value); (_v != NULL) && CFGetTypeID(_v) == type ## GetTypeID() ? (type ## Ref)_v : NULL; })
-#define CFCastWithError(type, value, error) \
- ((value != NULL) && CFGetTypeID(value) == type ## GetTypeID() ? \
- (type ## Ref)(value) : \
- (SecError(errSecParam, error, CFSTR("Unexpected type")), 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
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);
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);
//
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);
}
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));
}
* @APPLE_LICENSE_HEADER_END@
*/
-#import <Foundation/Foundation.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+void SecCoreAnalyticsSendValue(CFStringRef _Nonnull eventName, int64_t value);
#if __OBJC__
+#import <Foundation/Foundation.h>
+
NS_ASSUME_NONNULL_BEGIN
+extern NSString* const SecCoreAnalyticsValue;
+
@interface SecCoreAnalytics : NSObject
+ (void)sendEvent:(NSString*) eventName event:(NSDictionary<NSString*,NSObject*> *)event;
#import <SoftLinking/SoftLinking.h>
#import <Availability.h>
+NSString* const SecCoreAnalyticsValue = @"value";
+
+
+void SecCoreAnalyticsSendValue(CFStringRef _Nonnull eventName, int64_t value)
+{
+ [SecCoreAnalytics sendEvent:(__bridge NSString*)eventName
+ event:@{
+ SecCoreAnalyticsValue: [NSNumber numberWithLong:value],
+ }];
+}
+
@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<NSString*,NSObject*>* eventPayload),(eventName, eventPayload));
#include "SecDb.h"
+#include "SecDbInternal.h"
#include "debugging.h"
#include <sqlite3.h>
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;
+ // 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;
SecDbCopyFormatDescription(CFTypeRef value, CFDictionaryRef formatOptions)
{
SecDbRef db = (SecDbRef)value;
- return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("<SecDb path:%@ connections: %@>"), db->db_path, db->connections);
+ return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("<SecDb path:%@ connections: %@>"), db->db_path, db->idleReadConnections);
}
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;
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;
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);
+ if (pthread_mutex_init(&(db->writeMutex), 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
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 */
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);
}
CFReleaseSafe(changes);
}
+#endif
}
static void SecDbOnNotify(SecDbConnectionRef dbconn, void (^perform)(void)) {
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"));
-}
-
static sqlite3 *_SecDbOpenV2(const char *path,
int flags,
int useWAL,
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;
}
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;
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)) {
}
}
-
if (dbconn && !ranOpenedHandler && dbconn->db->opened) {
dispatch_sync(db->queue, ^{
if (dbconn->db->callOpenedHandlerForNextConnection) {
}
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);
}
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) {
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, ^{
- CFArrayForEach(db->connections, ^(const void* p) {
- SecDbConnectionRef connection = (SecDbConnectionRef)p;
-
- // this pointer is claimed to be nonretained
- connection->db = NULL;
-
- if(connection->handle) {
- sqlite3_close(connection->handle);
- connection->handle = NULL;
- }
- });
- CFArrayRemoveAllValues(db->connections);
- dispatch_semaphore_signal(db->write_semaphore);
- dispatch_semaphore_signal(db->read_semaphore);
+ onQueueSecDbForceCloseForCache(db->idleReadConnections);
+ onQueueSecDbForceCloseForCache(db->idleWriteConnections);
});
}
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,
--- /dev/null
+#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 */
CFURLRef SecCopyURLForFileInRevocationInfoDirectory(CFStringRef fileName)
{
+#if TARGET_OS_OSX
+ return SecCopyURLForFileInBaseDirectory(true, CFSTR("private/var/protected/trustd/"), fileName);
+#else
return SecCopyURLForFileInBaseDirectory(true, CFSTR("Library/Keychains/crls/"), fileName);
+#endif
+}
+
+CFURLRef SecCopyURLForFileInProtectedDirectory(CFStringRef fileName)
+{
+ return SecCopyURLForFileInBaseDirectory(true, CFSTR("private/var/protected/"), fileName);
}
static void WithPathInDirectory(CFURLRef fileURL, void(^operation)(const char *utf8String))
WithPathInDirectory(SecCopyURLForFileInUserCacheDirectory(fileName), operation);
}
+void WithPathInProtectedDirectory(CFStringRef fileName, void(^operation)(const char *utf8String))
+{
+ WithPathInDirectory(SecCopyURLForFileInProtectedDirectory(fileName), operation);
+}
+
void SetCustomHomeURL(CFURLRef url)
{
sCustomHomeURL = CFRetainSafe(url);
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 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);
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);
* 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
return errorClasses;
}
++ (NSSet<Class> *)safeCKErrorPrimitiveClasses
+{
+ static NSMutableSet<Class> *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<Class> *)safeErrorCollectionClasses
{
static NSMutableSet<Class> *errorClasses = nil;
"NSError",
"NSOrderedSet",
"NSSet",
+ "NSURLError",
};
for (unsigned n = 0; n < sizeof(classes) / sizeof(classes[0]); n++) {
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];
}
static NSString *kArchiveKeyError = @"error";
-+ (NSError *)errorFromEncodedData:(NSData *)data
++ (NSError * _Nullable)errorFromEncodedData:(NSData *)data
{
NSKeyedUnarchiver *unarchiver = nil;
NSError *error = nil;
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);
}
-
-
-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)
{
#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. */
#include <CoreFoundation/CoreFoundation.h>
-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);
{
der_end = der_encode_plist(CFArrayGetValueAtIndex(array, position), error, 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);
}
#include <CoreFoundation/CoreFoundation.h>
-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);
{
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);
}
#include <CoreFoundation/CoreFoundation.h>
-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);
{
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);
}
/* 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;
}
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;
}
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;
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,
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;
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,
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);
}
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);
+}
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_ */
#include <corecrypto/ccder.h>
#include <CoreFoundation/CoreFoundation.h>
-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)
{
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;
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);
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);
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);
static uint8_t* der_encode_key_value(CFPropertyListRef key, CFPropertyListRef value, CFErrorRef *error,
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(key, error, der,
+ der_encode_plist(value, error, der, der_end))),
+ error);
}
struct encode_context {
}
}
-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);
}
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;
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);
}
#include <CoreFoundation/CoreFoundation.h>
-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);
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);
}
#include <CoreFoundation/CoreFoundation.h>
-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);
if (payload_size > sizeof(long long)) {
SecCFDERCreateError(kSecDERErrorUnsupportedNumberType, CFSTR("Number too large"), NULL, error);
return NULL;
-
}
long long value = 0;
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));
}
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)
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);
}
#include <corecrypto/ccder.h>
#include <CoreFoundation/CoreFoundation.h>
+#include "utilities/simulatecrash_assert.h"
+
//
// der..CFPropertyList
//
//
//
-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;
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);
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);
else if (CFSetGetTypeID() == 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;
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);
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;
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);
#include "utilities/der_plist_internal.h"
#include "utilities/SecCFError.h"
#include "utilities/SecCFRelease.h"
+#include "utilities/der_plist.h"
#include <CoreFoundation/CoreFoundation.h>
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;
+}
#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);
-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);
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);
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);
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);
uint8_t* der_encode_dictionary(CFDictionaryRef dictionary, CFErrorRef *error,
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);
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);
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);
uint8_t* der_encode_set(CFSetRef set, CFErrorRef *error,
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);
#include <corecrypto/ccder.h>
#include <CoreFoundation/CoreFoundation.h>
-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);
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);
}
}
-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);
}
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;
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);
}
#include <corecrypto/ccder.h>
// 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);
#include <CoreFoundation/CoreFoundation.h>
-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);
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);
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);
}
--- /dev/null
+/*
+* 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;
+}
--- /dev/null
+/*
+* 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 <CoreFoundation/CoreFoundation.h>
+#include <sys/cdefs.h>
+
+__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 */
#import <SoftLinking/SoftLinking.h>
#import <Foundation/Foundation.h>
-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),
--- /dev/null
+/*
+ * 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 <assert.h>
+#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_ */
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Project</key>
</array>
<key>Disabled</key>
<string>BATS_UTD_Disabled_keychainnetworkextensionsharing_1</string>
+ <key>MayRunConcurrently</key>
+ <false/>
</dict>
<dict>
<key>TestName</key>
</array>
<key>Disabled</key>
<string>BATS_UTD_Disabled_keychainnetworkextensionsharing_2</string>
+ <key>MayRunConcurrently</key>
+ <false/>
</dict>
<dict>
<key>TestName</key>
</array>
<key>Disabled</key>
<string>BATS_UTD_Disabled_keychainnetworkextensionsharing_3</string>
+ <key>MayRunConcurrently</key>
+ <false/>
</dict>
<dict>
<key>TestName</key>
</dict>
<dict>
<key>TestName</key>
- <string>KeychainSecd_macOS</string>
+ <string>KeychainSecd</string>
<key>ShowSubtestResults</key>
<true/>
<key>Command</key>
<array>
- <string>BATS_XCTEST_CMD</string>
- <string>/AppleInternal/XCTests/com.apple.security/secdxctests_mac.xctest</string>
+ <string>/AppleInternal/CoreOS/tests/Security/KeychainEntitledTestRunner</string>
+ <string>-t</string>
+ <string>secdxctests</string>
</array>
<key>Disabled</key>
- <string>BATS_UTD_Disabled_KeychainSecd_macOS</string>
+ <string>BATS_UTD_Disabled_KeychainSecdXCTests</string>
</dict>
<dict>
<key>TestName</key>
- <string>KeychainSecd_iOS</string>
+ <string>SecDbBackupTests</string>
+ <key>WorkingDirectory</key>
+ <string>/AppleInternal/XCTests/com.apple.security/</string>
<key>ShowSubtestResults</key>
<true/>
<key>Command</key>
<array>
- <string>BATS_XCTEST_CMD</string>
- <string>/AppleInternal/XCTests/com.apple.security/secdxctests_ios.xctest</string>
+ <string>/AppleInternal/CoreOS/tests/Security/KeychainEntitledTestRunner</string>
+ <string>-t</string>
+ <string>SecDbBackupTests</string>
</array>
<key>Disabled</key>
- <string>BATS_UTD_Disabled_KeychainSecd_iOS</string>
+ <string>BATS_UTD_Disabled_KeychainSecDbBackupTests</string>
</dict>
<dict>
<key>TestName</key>
<key>Disabled</key>
<string>BATS_UTD_Disabled_SecurityUtiltitesTests</string>
</dict>
+ <dict>
+ <key>TestName</key>
+ <string>SecCodeAPITest</string>
+ <key>Command</key>
+ <array>
+ <string>/AppleInternal/CoreOS/tests/Security/secseccodeapitest</string>
+ </array>
+ <key>Disabled</key>
+ <string>BATS_UTD_Disabled_SecCodeAPITest</string>
+ <key>ShowSubtestResults</key>
+ <true/>
+ </dict>
</array>
</dict>
</plist>
#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_
#elif TARGET_OS_OSX
/* For MacOS, we disable the iOS only tests. */
#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_
+
+#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_
+
+#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_
#else
/* By default, assume iOS platforms. We disable the MacOS only tests. */
#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_
#endif
-//
-// 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
#include <Security/SecItemPriv.h>
#include <notify.h>
#include <err.h>
+#import <TargetConditionals.h>
int
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");
*/
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;
/*
*/
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;
}
(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,
(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
--- /dev/null
+//
+// secseccodeapitest.c
+// secseccodeapitest
+//
+
+#include "authd_private.h"
+
+#include <stdio.h>
+#include <xpc/xpc.h>
+#include <Security/SecCode.h>
+#include <libkern/OSAtomic.h>
+#include <AssertMacros.h>
+
+#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;
+}
+
+int main(void)
+{
+ fprintf(stdout, "[TEST] secseccodeapitest\n");
+
+ int i;
+ int (*testList[])(void) = {
+ CheckCreateWithXPCMessage,
+ CheckCreateWithXPCMessage_invalidXPCObject,
+ CheckCreateWithXPCMessage_NULLConnectionInObject
+ };
+ 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;
+}
SEC_EXP_CLASS(SecuritydXPCClient)
#if __OBJC2__
-SEC_EXP_CLASS(SFSignInAnalytics)
SEC_EXP_CLASS(SecXPCHelper)
SEC_EXP_CLASS(OTClique)
SEC_EXP_CLASS(OTConfigurationContext)
_OTDefaultsDomain
_OTDefaultsOctagonEnable
_OTTrustStatusChangeNotification
-
-_OctagonEventAttributeZoneName
-_OctagonEventAttributeFailureReason
-_OctagonEventAttributeTimeSinceLastPostedFollowUp
+_OTEscrowRecordPrefix
_SecEscrowRequestHavePrecord
_SecEscrowRequestPendingPasscode
_SecEscrowRequestPendingCertificate
-_OTCKContainerName
-_CuttlefishTrustZone
_CuttlefishErrorDomain
-_TrustedPeersHelperErrorDomain
_CuttlefishErrorRetryAfterKey
_OctagonPlatformSupportsSOS
_OctagonAuthoritativeTrustSetIsEnabled
_OctagonIsSOSFeatureEnabled
_OctagonSetSOSFeatureEnabled
+_OctagonIsOptimizationEnabled
+_OctagonSetOptimizationEnabled
+_OctagonSetEscrowRecordFetchEnabled
+_OctagonIsEscrowRecordFetchEnabled
+_SecKVSOnCloudKitIsEnabled
+_SecKVSOnCloudKitSetOverrideIsEnabled
+_SecErrorIsNestedErrorCappingEnabled
+_SecErrorSetOverrideNestedErrorCappingIsEnabled
SEC_EXP_CLASS(OTJoiningConfiguration)
SEC_EXP_CLASS(OTControl)
_SecAccessGroupsGetCurrent
_SecAccessGroupsSetCurrent
_SecSecurityClientGet
+_SecSecurityClientRegularToAppClip
+_SecSecurityClientAppClipToRegular
+_SecSecurityClientSetApplicationIdentifier
_securityd_create_message
_securityd_message_with_reply_sync
_securityd_message_no_error
_SecDERItemCopyOIDDecimalRepresentation
_SecDigestCreate
-_SecFrameworkCopyResourceURL
_SecCopyErrorMessageString
_SecFrameworkCopyIPAddressData
_AuthorizationFree
_AuthorizationFreeItemSet
_AuthorizationMakeExternalForm
-_AuthorizationPreauthorizeCredentials
_AuthorizationRightGet
_AuthorizationRightRemove
_AuthorizationRightSet
_AuthorizationEnableSmartCard
+_AuthorizationCopyPreloginUserDatabase
+_AuthorizationCopyRightProperties
_SessionCreate
_SessionGetInfo
_SessionSetDistinguishedUser
_SecFDERecoveryUnwrapCRSKWithPrivKey
_SecFDERecoveryWrapCRSKWithPubKey
_SecGenericPasswordCreate
-_SecIdentityAddPreferenceItem
-_SecIdentityCompare
-_SecIdentityCopyFromPreferenceItem
_SecIdentityCopyPreference
_SecIdentityCopyPreferred
_SecIdentityCopySystemIdentity
_SecIdentityCreateWithCertificate
-_SecIdentityFindPreferenceItem
_SecIdentitySearchCopyNext
_SecIdentitySearchCreate
_SecIdentitySearchCreateWithAttributes
_SecIdentitySetPreference
_SecIdentitySetPreferred
_SecIdentitySetSystemIdentity
-_SecIdentityUpdatePreferenceItem
_SecInferLabelFromX509Name
_SecItemAdd_ios
_SecItemCopyMatching_ios
-_SecItemUpdateTokenItems_ios
+_SecItemUpdateTokenItemsForAccessGroups
_SecKeyGeneratePair_ios
_SecKeychainAddCallback
_SecKeychainAddDBToKeychainList
_SecKeychainAddGenericPassword
-_SecKeychainAddIToolsPassword
_SecKeychainAddInternetPassword
_SecKeychainAttemptMigrationWithMasterKey
_SecKeychainAttributeInfoForItemID
_SecKeychainMDSInstall
_SecKeychainMakeFromFullPath
_SecKeychainOpen
-_SecKeychainOpenWithGuid
_SecKeychainRecodeKeychain
_SecKeychainRemoveCallback
_SecKeychainRemoveDBFromKeychainList
_SecCodeCopyGuestWithAttributes
_SecCodeCreateWithAuditToken
_SecCodeCreateWithPID
+_SecCodeCreateWithXPCMessage
_SecCodeCheckValidity
_SecCodeCheckValidityWithErrors
_SecCodeCopyPath
_kSecCodeInfoDiskRepVersionSDK
_kSecCodeInfoResourceDirectory
_kSecCodeInfoNotarizationDate
+_kSecCodeInfoSignatureVersion
_kSecGuestAttributeCanonical
_kSecGuestAttributeDynamicCode
_kSecGuestAttributeDynamicCodeInfoPlist
_SecStaticCodeCheckValidity
_SecStaticCodeCreateWithPath
_SecStaticCodeGetTypeID
+_SecStaticCodeSetCallback
+_SecStaticCodeSetValidationConditions
+_SecStaticCodeCancelValidation
_kSecCFErrorArchitecture
_kSecCFErrorGuestAttributes
_kSecCFErrorInfoPlist
_kSecCodeAttributeArchitecture
_kSecCodeAttributeBundleVersion
_kSecCodeAttributeSubarchitecture
+_kSecCodeDirectoryFlagTable
_kSecCodeInfoCMS
_kSecCodeInfoCMSDigest
_kSecCodeInfoCMSDigestHashType
_kSecCodeInfoRequirementData
_kSecCodeInfoRequirements
_kSecCodeInfoResourceDirectory
+_kSecCodeInfoSignatureVersion
_kSecCodeInfoSource
_kSecCodeInfoStatus
_kSecCodeInfoTimestamp
#endif // TARGET_OS_IPHONE
-#if TARGET_OS_OSX
-//breadcrumb
-_SecBreadcrumbCreateFromPassword
-_SecBreadcrumbCopyPassword
-_SecBreadcrumbCreateNewEncryptedKey
-#endif // TARGET_OS_OSX
-
//
// libDER OIDs
//
_SecTranslocateURLShouldRunTranslocated
_SecTranslocateIsTranslocatedURL
_SecTranslocateCreateOriginalPathForURL
+_SecTranslocateCreateGeneric
#endif // TARGET_OS_OSX
#if TARGET_OS_OSX
_OBJC_CLASS_$_SFAnalyticsSampler
_OBJC_CLASS_$_SFAnalyticsSQLiteStore
_OBJC_CLASS_$_SecCoreAnalytics
-_OBJC_METACLASS_$_SFSignInAnalytics
+_SecCoreAnalyticsValue
+_SecCoreAnalyticsSendValue
_SFAnalyticsMaxEventsToReport
_SFSQLiteJournalSuffixes
_SFAnalyticsSamplerIntervalOncePerReport
_SFAnalyticsAttributeLastUploadTime
_SFAnalyticsTopicCloudServices
_SFAnalyticsTopicKeySync
+_SFAnalyticsTopicNetworking
_SFAnalyticsTopicTransparency
_SFAnalyticsTopicTrust
_SFAnalyticsErrorDomain
_OBJC_CLASS_$_LocalKeychainAnalytics
_LKAEventUpgrade
+_LKAEventStash
+_LKAEventStashLoad
#endif // __OBJC2__
_LKAReportKeychainUpgradeOutcome
_SecCreateXPCObjectWithCFError
_SecItemVerifyBackupIntegrity
+
+_SecItemDeleteKeychainItemsForAppClip
buildPhases = (
);
dependencies = (
+ 6C2045F82424BC4400F9461D /* PBXTargetDependency */,
47C2F1902059CBFC0062DE30 /* PBXTargetDependency */,
+ DCE27861245B81BD00381FE8 /* PBXTargetDependency */,
D469C4E5218BECCE008AC1FC /* PBXTargetDependency */,
0C78CCE51FCC97E7008B4B24 /* PBXTargetDependency */,
EB27FF261E40716D00EC9E3A /* PBXTargetDependency */,
EB6A6FBD1B90F9170045DC68 /* PBXTargetDependency */,
DC647C46208A85C900D0F9F8 /* PBXTargetDependency */,
D4F56BAB217FCAF600FCA6B7 /* PBXTargetDependency */,
+ 0C65BB4F23C3F3270063D2B7 /* PBXTargetDependency */,
);
name = Security_frameworks_ios;
productName = kernel;
buildPhases = (
);
dependencies = (
+ 5AAE383623D261CF0025CF9E /* PBXTargetDependency */,
EB74CC232207E99700F1BBAD /* PBXTargetDependency */,
47C2F18C2059CBEA0062DE30 /* PBXTargetDependency */,
4771D982209A76B100BA9772 /* PBXTargetDependency */,
buildPhases = (
);
dependencies = (
+ 0CCC22D223F39A7500E1FCD0 /* PBXTargetDependency */,
+ 6CF33CA62387156600D1E75D /* PBXTargetDependency */,
EB694E87223AB79400F02C1C /* PBXTargetDependency */,
- D4E0E9762224DE9100A802E0 /* PBXTargetDependency */,
D4E0E9702224DE8200A802E0 /* PBXTargetDependency */,
D4E0E9722224DE8200A802E0 /* PBXTargetDependency */,
D4E0E9742224DE8200A802E0 /* PBXTargetDependency */,
buildPhases = (
);
dependencies = (
+ 0CCC22D423F39A7C00E1FCD0 /* PBXTargetDependency */,
+ 6CF33CA82387157200D1E75D /* PBXTargetDependency */,
EB694E72223AB78E00F02C1C /* PBXTargetDependency */,
- D4E0E9AC2224DFEB00A802E0 /* PBXTargetDependency */,
D4E0E9A62224DFDD00A802E0 /* PBXTargetDependency */,
D4E0E9A82224DFDD00A802E0 /* PBXTargetDependency */,
D4E0E9AA2224DFDD00A802E0 /* PBXTargetDependency */,
D4F56B9D217FCA7E00FCA6B7 /* PBXTargetDependency */,
D4F56B9F217FCA8600FCA6B7 /* PBXTargetDependency */,
D4F56BB72181380600FCA6B7 /* PBXTargetDependency */,
+ 0C2B36C523C42EC800000718 /* PBXTargetDependency */,
);
name = Security_frameworks_tvos;
productName = Security_frameworks_tvos;
D4F56BA7217FCAB000FCA6B7 /* PBXTargetDependency */,
D4F56BA5217FCAAA00FCA6B7 /* PBXTargetDependency */,
D4F56BBB2181387600FCA6B7 /* PBXTargetDependency */,
+ 0C2B36C323C42EBC00000718 /* PBXTargetDependency */,
);
name = Security_frameworks_watchos;
productName = Security_frameworks_watchos;
buildPhases = (
);
dependencies = (
+ 0CCC22D023F39A6A00E1FCD0 /* PBXTargetDependency */,
+ 6CC638FE2266AE0A00E5DB0B /* PBXTargetDependency */,
+ 6CC639002266AE0A00E5DB0B /* PBXTargetDependency */,
EB694E8B223AB7A200F02C1C /* PBXTargetDependency */,
EB694DD0223A087700F02C1C /* PBXTargetDependency */,
EB694DC82239E5F200F02C1C /* PBXTargetDependency */,
D4A763E32224BDF90063B2B9 /* PBXTargetDependency */,
D4A763E12224BDED0063B2B9 /* PBXTargetDependency */,
D4A763DF2224BDDC0063B2B9 /* PBXTargetDependency */,
- D4A763DD2224BDCC0063B2B9 /* PBXTargetDependency */,
- D4A763DB2224BDAB0063B2B9 /* PBXTargetDependency */,
D4A763D92224BD990063B2B9 /* PBXTargetDependency */,
D4A763D52224BD6F0063B2B9 /* PBXTargetDependency */,
D4A763D32224BD640063B2B9 /* PBXTargetDependency */,
D477EE7B21ED48C000C9AAFF /* PBXTargetDependency */,
D477EE7D21ED48CB00C9AAFF /* PBXTargetDependency */,
D477EE7F21ED48D500C9AAFF /* PBXTargetDependency */,
- D477EE8321ED48E800C9AAFF /* PBXTargetDependency */,
D477EE8121ED48DF00C9AAFF /* PBXTargetDependency */,
EBB8521022F793A200424FD0 /* PBXTargetDependency */,
+ 6C61D3E8242A29BA008AB9BB /* PBXTargetDependency */,
+ 3E88361D24F08F5400E9F4D6 /* PBXTargetDependency */,
);
name = Security_tests_osx;
productName = Security_test_macos;
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 */,
EB58A0621E74C8E4009C10D7 /* PBXTargetDependency */,
EB10557D1E14DFB60003C309 /* PBXTargetDependency */,
BE9C38D31EB11605007E2AE1 /* PBXTargetDependency */,
- 47D991D020407F7E0078CAE2 /* PBXTargetDependency */,
EBB8521222F793AC00424FD0 /* PBXTargetDependency */,
);
name = Security_tests_ios;
DC647C44208A85BE00D0F9F8 /* PBXTargetDependency */,
DC58C4431D77C1F8003C25A4 /* PBXTargetDependency */,
D4F56BB32181306900FCA6B7 /* PBXTargetDependency */,
+ 0C65BB4D23C3F31B0063D2B7 /* PBXTargetDependency */,
);
name = Security_frameworks_osx;
productName = Security_frameworks_macos;
buildPhases = (
);
dependencies = (
+ 6C7BE2EA23C3DD9C003BB2CA /* PBXTargetDependency */,
47455B24205B3E2F008FE980 /* PBXTargetDependency */,
D41257F71E941E9600781F23 /* PBXTargetDependency */,
);
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, ); }; };
0C0BDB32175685B000BC1A7E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C0BDB31175685B000BC1A7E /* main.m */; };
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 */; };
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 */; };
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 */; };
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 */; };
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, ); }; };
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 */; };
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 */; };
0CE887D32299A9090082D120 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0BCC361D8C684F00070CB0 /* libutilities.a */; };
0CE887D52299A9C70082D120 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E71F3E3016EA69A900FAF9B4 /* SystemConfiguration.framework */; };
0CE902352395D0A3005E3F8C /* AuthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A7DD7320A26CF900F51F3F /* AuthKit.framework */; };
- 0CF406522072E422003D6A7F /* SFSignInAnalyticsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CF405F42072E2BF003D6A7F /* SFSignInAnalyticsTests.m */; };
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 */; };
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 */; };
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 */; };
+ 3E88360D24F068EF00E9F4D6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; };
+ 3E88361424F0699F00E9F4D6 /* secseccodeapitest.c in Sources */ = {isa = PBXBuildFile; fileRef = 3E88361324F0699F00E9F4D6 /* secseccodeapitest.c */; };
+ 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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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, ); }; };
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 */; };
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 */; };
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 */; };
48FE669620E6E69D00FAEF17 /* SOSAuthKitHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 48FE668F20E6E69B00FAEF17 /* SOSAuthKitHelpers.m */; };
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 */; };
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 */; };
+ 6C2D463D24C88AA10015C3C9 /* LegacyAPICounts.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C2D463B24C88A870015C3C9 /* LegacyAPICounts.m */; };
+ 6C2D463E24C88AA60015C3C9 /* LegacyAPICounts.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C2D463924C88A700015C3C9 /* LegacyAPICounts.h */; };
6C32BB9920EAE6B00042DF59 /* LocalKeychainAnalytics.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C814A4B2050B4B600CB391B /* LocalKeychainAnalytics.m */; };
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, ); }; };
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 */; };
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 */; };
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 */; };
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, ); }; };
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 */; };
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 */; };
A690B033208A75D1002FB775 /* notarization.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A6B1BA78207BD9D400F1E099 /* notarization.cpp */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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, ); }; };
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, ); }; };
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 */; };
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 */; };
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 */; };
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 */; };
- D49A370323873A580065719F /* RevocationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D49A370023873A570065719F /* RevocationTests.m */; };
- D49A370423873A580065719F /* RevocationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D49A370023873A570065719F /* RevocationTests.m */; };
- D49A370623873BD30065719F /* TrustDaemonTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = D49A370523873BD30065719F /* TrustDaemonTestCase.m */; };
- D49A370723873BD30065719F /* TrustDaemonTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = D49A370523873BD30065719F /* TrustDaemonTestCase.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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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, ); }; };
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, ); }; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
- 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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
+ 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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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, ); }; };
+ 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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
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 */; };
+ 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 */
);
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;
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 */;
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;
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 */;
remoteGlobalIDString = DCC78EA81D8088E200865A7C;
remoteInfo = security;
};
- 0C9AEEB920783FE000BF6237 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 4C35DB69094F906D002917C4 /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = DC1789031D77980500B50D50;
- remoteInfo = Security_osx;
- };
0CA378E823876E0900090B7E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4C35DB69094F906D002917C4 /* Project object */;
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 */;
remoteGlobalIDString = DC0BCC211D8C684F00070CB0;
remoteInfo = utilities;
};
+ 3E88361C24F08F5400E9F4D6 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 4C35DB69094F906D002917C4 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 3E88360824F068EF00E9F4D6;
+ remoteInfo = secseccodeapitest;
+ };
438169E61B4EE4B300C54D58 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4C35DB69094F906D002917C4 /* Project object */;
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 */;
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 */;
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 */;
remoteGlobalIDString = 5346480017331E1100FE9172;
remoteInfo = KeychainSyncAccountNotification;
};
- 6C4AA1A92228B640006FA945 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 4C35DB69094F906D002917C4 /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = EB9C1DAE1BDFD4DE00F89272;
- remoteInfo = SecurityBatsTests;
- };
- 6C8FF4B5224C1A9800E5C812 /* PBXContainerItemProxy */ = {
+ 5AAE383523D261CF0025CF9E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4C35DB69094F906D002917C4 /* Project object */;
proxyType = 1;
- remoteGlobalIDString = BEF88C271EAFFC3F00357577;
- remoteInfo = TrustedPeers;
+ remoteGlobalIDString = 5A442F81233C330F00918373;
+ remoteInfo = experimentTool;
};
- 6C9808301E788AEB00E70590 /* PBXContainerItemProxy */ = {
+ 6C14CA0323C4F6830097B572 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4C35DB69094F906D002917C4 /* Project object */;
proxyType = 1;
- remoteGlobalIDString = DC8834011D8A218F00CE0ACA;
- remoteInfo = ASN1_not_installed;
+ remoteGlobalIDString = 4718AE2E205B39C40068EC3F;
+ remoteInfo = libsecurityd_bridge;
};
- 6C9808321E788AEB00E70590 /* PBXContainerItemProxy */ = {
+ 6C16258023C4FFC40086A0FF /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4C35DB69094F906D002917C4 /* Project object */;
proxyType = 1;
- remoteGlobalIDString = DC0BCC211D8C684F00070CB0;
- remoteInfo = utilities;
+ remoteGlobalIDString = D4ADA3181E2B41670031CEA3;
+ remoteInfo = libtrustd;
};
- 6C9808361E788AEB00E70590 /* PBXContainerItemProxy */ = {
+ 6C16258323C4FFD40086A0FF /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4C35DB69094F906D002917C4 /* Project object */;
proxyType = 1;
remoteGlobalIDString = DCD8A1061E09EE0F00E4FA0A;
remoteInfo = SecureObjectSyncFramework;
};
- 6C9808381E788AEB00E70590 /* PBXContainerItemProxy */ = {
+ 6C16258523C4FFD40086A0FF /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4C35DB69094F906D002917C4 /* Project object */;
proxyType = 1;
remoteGlobalIDString = DC52E8BE1D80C25800B0A59C;
remoteInfo = SecureObjectSyncServer;
};
- 6C98083A1E788AEB00E70590 /* PBXContainerItemProxy */ = {
+ 6C2045F72424BC4400F9461D /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4C35DB69094F906D002917C4 /* Project object */;
proxyType = 1;
- remoteGlobalIDString = DCC78EA81D8088E200865A7C;
- remoteInfo = security;
+ remoteGlobalIDString = 6C2045E92424BA7E00F9461D;
+ remoteInfo = KeychainStasher;
};
- 6C98086C1E788AFD00E70590 /* PBXContainerItemProxy */ = {
+ 6C2D797222C06CEB00C3CE32 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4C35DB69094F906D002917C4 /* Project object */;
proxyType = 1;
- remoteGlobalIDString = DC8834011D8A218F00CE0ACA;
- remoteInfo = ASN1_not_installed;
+ remoteGlobalIDString = 6C39234421F13E4D00D018AD;
+ remoteInfo = SecDbBackupTests;
};
- 6C98086E1E788AFD00E70590 /* PBXContainerItemProxy */ = {
+ 6C2D797422C06CEF00C3CE32 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4C35DB69094F906D002917C4 /* Project object */;
proxyType = 1;
- remoteGlobalIDString = DC0BCC211D8C684F00070CB0;
- remoteInfo = utilities;
+ remoteGlobalIDString = 4727FBB61F9918580003AE36;
+ remoteInfo = secdxctests;
};
- 6C9808721E788AFD00E70590 /* PBXContainerItemProxy */ = {
+ 6C4AA1A92228B640006FA945 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4C35DB69094F906D002917C4 /* Project object */;
proxyType = 1;
- remoteGlobalIDString = DCD8A1061E09EE0F00E4FA0A;
- remoteInfo = SecureObjectSyncFramework;
+ remoteGlobalIDString = EB9C1DAE1BDFD4DE00F89272;
+ remoteInfo = SecurityBatsTests;
};
- 6C9808741E788AFD00E70590 /* PBXContainerItemProxy */ = {
+ 6C61D3E7242A29BA008AB9BB /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4C35DB69094F906D002917C4 /* Project object */;
proxyType = 1;
- remoteGlobalIDString = DC52E8BE1D80C25800B0A59C;
- remoteInfo = SecureObjectSyncServer;
+ remoteGlobalIDString = 6C963280242A279B00C53CE2;
+ remoteInfo = stashtester;
};
- 6C9808761E788AFD00E70590 /* PBXContainerItemProxy */ = {
+ 6C7BE2AB23C3DD64003BB2CA /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4C35DB69094F906D002917C4 /* Project object */;
proxyType = 1;
- remoteGlobalIDString = DCC78EA81D8088E200865A7C;
- remoteInfo = security;
+ remoteGlobalIDString = DCDA5E4F2124B9C5009B11B2;
+ remoteInfo = aks_support;
};
- 6C98089F1E788B9400E70590 /* PBXContainerItemProxy */ = {
+ 6C7BE2AD23C3DD64003BB2CA /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4C35DB69094F906D002917C4 /* Project object */;
proxyType = 1;
- remoteGlobalIDString = 6CF4A0B31E45488B00ECD7B5;
- remoteInfo = KeychainEntitledTestApp_mac;
+ remoteGlobalIDString = DC0BCC211D8C684F00070CB0;
+ remoteInfo = utilities;
};
- 6C9808A31E788CB100E70590 /* PBXContainerItemProxy */ = {
+ 6C7BE2E923C3DD9C003BB2CA /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4C35DB69094F906D002917C4 /* Project object */;
proxyType = 1;
- remoteGlobalIDString = 6CF4A0DF1E4549F200ECD7B5;
- remoteInfo = KeychainEntitledTestApp_ios;
+ remoteGlobalIDString = 6C7BE2A923C3DD64003BB2CA;
+ remoteInfo = securitytool_bridge;
};
6C9A49B11FAB647D00239D58 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
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 */;
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 */;
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 */;
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 */;
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 */;
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 */;
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 */;
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 */;
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 */;
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 */;
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 */;
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 */;
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 */;
name = "Copy System logging profile";
runOnlyForDeploymentPostprocessing = 1;
};
- 0C9AEEB320783FBB00BF6237 /* Embed OCMock */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 2147483647;
- dstPath = "";
- dstSubfolderSpec = 10;
- files = (
- );
- name = "Embed OCMock";
- runOnlyForDeploymentPostprocessing = 0;
- };
0CA378E623876DEC00090B7E /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
);
runOnlyForDeploymentPostprocessing = 1;
};
- 0CF4064A2072E3E3003D6A7F /* Embed OCMock */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 2147483647;
- dstPath = "";
- dstSubfolderSpec = 10;
- files = (
- );
- name = "Embed OCMock";
- runOnlyForDeploymentPostprocessing = 0;
- };
3D58394821890FFB000ACA44 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
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";
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;
);
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;
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";
09E9991F1F7D76550018DF67 /* SecKeyProxy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecKeyProxy.m; sourceTree = "<group>"; };
0C00FC81217A971800C8BF00 /* OTLocalCuttlefishReset.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTLocalCuttlefishReset.m; sourceTree = "<group>"; };
0C00FC85217A972E00C8BF00 /* OTLocalCuttlefishReset.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTLocalCuttlefishReset.h; sourceTree = "<group>"; };
+ 0C0203E023A8564E005D0A68 /* OTEscrowRecord.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; name = OTEscrowRecord.proto; path = proto/OTEscrowRecord.proto; sourceTree = "<group>"; };
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 = "<group>"; };
0C0BDB441756868B00BC1A7E /* testlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testlist.h; sourceTree = "<group>"; };
0C0C4F83216FB55600C14C61 /* EscrowKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EscrowKeys.swift; sourceTree = "<group>"; };
0C0C4F84216FB56B00C14C61 /* BottledPeer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottledPeer.swift; sourceTree = "<group>"; };
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 = "<group>"; };
+ 0C0CB73723AD71400020C6BF /* Container_EscrowRecords.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container_EscrowRecords.swift; sourceTree = "<group>"; };
0C0CEC9D1DA45EA200C22FBC /* recovery_key.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = recovery_key.h; sourceTree = "<group>"; };
0C0CEC9E1DA45EA200C22FBC /* recovery_key.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = recovery_key.m; sourceTree = "<group>"; };
+ 0C0D920523BFEA740070A68C /* OTCDPRecoveryInformation.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; name = OTCDPRecoveryInformation.proto; path = proto/OTCDPRecoveryInformation.proto; sourceTree = "<group>"; };
0C0F76DD21399AF40074EDDF /* OTPairingMessage.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = OTPairingMessage.proto; sourceTree = "<group>"; };
- 0C108C4B208A677100E8CF70 /* SFSignInAnalytics+Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SFSignInAnalytics+Internal.h"; sourceTree = "<group>"; };
0C12B1F02138D31600BE0A98 /* OTClientStateMachine.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTClientStateMachine.m; sourceTree = "<group>"; };
0C12B1F52138D32F00BE0A98 /* OTClientStateMachine.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTClientStateMachine.h; sourceTree = "<group>"; };
0C1B8BB3223323710094D5DA /* OTVouchWithRecoveryKeyOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTVouchWithRecoveryKeyOperation.h; sourceTree = "<group>"; };
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 = "<group>"; };
+ 0C3C47C024902D450084B951 /* OTSupportOctagonMessage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTSupportOctagonMessage.m; sourceTree = "<group>"; };
+ 0C3C47C224902D460084B951 /* OTSupportSOSMessage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSupportSOSMessage.h; sourceTree = "<group>"; };
+ 0C3C47C324902D460084B951 /* OTSupportSOSMessage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTSupportSOSMessage.m; sourceTree = "<group>"; };
+ 0C3C47C424902D470084B951 /* OTSupportOctagonMessage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSupportOctagonMessage.h; sourceTree = "<group>"; };
+ 0C3C47C524902D470084B951 /* OTGlobalEnums.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTGlobalEnums.h; sourceTree = "<group>"; };
+ 0C3DF8C524789C04009CF03A /* Container_Peers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container_Peers.swift; sourceTree = "<group>"; };
+ 0C468FD823C7D41C006F4582 /* OTEscrowRecordMetadata.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OTEscrowRecordMetadata.m; path = proto/generated_source/OTEscrowRecordMetadata.m; sourceTree = "<group>"; };
+ 0C468FD923C7D41D006F4582 /* OTEscrowRecordMetadataClientMetadata.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OTEscrowRecordMetadataClientMetadata.m; path = proto/generated_source/OTEscrowRecordMetadataClientMetadata.m; sourceTree = "<group>"; };
+ 0C468FDA23C7D41D006F4582 /* OTEscrowRecordMetadata.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OTEscrowRecordMetadata.h; path = proto/generated_source/OTEscrowRecordMetadata.h; sourceTree = "<group>"; };
+ 0C468FDB23C7D41D006F4582 /* OTEscrowRecordMetadataClientMetadata.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OTEscrowRecordMetadataClientMetadata.h; path = proto/generated_source/OTEscrowRecordMetadataClientMetadata.h; sourceTree = "<group>"; };
+ 0C468FDD23C7D471006F4582 /* OTEscrowRecord.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OTEscrowRecord.m; path = proto/generated_source/OTEscrowRecord.m; sourceTree = "<group>"; };
+ 0C468FDE23C7D471006F4582 /* OTEscrowRecord.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OTEscrowRecord.h; path = proto/generated_source/OTEscrowRecord.h; sourceTree = "<group>"; };
+ 0C468FE723C7D4C7006F4582 /* OTICDPRecordContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OTICDPRecordContext.h; path = proto/generated_source/OTICDPRecordContext.h; sourceTree = "<group>"; };
+ 0C468FE823C7D4C8006F4582 /* OTEscrowAuthenticationInformation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OTEscrowAuthenticationInformation.h; path = proto/generated_source/OTEscrowAuthenticationInformation.h; sourceTree = "<group>"; };
+ 0C468FE923C7D4C8006F4582 /* OTICDPRecordSilentContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OTICDPRecordSilentContext.h; path = proto/generated_source/OTICDPRecordSilentContext.h; sourceTree = "<group>"; };
+ 0C468FEA23C7D4C8006F4582 /* OTCDPRecoveryInformation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OTCDPRecoveryInformation.h; path = proto/generated_source/OTCDPRecoveryInformation.h; sourceTree = "<group>"; };
+ 0C468FEB23C7D4C9006F4582 /* OTICDPRecordSilentContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OTICDPRecordSilentContext.m; path = proto/generated_source/OTICDPRecordSilentContext.m; sourceTree = "<group>"; };
+ 0C468FEC23C7D4C9006F4582 /* OTEscrowAuthenticationInformation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OTEscrowAuthenticationInformation.m; path = proto/generated_source/OTEscrowAuthenticationInformation.m; sourceTree = "<group>"; };
+ 0C468FED23C7D4C9006F4582 /* OTICDPRecordContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OTICDPRecordContext.m; path = proto/generated_source/OTICDPRecordContext.m; sourceTree = "<group>"; };
+ 0C468FEE23C7D4CA006F4582 /* OTCDPRecoveryInformation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OTCDPRecoveryInformation.m; path = proto/generated_source/OTCDPRecoveryInformation.m; sourceTree = "<group>"; };
0C48990A1E0E0FF300C6CF70 /* SOSTransportCircleCK.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSTransportCircleCK.h; sourceTree = "<group>"; };
0C4899111E0E105D00C6CF70 /* SOSTransportCircleCK.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SOSTransportCircleCK.m; sourceTree = "<group>"; };
0C48991B1E0F384700C6CF70 /* SOSAccountTrustClassic.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SOSAccountTrustClassic.m; path = SecureObjectSync/SOSAccountTrustClassic.m; sourceTree = "<group>"; };
0C5258B821BB05C100B32C96 /* FakeSOSControl.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FakeSOSControl.m; path = Tests/FakeSOSControl.m; sourceTree = "<group>"; };
0C5258BC21BB137800B32C96 /* FakeSOSControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FakeSOSControl.h; path = Tests/FakeSOSControl.h; sourceTree = "<group>"; };
0C5824A322860001009E8C15 /* OctagonTests+HealthCheck.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+HealthCheck.swift"; sourceTree = "<group>"; };
+ 0C64C07C2485A53000D84A5D /* OTPreloadOctagonKeysOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTPreloadOctagonKeysOperation.m; sourceTree = "<group>"; };
+ 0C64C07F2485A54100D84A5D /* OTPreloadOctagonKeysOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTPreloadOctagonKeysOperation.h; sourceTree = "<group>"; };
0C6604692134983900BFBBB8 /* OTEstablishOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTEstablishOperation.m; sourceTree = "<group>"; };
0C66046E2134985100BFBBB8 /* OTEstablishOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTEstablishOperation.h; sourceTree = "<group>"; };
0C6604782134C86500BFBBB8 /* OTDeviceInformation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTDeviceInformation.h; sourceTree = "<group>"; };
0C8FD546214AEC650098E3FB /* OTJoiningConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTJoiningConfiguration.h; sourceTree = "<group>"; };
0C8FD549214AECD70098E3FB /* OTJoiningConfiguration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTJoiningConfiguration.m; sourceTree = "<group>"; };
0C97867C235A76E70040A867 /* com.apple.security.signposts.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.security.signposts.plist; sourceTree = "<group>"; };
+ 0C9A54B4250C27F100FF007B /* OctagonTrustTests+Errors.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "OctagonTrustTests+Errors.m"; sourceTree = "<group>"; };
+ 0C9A54B7250C290800FF007B /* OctagonTrustTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OctagonTrustTests.h; sourceTree = "<group>"; };
0C9AE289214054F4003BFDB5 /* OTSponsorToApplicantRound1M2.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSponsorToApplicantRound1M2.h; sourceTree = "<group>"; };
0C9AE28A214054F5003BFDB5 /* OTSponsorToApplicantRound2M2.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSponsorToApplicantRound2M2.h; sourceTree = "<group>"; };
0C9AE28B214054F5003BFDB5 /* OTApplicantToSponsorRound2M1.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTApplicantToSponsorRound2M1.h; sourceTree = "<group>"; };
0C9AE290214054F7003BFDB5 /* OTSponsorToApplicantRound2M2.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTSponsorToApplicantRound2M2.m; sourceTree = "<group>"; };
0C9AE2A1214055CE003BFDB5 /* OTPairingMessage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTPairingMessage.h; sourceTree = "<group>"; };
0C9AE2A2214055CF003BFDB5 /* OTPairingMessage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTPairingMessage.m; sourceTree = "<group>"; };
- 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 = "<group>"; };
+ 0C9F65AC23E3ACF700B1A2C5 /* OTEscrowTranslation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTEscrowTranslation.h; sourceTree = "<group>"; };
+ 0CA1D0B223E9023100021038 /* OctagonTests+EscrowTestVectors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+EscrowTestVectors.swift"; sourceTree = "<group>"; };
0CA4EBF1202B8D1C002B1D96 /* CloudKitKeychainSyncingTestsBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CloudKitKeychainSyncingTestsBase.h; sourceTree = "<group>"; };
0CA4EBF2202B8D1D002B1D96 /* CloudKitKeychainSyncingTestsBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CloudKitKeychainSyncingTestsBase.m; sourceTree = "<group>"; };
0CA702082280D5600085AC54 /* OTCheckHealthOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTCheckHealthOperation.m; sourceTree = "<group>"; };
0CBA047C214C4E4D005B3A2F /* OctagonPairingTests+ProxMultiClients.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonPairingTests+ProxMultiClients.swift"; sourceTree = "<group>"; };
0CBEF3412242C9AE00015691 /* TestsObjcTranslation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestsObjcTranslation.m; sourceTree = "<group>"; };
0CBEF3422242C9BE00015691 /* TestsObjcTranslation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestsObjcTranslation.h; sourceTree = "<group>"; };
+ 0CBF883A23AAD9DC00652EDD /* OctagonTests+EscrowRecords.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+EscrowRecords.swift"; sourceTree = "<group>"; };
0CC8A8FA2123A9EB005D7F6A /* OTClientVoucherOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTClientVoucherOperation.m; sourceTree = "<group>"; };
0CC8A9002123AA3B005D7F6A /* OTClientVoucherOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTClientVoucherOperation.h; sourceTree = "<group>"; };
0CC8A9012123AEF7005D7F6A /* OTJoinWithVoucherOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTJoinWithVoucherOperation.m; sourceTree = "<group>"; };
0CC8A9052123AF16005D7F6A /* OTJoinWithVoucherOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTJoinWithVoucherOperation.h; sourceTree = "<group>"; };
+ 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 = "<group>"; };
+ 0CCC229F23F367D100E1FCD0 /* OctagonTrustTests-EscrowRecords.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "OctagonTrustTests-EscrowRecords.m"; sourceTree = "<group>"; };
+ 0CCC22A323F36DD300E1FCD0 /* OctagonTrustTests-EscrowTestVectors.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "OctagonTrustTests-EscrowTestVectors.h"; sourceTree = "<group>"; };
+ 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 = "<group>"; };
+ 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 = "<group>"; };
0CCCC7C820261D310024405E /* OT.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OT.m; sourceTree = "<group>"; };
0CCDE7161EEB08220021A946 /* secd-156-timers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "secd-156-timers.m"; sourceTree = "<group>"; };
0CD3D5152240479600024755 /* OTSetRecoveryKeyOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTSetRecoveryKeyOperation.m; sourceTree = "<group>"; };
0CD3D518224047B400024755 /* OTSetRecoveryKeyOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSetRecoveryKeyOperation.h; sourceTree = "<group>"; };
0CD5797721498F7700C43496 /* OctagonPairingTests+Piggybacking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonPairingTests+Piggybacking.swift"; sourceTree = "<group>"; };
+ 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 = "<group>"; };
+ 0CD743A923C3EC8000FA0EC5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+ 0CD743B723C3ED7E00FA0EC5 /* OctagonTrust.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OctagonTrust.m; sourceTree = "<group>"; };
+ 0CD743BA23C3EF0D00FA0EC5 /* OTClique+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "OTClique+Private.h"; sourceTree = "<group>"; };
0CD8CB041ECA50780076F37F /* SOSPeerOTRTimer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SOSPeerOTRTimer.m; sourceTree = "<group>"; };
0CD8CB0C1ECA50D10076F37F /* SOSPeerOTRTimer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSPeerOTRTimer.h; sourceTree = "<group>"; };
0CD8D654207D6E65005CDBE8 /* SFAnalytics+Signin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SFAnalytics+Signin.h"; sourceTree = "<group>"; };
0CE760531E13155100B4381E /* SOSAccountTrustClassic+Circle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "SOSAccountTrustClassic+Circle.h"; path = "SecureObjectSync/SOSAccountTrustClassic+Circle.h"; sourceTree = "<group>"; };
0CE760551E1316E900B4381E /* SOSAccountTrustClassic+Retirement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "SOSAccountTrustClassic+Retirement.h"; path = "SecureObjectSync/SOSAccountTrustClassic+Retirement.h"; sourceTree = "<group>"; };
0CE98B5B1FA9360700CF1D54 /* libprequelite.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libprequelite.tbd; path = usr/lib/libprequelite.tbd; sourceTree = SDKROOT; };
- 0CF0E2E31F8EE3B000BD18E4 /* SFSignInAnalytics.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFSignInAnalytics.m; sourceTree = "<group>"; };
- 0CF0E2E71F8EE40700BD18E4 /* SFSignInAnalytics.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SFSignInAnalytics.h; sourceTree = "<group>"; };
- 0CF405F42072E2BF003D6A7F /* SFSignInAnalyticsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFSignInAnalyticsTests.m; sourceTree = "<group>"; };
0CF405FC2072E352003D6A7F /* SFTMTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SFTMTests-Info.plist"; sourceTree = "<group>"; };
- 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 = "<group>"; };
+ 0CF7613D23F24B5D00A3C3AD /* KeychainCircle.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; name = KeychainCircle.modulemap; path = Modules/KeychainCircle.modulemap; sourceTree = "<group>"; };
+ 0CF7613F23F24B5E00A3C3AD /* OctagonTrust.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; name = OctagonTrust.modulemap; path = Modules/OctagonTrust.modulemap; sourceTree = "<group>"; };
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 = "<group>"; };
107226D10D91DB32003CF14F /* SecTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTask.h; path = sectask/SecTask.h; sourceTree = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
+ 3DC5BD59241845100039ABF4 /* SecureTransportTests_ios.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = SecureTransportTests_ios.xctestplan; path = OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransportTests_ios.xctestplan; sourceTree = "<group>"; };
3DD1FE78201AA50C0086D049 /* STLegacyTests+clientauth41.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "STLegacyTests+clientauth41.m"; sourceTree = "<group>"; };
3DD1FE79201AA50D0086D049 /* SecureTransport_macosTests.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = SecureTransport_macosTests.plist; sourceTree = "<group>"; };
3DD1FE7A201AA50D0086D049 /* STLegacyTests-Entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "STLegacyTests-Entitlements.plist"; sourceTree = "<group>"; };
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 = "<group>"; };
+ 3E88361124F068EF00E9F4D6 /* secseccodeapitest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secseccodeapitest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 3E88361324F0699F00E9F4D6 /* secseccodeapitest.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = secseccodeapitest.c; sourceTree = "<group>"; };
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 = "<group>"; };
4723C9D11F1531970082882F /* CKKSLoggerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSLoggerTests.m; sourceTree = "<group>"; };
4723C9DA1F1540CE0082882F /* SFAnalytics.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SFAnalytics.h; sourceTree = "<group>"; };
4723C9DB1F1540CE0082882F /* SFAnalytics.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFAnalytics.m; sourceTree = "<group>"; };
- 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 = "<group>"; };
4727FBBB1F9918590003AE36 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
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; };
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 = "<group>"; };
473337781FDAFBCC00E19F30 /* SFKeychainControlManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFKeychainControlManager.m; sourceTree = "<group>"; };
473337821FDB29A200E19F30 /* KeychainCheck.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeychainCheck.h; sourceTree = "<group>"; };
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; };
477A1FE1203763A500ACD81D /* KeychainAPITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeychainAPITests.m; sourceTree = "<group>"; };
477A1FEB2037A0E000ACD81D /* KeychainXCTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeychainXCTest.h; sourceTree = "<group>"; };
477A1FEC2037A0E000ACD81D /* KeychainXCTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeychainXCTest.m; sourceTree = "<group>"; };
- 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 = "<group>"; };
479108B61EE879F9008CEFA0 /* CKKSAnalytics.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSAnalytics.m; sourceTree = "<group>"; };
47922D171FAA65120008F7E0 /* SecDbKeychainSerializedAKSWrappedKey.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = SecDbKeychainSerializedAKSWrappedKey.proto; sourceTree = "<group>"; };
48776C7C1DA5BB5F00CC09B9 /* SOSRingRecovery.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SOSRingRecovery.m; sourceTree = "<group>"; };
48776C7D1DA5BB5F00CC09B9 /* SOSRingRecovery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSRingRecovery.h; sourceTree = "<group>"; };
48776C801DA5BC0E00CC09B9 /* SOSAccountRecovery.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SOSAccountRecovery.m; sourceTree = "<group>"; };
+ 487A65F3245B65F1005F51D6 /* secd-68-fullPeerInfoIntegrity.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "secd-68-fullPeerInfoIntegrity.m"; sourceTree = "<group>"; };
48AC7B5C232B1A1700F02B6F /* SOSIntervalEvent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSIntervalEvent.h; sourceTree = "<group>"; };
48AC7B71232B1A7000F02B6F /* SOSIntervalEvent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SOSIntervalEvent.m; sourceTree = "<group>"; };
48C2F9321E4BCFC30093D70C /* accountCirclesViewsPrint.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = accountCirclesViewsPrint.m; sourceTree = "<group>"; };
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 = "<group>"; };
5F00F95A230614A200B832E0 /* SecImportExportPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecImportExportPriv.h; path = keychain/headers/SecImportExportPriv.h; sourceTree = "<group>"; };
+ 5F4C21FE2489C68900F0C425 /* simulatecrash_assert.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = simulatecrash_assert.h; sourceTree = "<group>"; };
5F8494FF22DFB502008B3EFB /* SecTrustExceptionResetCount.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecTrustExceptionResetCount.m; sourceTree = "<group>"; };
617570BA22C2D19E00EFBA37 /* Security.macOS.private.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; name = Security.macOS.private.modulemap; path = Modules/Security.macOS.private.modulemap; sourceTree = "<group>"; };
- 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 = "<group>"; };
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; };
6C1260FA1F7D631D001B2EEC /* securityuploadd-ios.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "securityuploadd-ios.plist"; sourceTree = "<group>"; };
6C1520CD1DCCF57A00C85C6D /* secd.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = secd.8; sourceTree = "<group>"; };
6C1A29FC1F882788002312D8 /* SFAnalyticsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFAnalyticsTests.m; sourceTree = "<group>"; };
- 6C2008EF220BB4B500674B3A /* Entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Entitlements.plist; sourceTree = "<group>"; };
+ 6C2008EF220BB4B500674B3A /* SecDbBackupTests-Entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "SecDbBackupTests-Entitlements.plist"; sourceTree = "<group>"; };
+ 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 = "<group>"; };
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 = "<group>"; };
+ 6C2D463B24C88A870015C3C9 /* LegacyAPICounts.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LegacyAPICounts.m; sourceTree = "<group>"; };
6C34462F1E24F6BE00F9522B /* CKKSRateLimiterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSRateLimiterTests.m; sourceTree = "<group>"; };
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 = "<group>"; };
+ 6C48D10F2423A3C0004AF950 /* com.apple.security.KeychainStasher.sb */ = {isa = PBXFileReference; lastKnownFileType = text; path = com.apple.security.KeychainStasher.sb; sourceTree = "<group>"; };
6C4AEF82218A09210012C5DA /* CheckV12DevEnabled.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CheckV12DevEnabled.h; sourceTree = "<group>"; };
6C4AEF83218A09210012C5DA /* CheckV12DevEnabled.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CheckV12DevEnabled.m; sourceTree = "<group>"; };
6C4AEF8A218A0A400012C5DA /* SecDbBackupManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecDbBackupManager.h; sourceTree = "<group>"; };
6C4AEF93218A124B0012C5DA /* SecDbKeychainMetadataKeyStore.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecDbKeychainMetadataKeyStore.m; sourceTree = "<group>"; };
6C4AEF9C218A16F80012C5DA /* SecAKSObjCWrappers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecAKSObjCWrappers.h; sourceTree = "<group>"; };
6C4AEF9D218A16F80012C5DA /* SecAKSObjCWrappers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecAKSObjCWrappers.m; sourceTree = "<group>"; };
+ 6C513A37244F007B00207D5E /* SecItemRateLimit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecItemRateLimit.h; sourceTree = "<group>"; };
+ 6C513A38244F007B00207D5E /* SecItemRateLimit.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecItemRateLimit.m; sourceTree = "<group>"; };
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 = "<group>"; };
6C588D791EAA149F00D7E322 /* RateLimiterTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RateLimiterTests.m; sourceTree = "<group>"; };
6C5B101B1F91613E009B091E /* supdctl-Entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "supdctl-Entitlements.plist"; sourceTree = "<group>"; };
6C5B10211F9164F5009B091E /* securityuploadd.8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = securityuploadd.8; sourceTree = "<group>"; };
+ 6C5D62A5221B6E3F00AF79DC /* secdxctests-entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "secdxctests-entitlements.plist"; sourceTree = "<group>"; };
+ 6C6579FC2394878700701C8B /* SecDbBackupTestsBase.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecDbBackupTestsBase.m; sourceTree = "<group>"; };
6C69517C1F758E1000F68F91 /* supdProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = supdProtocol.h; sourceTree = "<group>"; };
6C69517D1F758E1000F68F91 /* supd.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = supd.h; sourceTree = "<group>"; };
6C69517E1F758E1000F68F91 /* supd.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = supd.m; sourceTree = "<group>"; };
6C69518D1F75A7DB00F68F91 /* SFAnalyticsSQLiteStore.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFAnalyticsSQLiteStore.m; sourceTree = "<group>"; };
6C69518E1F75A7DC00F68F91 /* SFAnalyticsSQLiteStore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SFAnalyticsSQLiteStore.h; sourceTree = "<group>"; };
6C69518F1F75A8C100F68F91 /* SFAnalyticsDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SFAnalyticsDefines.h; sourceTree = "<group>"; };
+ 6C6AF178221A03930091CE0A /* SecDbKeychainSerializedMetadataKey.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = SecDbKeychainSerializedMetadataKey.proto; sourceTree = "<group>"; };
+ 6C6AF17D221A06F70091CE0A /* SecDbKeychainSerializedMetadataKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecDbKeychainSerializedMetadataKey.h; sourceTree = "<group>"; };
+ 6C6AF17E221A06F80091CE0A /* SecDbKeychainSerializedMetadataKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecDbKeychainSerializedMetadataKey.m; sourceTree = "<group>"; };
6C70D8D420EB02B700AB6FAF /* TPPBPolicyCategoriesByView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TPPBPolicyCategoriesByView.m; sourceTree = "<group>"; };
6C70D8D520EBDE4500AB6FAF /* TPPBPolicyRedaction.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = TPPBPolicyRedaction.proto; sourceTree = "<group>"; };
6C70D8DD20EBDFD600AB6FAF /* TPPBPolicyRedaction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TPPBPolicyRedaction.m; sourceTree = "<group>"; };
6C70D8DE20EBDFD700AB6FAF /* TPPBPolicyRedaction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPPBPolicyRedaction.h; sourceTree = "<group>"; };
+ 6C755603242121F000025D78 /* keychainstasherinterface.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = keychainstasherinterface.m; sourceTree = "<group>"; };
+ 6C755604242121F000025D78 /* keychainstasherinterface.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = keychainstasherinterface.h; sourceTree = "<group>"; };
6C758CB01F8826100075BD78 /* SupdTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SupdTests.m; sourceTree = "<group>"; };
6C758CB21F8826100075BD78 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
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 = "<group>"; };
6C814A4B2050B4B600CB391B /* LocalKeychainAnalytics.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LocalKeychainAnalytics.m; sourceTree = "<group>"; };
+ 6C84E3C723ECBC84003C9710 /* KeychainAppClipTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeychainAppClipTests.m; sourceTree = "<group>"; };
6C860C741F4F63AD004100A1 /* SOSEnsureBackup.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSEnsureBackup.h; sourceTree = "<group>"; };
6C860C7A1F4F63DB004100A1 /* SOSEnsureBackup.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SOSEnsureBackup.m; sourceTree = "<group>"; };
6C880FBE21C334FB00D38D66 /* SecDbBackupBagIdentity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecDbBackupBagIdentity.h; sourceTree = "<group>"; };
6C880FC721C334FE00D38D66 /* SecDbBackupRecoverySet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecDbBackupRecoverySet.h; sourceTree = "<group>"; };
6C8CE6BB1FA248B50032ADF0 /* SFAnalyticsActivityTracker+Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SFAnalyticsActivityTracker+Internal.h"; sourceTree = "<group>"; };
6C8CE6C31FA24A670032ADF0 /* SFAnalyticsSampler+Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SFAnalyticsSampler+Internal.h"; sourceTree = "<group>"; };
+ 6C915BE3242E14BC00DBDAFB /* SecDbInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecDbInternal.h; sourceTree = "<group>"; };
+ 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 = "<group>"; };
+ 6C963289242A27F300C53CE2 /* stashtester.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = stashtester.entitlements; sourceTree = "<group>"; };
6C9791C421C17D060074C609 /* SecDbBackupManager_Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecDbBackupManager_Internal.h; sourceTree = "<group>"; };
- 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 = "<group>"; };
+ 6C99786A242362EC008C498D /* KeychainStasher.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeychainStasher.h; sourceTree = "<group>"; };
+ 6C99786B242362EC008C498D /* KeychainStasher.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeychainStasher.m; sourceTree = "<group>"; };
+ 6C99786D242362EC008C498D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ 6C99786F242362EC008C498D /* KeychainStasher-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "KeychainStasher-Info.plist"; sourceTree = "<group>"; };
+ 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 = "<group>"; };
6CA2B9431E9F9F5700C43444 /* RateLimiter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RateLimiter.h; sourceTree = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
- 6CB5F4791E402E5700DBF3F0 /* KeychainEntitledTestRunner-Entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "KeychainEntitledTestRunner-Entitlements.plist"; sourceTree = "<group>"; };
+ 6CB5F4791E402E5700DBF3F0 /* KeychainEntitledTestRunner.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = KeychainEntitledTestRunner.entitlements; sourceTree = "<group>"; };
6CB5F47A1E402E5700DBF3F0 /* KeychainEntitledTestRunner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KeychainEntitledTestRunner.m; sourceTree = "<group>"; };
6CB6CC022198D4BC0080AD6F /* SecDbBackupRecoverySet.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = SecDbBackupRecoverySet.proto; sourceTree = "<group>"; };
6CB96BB41F966E0C00E11457 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; };
6CC952421FB4C5CA0051A823 /* SFAnalytics+Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SFAnalytics+Internal.h"; sourceTree = "<group>"; };
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 = "<group>"; };
+ 6CD224E7239493E8001B70FD /* SecDbBackupTestsBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecDbBackupTestsBase.h; sourceTree = "<group>"; };
+ 6CD8412B23F5D871003DDF34 /* KeychainBackupTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeychainBackupTests.m; sourceTree = "<group>"; };
6CDB5FED1FA78CB400410924 /* SFAnalyticsMultiSampler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SFAnalyticsMultiSampler.m; sourceTree = "<group>"; };
6CDB5FF31FA78CB500410924 /* SFAnalyticsMultiSampler+Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SFAnalyticsMultiSampler+Internal.h"; sourceTree = "<group>"; };
6CDB5FF41FA78CB500410924 /* SFAnalyticsMultiSampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SFAnalyticsMultiSampler.h; sourceTree = "<group>"; };
6CDF8DE51F95562B00140B54 /* SFAnalyticsSampler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SFAnalyticsSampler.h; sourceTree = "<group>"; };
6CDF8DE61F95562B00140B54 /* SFAnalyticsSampler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFAnalyticsSampler.m; sourceTree = "<group>"; };
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 = "<group>"; };
+ 6CF33CA2238714C900D1E75D /* bats_utd_plist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bats_utd_plist.h; sourceTree = "<group>"; };
+ 6CF33CA4238714C900D1E75D /* PreprocessPlist.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = PreprocessPlist.sh; sourceTree = "<group>"; };
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 = "<group>"; };
6CF4A0B71E45488B00ECD7B5 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
6CF4A0BC1E45488B00ECD7B5 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
6CF4A0BD1E45488B00ECD7B5 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
6CF4A0BF1E45488B00ECD7B5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
- 6CF4A0C41E45488B00ECD7B5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
- 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 = "<group>"; };
- 6CF4A0E51E4549F200ECD7B5 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
- 6CF4A0E61E4549F300ECD7B5 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
- 6CF4A0E81E4549F300ECD7B5 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
- 6CF4A0E91E4549F300ECD7B5 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
- 6CF4A0EE1E4549F300ECD7B5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
- 6CF4A0F31E4549F300ECD7B5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+ 6CF4A0C41E45488B00ECD7B5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
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 = "<group>"; };
7221843F1EC6782A004C7BED /* sec_action.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sec_action.h; sourceTree = "<group>"; };
8ED6F6C8110904E300D2B368 /* SecPBKDF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecPBKDF.h; sourceTree = "<group>"; };
A6B1BA78207BD9D400F1E099 /* notarization.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = notarization.cpp; sourceTree = "<group>"; };
A6B1BA79207BD9D400F1E099 /* notarization.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = notarization.h; sourceTree = "<group>"; };
+ A6BF3B3123EB94A7009AF079 /* entitlements.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = entitlements.h; sourceTree = "<group>"; };
+ A6BF3B3223EB94A7009AF079 /* entitlements.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = entitlements.c; sourceTree = "<group>"; };
AA0DA47821E8189D009F1C74 /* example1.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = example1.json; path = protocol/test_data/example1.json; sourceTree = "<group>"; };
AA0DA47921E8189E009F1C74 /* builtins.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = builtins.json; path = protocol/test_data/builtins.json; sourceTree = "<group>"; };
AA44E0B3202E3451001EA371 /* SecProtocolTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SecProtocolTest.m; path = protocol/SecProtocolTest.m; sourceTree = "<group>"; };
BE55C77A2044D0C80045863D /* TrustedPeersHelper-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TrustedPeersHelper-Bridging-Header.h"; sourceTree = "<group>"; };
BE55C77B2044D0C90045863D /* Client.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = "<group>"; };
BE55C77D2044D7E60045863D /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
- BE6215BD1DB6E69100961E15 /* si-84-sectrust-allowlist.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "si-84-sectrust-allowlist.m"; sourceTree = "<group>"; };
+ BE57B1162509E0FF0045B7FD /* ca_revocation_additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ca_revocation_additions.m; sourceTree = "<group>"; };
BE64A7FD22AF0109001209F3 /* trusted_cert_ssl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = trusted_cert_ssl.h; sourceTree = "<group>"; };
BE64A7FE22AF010A001209F3 /* trusted_cert_ssl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = trusted_cert_ssl.m; sourceTree = "<group>"; };
BE7089911F9AA027001ACC20 /* TPPBVoucher.proto */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.protobuf; path = TPPBVoucher.proto; sourceTree = "<group>"; };
BE7089DD1FA40B93001ACC20 /* TPPBPeerPermanentInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPPBPeerPermanentInfo.h; sourceTree = "<group>"; };
BE7089DE1FA40B95001ACC20 /* TPPBPeerPermanentInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TPPBPeerPermanentInfo.m; sourceTree = "<group>"; };
BE72782A209D27C800F0DA77 /* TPKeyTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TPKeyTests.m; sourceTree = "<group>"; };
- 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 = "<group>"; };
+ BE7B8E112415579800E1CF4F /* SecSharedCredential.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecSharedCredential.m; sourceTree = "<group>"; };
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 = "<group>"; };
- BE9B8B43202BB42C0081EF87 /* si-88-sectrust-valid-data */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "si-88-sectrust-valid-data"; sourceTree = "<group>"; };
- 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 = "<group>"; };
BE9F8D0F206C099800B53D16 /* Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = "<group>"; };
BE9F8D11206C121400B53D16 /* Decrypter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Decrypter.swift; sourceTree = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
+ D4231147237261F7000E470A /* SMIMEPolicyTests-data */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "SMIMEPolicyTests-data"; path = "tests/TrustTests/TestData/SMIMEPolicyTests-data"; sourceTree = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
D458C4C0214E19FB0043D982 /* TrustInterfaceTests_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TrustInterfaceTests_data.h; path = tests/TrustTests/FrameworkTests/TrustInterfaceTests_data.h; sourceTree = "<group>"; };
D458C4C5214E1A400043D982 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = tests/TrustTests/TestRunners/Assets.xcassets; sourceTree = "<group>"; };
D458C4C6214E1A400043D982 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = tests/TrustTests/TestRunners/main.m; sourceTree = "<group>"; };
- D458C4C7214E1A400043D982 /* Base.lproj */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Base.lproj; path = tests/TrustTests/TestRunners/Base.lproj; sourceTree = "<group>"; };
D458C4C8214E1A410043D982 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = tests/TrustTests/TestRunners/AppDelegate.h; sourceTree = "<group>"; };
D458C4C9214E1A410043D982 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ViewController.h; path = tests/TrustTests/TestRunners/ViewController.h; sourceTree = "<group>"; };
D458C4CA214E1A420043D982 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = tests/TrustTests/TestRunners/AppDelegate.m; sourceTree = "<group>"; };
D458C513214E27620043D982 /* PolicyTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = PolicyTests.m; path = tests/TrustTests/EvaluationTests/PolicyTests.m; sourceTree = "<group>"; };
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 = "<group>"; };
D458C51E214E2E0C0043D982 /* Main.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Main.storyboard; path = tests/TrustTests/TestRunners/Main.storyboard; sourceTree = "<group>"; };
+ D458DAC22375FEA300E5890E /* TrustSettingsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = TrustSettingsTests.m; path = tests/TrustTests/EvaluationTests/TrustSettingsTests.m; sourceTree = "<group>"; };
+ D458DAC52375FEE900E5890E /* TrustSettingsTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TrustSettingsTests_data.h; path = tests/TrustTests/EvaluationTests/TrustSettingsTests_data.h; sourceTree = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
D47079F221128C46005BCFDA /* SecCMS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SecCMS.h; path = CMS/SecCMS.h; sourceTree = "<group>"; };
D47079F9211355B3005BCFDA /* CMSEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CMSEncoder.h; path = CMS/CMSEncoder.h; sourceTree = "<group>"; };
D4707A0521136E69005BCFDA /* TrustTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TrustTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
D4707A282113ECA0005BCFDA /* SecCmsMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsMessage.h; path = CMS/SecCmsMessage.h; sourceTree = "<group>"; };
D4707A2B2114B31A005BCFDA /* SecCmsContentInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsContentInfo.h; path = CMS/SecCmsContentInfo.h; sourceTree = "<group>"; };
D4707A2E2114C30A005BCFDA /* SecCmsDigestContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCmsDigestContext.h; path = CMS/SecCmsDigestContext.h; sourceTree = "<group>"; };
+ D477CB5B237B6E0E00C02355 /* PersonalizationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = PersonalizationTests.m; path = tests/TrustTests/DaemonTests/PersonalizationTests.m; sourceTree = "<group>"; };
+ D477CB69237CBA2C00C02355 /* TrustDaemonTestCase.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = TrustDaemonTestCase.m; path = tests/TrustTests/DaemonTests/TrustDaemonTestCase.m; sourceTree = "<group>"; };
+ D477CB6D237CBACD00C02355 /* TrustDaemonTestCase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TrustDaemonTestCase.h; path = tests/TrustTests/DaemonTests/TrustDaemonTestCase.h; sourceTree = "<group>"; };
D477CB76237E453C00C02355 /* si-88-sectrust-valid-data */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "si-88-sectrust-valid-data"; path = "SecurityTests/si-88-sectrust-valid-data"; sourceTree = "<group>"; };
D477CB7A237E4BD700C02355 /* ExceptionTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ExceptionTests.m; path = tests/TrustTests/EvaluationTests/ExceptionTests.m; sourceTree = "<group>"; };
D477CB7D237F321400C02355 /* ExceptionTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ExceptionTests_data.h; path = tests/TrustTests/EvaluationTests/ExceptionTests_data.h; sourceTree = "<group>"; };
+ D477CB81237F692400C02355 /* RevocationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = RevocationTests.m; path = tests/TrustTests/EvaluationTests/RevocationTests.m; sourceTree = "<group>"; };
+ D477CB85237F6A0700C02355 /* RevocationTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RevocationTests_data.h; path = tests/TrustTests/EvaluationTests/RevocationTests_data.h; sourceTree = "<group>"; };
+ D477CB86237F8B2F00C02355 /* CAIssuerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = CAIssuerTests.m; path = tests/TrustTests/EvaluationTests/CAIssuerTests.m; sourceTree = "<group>"; };
+ D477CB89237F8CB300C02355 /* CAIssuerTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CAIssuerTests_data.h; path = tests/TrustTests/EvaluationTests/CAIssuerTests_data.h; sourceTree = "<group>"; };
+ D477CB8A237F8DBB00C02355 /* AllowlistBlocklistTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = AllowlistBlocklistTests.m; path = tests/TrustTests/EvaluationTests/AllowlistBlocklistTests.m; sourceTree = "<group>"; };
+ D477CB8D237F8EB200C02355 /* AllowlistBlocklistTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AllowlistBlocklistTests_data.h; path = tests/TrustTests/EvaluationTests/AllowlistBlocklistTests_data.h; sourceTree = "<group>"; };
+ D477CB8E237F975500C02355 /* ValidTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ValidTests.m; path = tests/TrustTests/EvaluationTests/ValidTests.m; sourceTree = "<group>"; };
D479F6E01F980F8F00388D28 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = en.lproj/Trust.strings; sourceTree = "<group>"; };
+ D47A085B2486EC1A000F2C49 /* AppleExternalRootCertificates.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppleExternalRootCertificates.h; sourceTree = "<group>"; };
+ 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; };
D47C56AB1DCA831C00E18518 /* lib_ios_x64.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = lib_ios_x64.xcconfig; path = xcconfig/lib_ios_x64.xcconfig; sourceTree = "<group>"; };
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 = "<group>"; };
- D47C56FB1DCA8F4900E18518 /* all_arches.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = all_arches.xcconfig; path = xcconfig/all_arches.xcconfig; sourceTree = "<group>"; };
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 = "<group>"; };
D47DCCB723427C8D00B80E37 /* md.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = md.h; sourceTree = "<group>"; };
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 = "<group>"; };
D4961BC52079426000F16DA7 /* TrustURLSessionDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TrustURLSessionDelegate.h; sourceTree = "<group>"; };
- D49A370023873A570065719F /* RevocationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RevocationTests.m; path = tests/TrustTests/EvaluationTests/RevocationTests.m; sourceTree = "<group>"; };
- D49A370223873A570065719F /* RevocationTests_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RevocationTests_data.h; path = tests/TrustTests/EvaluationTests/RevocationTests_data.h; sourceTree = "<group>"; };
- D49A370523873BD30065719F /* TrustDaemonTestCase.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = TrustDaemonTestCase.m; path = tests/TrustTests/DaemonTests/TrustDaemonTestCase.m; sourceTree = "<group>"; };
- D49A370823873BF10065719F /* TrustDaemonTestCase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TrustDaemonTestCase.h; path = tests/TrustTests/DaemonTests/TrustDaemonTestCase.h; sourceTree = "<group>"; };
D49A370B23877ECC0065719F /* OCSPCacheTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = OCSPCacheTests.m; path = tests/TrustTests/DaemonTests/OCSPCacheTests.m; sourceTree = "<group>"; };
D4A0F8BA211E69CB00443CA1 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = tests/TrustTests/Info.plist; sourceTree = "<group>"; };
D4A0F8BB211E69CB00443CA1 /* TestMacroConversions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TestMacroConversions.h; path = tests/TrustTests/TestMacroConversions.h; sourceTree = "<group>"; };
D4FD4222217D7B48002B7EE2 /* PathScoringTests_data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PathScoringTests_data.h; path = tests/TrustTests/EvaluationTests/PathScoringTests_data.h; sourceTree = "<group>"; };
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 = "<group>"; };
+ 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 = "<group>"; };
DA30D6831DF8CA4100EC6B43 /* KeychainSyncAccountUpdater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeychainSyncAccountUpdater.h; sourceTree = "<group>"; };
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 = "<group>"; };
DC05037921409A4100A8EDB7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+ DC061A6E246211DD0026ADB3 /* CKKSLocalResetOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSLocalResetOperation.h; sourceTree = "<group>"; };
+ DC061A70246211DE0026ADB3 /* CKKSLocalResetOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSLocalResetOperation.m; sourceTree = "<group>"; };
DC07090222936BCC002711B9 /* OctagonTests+ErrorHandling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+ErrorHandling.swift"; sourceTree = "<group>"; };
DC08D1C21E64FA8C006237DA /* CloudKitKeychainSyncingMockXCTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CloudKitKeychainSyncingMockXCTest.h; sourceTree = "<group>"; };
DC08D1C31E64FA8C006237DA /* CloudKitKeychainSyncingMockXCTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CloudKitKeychainSyncingMockXCTest.m; sourceTree = "<group>"; };
DC1787241D778FDE00B50D50 /* SecManifest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecManifest.h; path = OSX/libsecurity_manifest/lib/SecManifest.h; sourceTree = "<group>"; };
DC1787251D778FDE00B50D50 /* SecureDownloadInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecureDownloadInternal.h; path = OSX/libsecurity_manifest/lib/SecureDownloadInternal.h; sourceTree = "<group>"; };
DC1787281D77903700B50D50 /* SecAccessPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecAccessPriv.h; path = OSX/libsecurity_keychain/lib/SecAccessPriv.h; sourceTree = "<group>"; };
- DC1787291D77903700B50D50 /* SecCertificateBundle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCertificateBundle.h; path = OSX/libsecurity_keychain/lib/SecCertificateBundle.h; sourceTree = "<group>"; };
DC17872A1D77903700B50D50 /* SecFDERecoveryAsymmetricCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecFDERecoveryAsymmetricCrypto.h; path = OSX/libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.h; sourceTree = "<group>"; };
DC17872B1D77903700B50D50 /* SecIdentitySearchPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecIdentitySearchPriv.h; path = OSX/libsecurity_keychain/lib/SecIdentitySearchPriv.h; sourceTree = "<group>"; };
DC17872C1D77903700B50D50 /* SecKeychainItemExtendedAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecKeychainItemExtendedAttributes.h; path = OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.h; sourceTree = "<group>"; };
DC1787671D77911D00B50D50 /* osKeyTemplates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = osKeyTemplates.h; path = OSX/libsecurity_asn1/lib/osKeyTemplates.h; sourceTree = "<group>"; };
DC1787681D77911D00B50D50 /* secasn1t.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = secasn1t.h; path = OSX/libsecurity_asn1/lib/secasn1t.h; sourceTree = "<group>"; };
DC1787691D77911D00B50D50 /* X509Templates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = X509Templates.h; path = OSX/libsecurity_asn1/lib/X509Templates.h; sourceTree = "<group>"; };
- 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; };
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 = "<group>"; };
DC1789A41D779E3B00B50D50 /* dummy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dummy.cpp; path = OSX/lib/dummy.cpp; sourceTree = "<group>"; };
DC178A0E1D77A1E700B50D50 /* cssm.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = cssm.mdsinfo; path = OSX/libsecurity_cssm/mds/cssm.mdsinfo; sourceTree = "<group>"; };
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 = "<group>"; };
DC178A311D77A1F500B50D50 /* FDEPrefs.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = FDEPrefs.plist; path = OSX/lib/FDEPrefs.plist; sourceTree = "<group>"; };
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 = "<group>"; };
DC178A391D77A1F500B50D50 /* en */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = en; path = OSX/lib/en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
DC178A3A1D77A1F500B50D50 /* TimeStampingPrefs.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = TimeStampingPrefs.plist; path = OSX/lib/TimeStampingPrefs.plist; sourceTree = "<group>"; };
DC178A3C1D77A1F500B50D50 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = OSX/lib/en.lproj/authorization.dfr.prompts.strings; sourceTree = "<group>"; };
DC24B5681DA326B900330B48 /* rule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = rule.h; path = OSX/authd/rule.h; sourceTree = "<group>"; };
DC24B5691DA326B900330B48 /* server.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = server.h; path = OSX/authd/server.h; sourceTree = "<group>"; };
DC24B56A1DA326B900330B48 /* session.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = session.h; path = OSX/authd/session.h; sourceTree = "<group>"; };
- DC24B5701DA3274000330B48 /* breadcrumb_regressions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = breadcrumb_regressions.h; path = OSX/Breadcrumb/breadcrumb_regressions.h; sourceTree = "<group>"; };
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; };
DC311E782124B8EF002F5EAE /* aks_real_witness.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = aks_real_witness.h; sourceTree = "<group>"; };
DC311E792124B8EF002F5EAE /* aks_real_witness.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = aks_real_witness.c; sourceTree = "<group>"; };
DC340C53208E7BAE004D7EEC /* swift_binary.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = swift_binary.xcconfig; path = xcconfig/swift_binary.xcconfig; sourceTree = "<group>"; };
+ DC3412E5245780B9008ABD0A /* CKKSOperationDependencies.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSOperationDependencies.h; sourceTree = "<group>"; };
+ DC3412E6245780BA008ABD0A /* CKKSOperationDependencies.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSOperationDependencies.m; sourceTree = "<group>"; };
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 = "<group>"; };
DC3502B91E0208BE00BC0587 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
DC6ACC401E81DF9400125DC5 /* server_endpoint.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = server_endpoint.m; sourceTree = "<group>"; };
DC6DE897213076C000C6B56D /* OTSOSUpgradeOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSOSUpgradeOperation.h; sourceTree = "<group>"; };
DC6DE898213076C000C6B56D /* OTSOSUpgradeOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTSOSUpgradeOperation.m; sourceTree = "<group>"; };
+ DC6E02122405DDC300C61335 /* OTModifyUserControllableViewStatusOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTModifyUserControllableViewStatusOperation.h; sourceTree = "<group>"; };
+ DC6E02132405DDC400C61335 /* OTModifyUserControllableViewStatusOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTModifyUserControllableViewStatusOperation.m; sourceTree = "<group>"; };
DC7181062089172F00B2CB13 /* TrustedPeersHelper-entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "TrustedPeersHelper-entitlements.plist"; sourceTree = "<group>"; };
DC71D8DD1D94CF3C0065FB93 /* lib_ios_shim.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = lib_ios_shim.xcconfig; path = xcconfig/lib_ios_shim.xcconfig; sourceTree = "<group>"; };
DC72502D229600A800493D88 /* OctagonTests+Reset.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+Reset.swift"; sourceTree = "<group>"; };
DC844AEC1E81F315007AAB71 /* client_endpoint.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = client_endpoint.m; sourceTree = "<group>"; };
DC85687C2284E7850088D3EF /* OctagonTestMocks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OctagonTestMocks.swift; sourceTree = "<group>"; };
DC85687F2284E79C0088D3EF /* OctagonEscrowRecoverer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OctagonEscrowRecoverer.h; sourceTree = "<group>"; };
+ DC86122B2408AC190092E93B /* CKKSTests+ItemSyncChoice.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CKKSTests+ItemSyncChoice.m"; sourceTree = "<group>"; };
DC8757F2218D2003000E65F1 /* OTRemovePeersOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTRemovePeersOperation.h; sourceTree = "<group>"; };
DC8757F3218D2003000E65F1 /* OTRemovePeersOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTRemovePeersOperation.m; sourceTree = "<group>"; };
+ DC880F67243D4CC00059806D /* CKKSLogging.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSLogging.m; sourceTree = "<group>"; };
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 = "<group>"; };
DC88340C1D8A21AA00CE0ACA /* SecAsn1Templates.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecAsn1Templates.c; sourceTree = "<group>"; };
DC90A4C621F279D4001300EB /* SecEscrowPendingRecord.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = SecEscrowPendingRecord.proto; sourceTree = "<group>"; };
DC93F02722387A010072720A /* OTSOSUpdatePreapprovalsOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSOSUpdatePreapprovalsOperation.h; sourceTree = "<group>"; };
DC93F02822387A010072720A /* OTSOSUpdatePreapprovalsOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTSOSUpdatePreapprovalsOperation.m; sourceTree = "<group>"; };
+ DC947E812463831E005B8669 /* CKKSCheckKeyHierarchyOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSCheckKeyHierarchyOperation.h; sourceTree = "<group>"; };
+ DC947E832463831F005B8669 /* CKKSCheckKeyHierarchyOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSCheckKeyHierarchyOperation.m; sourceTree = "<group>"; };
DC94BCC81F10448600E07CEB /* CloudKitCategories.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CloudKitCategories.h; sourceTree = "<group>"; };
DC94BCC91F10448600E07CEB /* CloudKitCategories.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CloudKitCategories.m; sourceTree = "<group>"; };
DC976C581E3AC5E50012A6DD /* PlatformFeatures.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = PlatformFeatures.xcconfig; path = xcconfig/PlatformFeatures.xcconfig; sourceTree = "<group>"; };
+ DC9978B72404AA3200A5EE2F /* Container_UserSync.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container_UserSync.swift; sourceTree = "<group>"; };
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 = "<group>"; };
DC9A2C5E1EB3F556008FAC27 /* CKKSTests+Coalesce.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CKKSTests+Coalesce.m"; sourceTree = "<group>"; };
DCA4D1F41E5520550056214F /* CKKSCurrentKeyPointer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSCurrentKeyPointer.m; sourceTree = "<group>"; };
DCA4D2131E5684220056214F /* CKKSReencryptOutgoingItemsOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSReencryptOutgoingItemsOperation.h; sourceTree = "<group>"; };
DCA4D2141E5684220056214F /* CKKSReencryptOutgoingItemsOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSReencryptOutgoingItemsOperation.m; sourceTree = "<group>"; };
+ DCA7F7EE23A44AA200927989 /* OctagonPolicyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OctagonPolicyTests.swift; sourceTree = "<group>"; };
DCA9BC00221B721D00B4EB26 /* CKKSCloudKitClassDependencies.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSCloudKitClassDependencies.h; sourceTree = "<group>"; };
DCA9BC01221B721E00B4EB26 /* CKKSCloudKitClassDependencies.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSCloudKitClassDependencies.m; sourceTree = "<group>"; };
DCA9BC05221B7AFB00B4EB26 /* CKKSMockSOSPresentAdapter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSMockSOSPresentAdapter.h; sourceTree = "<group>"; };
DCB342441D8A32A20054D16E /* SecBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecBase.cpp; sourceTree = "<group>"; };
DCB342451D8A32A20054D16E /* SecBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecBridge.h; sourceTree = "<group>"; };
DCB342461D8A32A20054D16E /* SecCertificate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecCertificate.cpp; sourceTree = "<group>"; };
- DCB342471D8A32A20054D16E /* SecCertificateBundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecCertificateBundle.cpp; sourceTree = "<group>"; };
DCB342491D8A32A20054D16E /* SecIdentity.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecIdentity.cpp; sourceTree = "<group>"; };
DCB3424A1D8A32A20054D16E /* SecIdentitySearch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecIdentitySearch.cpp; sourceTree = "<group>"; };
DCB3424B1D8A32A20054D16E /* SecItemConstants.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecItemConstants.c; sourceTree = "<group>"; };
DCB342A51D8A32A20054D16E /* PolicyCursor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolicyCursor.h; sourceTree = "<group>"; };
DCB342A61D8A32A20054D16E /* SecCFTypes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecCFTypes.cpp; sourceTree = "<group>"; };
DCB342A71D8A32A20054D16E /* SecCFTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCFTypes.h; sourceTree = "<group>"; };
- DCB342A81D8A32A20054D16E /* SecKeychainAddIToolsPassword.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecKeychainAddIToolsPassword.cpp; sourceTree = "<group>"; };
DCB342AA1D8A32A20054D16E /* StorageManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = StorageManager.cpp; sourceTree = "<group>"; };
DCB342AB1D8A32A20054D16E /* Trust.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = Trust.cpp; sourceTree = "<group>"; };
DCB342AC1D8A32A20054D16E /* Trust.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Trust.h; sourceTree = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
DCB41DF9216C3F8A00F219E0 /* tpctl-entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "tpctl-entitlements.plist"; sourceTree = "<group>"; };
+ DCB5516A247F3DB50009A859 /* CKKSCreateCKZoneOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSCreateCKZoneOperation.h; sourceTree = "<group>"; };
+ DCB5516B247F3DB50009A859 /* CKKSCreateCKZoneOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSCreateCKZoneOperation.m; sourceTree = "<group>"; };
+ DCB55173247F48290009A859 /* CKKSDeleteCKZoneOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSDeleteCKZoneOperation.h; sourceTree = "<group>"; };
+ DCB55174247F48290009A859 /* CKKSDeleteCKZoneOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSDeleteCKZoneOperation.m; sourceTree = "<group>"; };
DCB5D9391E4A9A3400BE22AB /* CKKSSynchronizeOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSSynchronizeOperation.h; sourceTree = "<group>"; };
DCB5D93A1E4A9A3400BE22AB /* CKKSSynchronizeOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSSynchronizeOperation.m; sourceTree = "<group>"; };
DCB946AD22FCB88400BE4490 /* OTDetermineHSA2AccountStatusOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTDetermineHSA2AccountStatusOperation.h; sourceTree = "<group>"; };
DCB947592127534C00ED9272 /* OctagonTests+SOSUpgrade.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+SOSUpgrade.swift"; sourceTree = "<group>"; };
DCB9475B2127562100ED9272 /* OTSOSAdapter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTSOSAdapter.h; sourceTree = "<group>"; };
DCB9475C2127562100ED9272 /* OTSOSAdapter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTSOSAdapter.m; sourceTree = "<group>"; };
+ DCBA6F2824105399009A5187 /* CKKSTests+ForwardCompatibility.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CKKSTests+ForwardCompatibility.m"; sourceTree = "<group>"; };
+ DCBDA460245A39A300B0938B /* com.apple.TrustedPeersHelper.sb */ = {isa = PBXFileReference; lastKnownFileType = text; path = com.apple.TrustedPeersHelper.sb; sourceTree = "<group>"; };
DCBDB3B01E57C67500B61300 /* CKKSKeychainView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSKeychainView.h; sourceTree = "<group>"; };
DCBDB3B11E57C67500B61300 /* CKKSKeychainView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSKeychainView.m; sourceTree = "<group>"; };
DCBDB3B91E57CA7A00B61300 /* CKKSViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSViewManager.h; sourceTree = "<group>"; };
DCBF4AE321FFC9A800539F0A /* SecEscrowRequestTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecEscrowRequestTests.m; sourceTree = "<group>"; };
DCBFF830222611A200C5C044 /* OTFetchCKKSKeysOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTFetchCKKSKeysOperation.h; sourceTree = "<group>"; };
DCBFF831222611A200C5C044 /* OTFetchCKKSKeysOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTFetchCKKSKeysOperation.m; sourceTree = "<group>"; };
+ DCC03FA223FF521100A4DA3F /* TPSyncingPolicy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TPSyncingPolicy.h; sourceTree = "<group>"; };
+ DCC03FA323FF521100A4DA3F /* TPSyncingPolicy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TPSyncingPolicy.m; sourceTree = "<group>"; };
DCC0800D1CFF7903005C35C8 /* CSSMOID.exp-in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "CSSMOID.exp-in"; sourceTree = "<group>"; };
DCC1849220EEEC4400F3B26C /* security_framework.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = security_framework.xcconfig; path = xcconfig/security_framework.xcconfig; sourceTree = "<group>"; };
+ DCC40B0F2383786D00402CB9 /* CKKSStates.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CKKSStates.h; sourceTree = "<group>"; };
+ DCC40B102383786D00402CB9 /* CKKSStates.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSStates.m; sourceTree = "<group>"; };
DCC5417F225C05170095D926 /* OTUploadNewCKKSTLKsOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTUploadNewCKKSTLKsOperation.h; sourceTree = "<group>"; };
DCC54180225C05180095D926 /* OTUploadNewCKKSTLKsOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTUploadNewCKKSTLKsOperation.m; sourceTree = "<group>"; };
DCC5860220BF8A98005C7269 /* SecBase.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecBase.c; sourceTree = "<group>"; };
DCC78DBD1D8085FC00865A7C /* si-21-sectrust-asr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-21-sectrust-asr.c"; sourceTree = "<group>"; };
DCC78DBE1D8085FC00865A7C /* si-22-sectrust-iap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-22-sectrust-iap.c"; sourceTree = "<group>"; };
DCC78DBF1D8085FC00865A7C /* si-22-sectrust-iap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "si-22-sectrust-iap.h"; sourceTree = "<group>"; };
- DCC78DC01D8085FC00865A7C /* si-23-sectrust-ocsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-23-sectrust-ocsp.c"; sourceTree = "<group>"; };
DCC78DC11D8085FC00865A7C /* si-24-sectrust-digicert-malaysia.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-digicert-malaysia.c"; sourceTree = "<group>"; };
DCC78DC21D8085FC00865A7C /* si-24-sectrust-diginotar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-diginotar.c"; sourceTree = "<group>"; };
DCC78DC31D8085FC00865A7C /* si-24-sectrust-itms.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-itms.c"; sourceTree = "<group>"; };
DCC78DC51D8085FC00865A7C /* si-24-sectrust-passbook.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-24-sectrust-passbook.c"; sourceTree = "<group>"; };
DCC78DC61D8085FC00865A7C /* si-26-sectrust-copyproperties.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-26-sectrust-copyproperties.c"; sourceTree = "<group>"; };
- DCC78DC81D8085FC00865A7C /* si-28-sectrustsettings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "si-28-sectrustsettings.m"; sourceTree = "<group>"; };
- DCC78DC91D8085FC00865A7C /* si-28-sectrustsettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "si-28-sectrustsettings.h"; sourceTree = "<group>"; };
DCC78DCA1D8085FC00865A7C /* si-30-keychain-upgrade.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-30-keychain-upgrade.c"; sourceTree = "<group>"; };
DCC78DCB1D8085FC00865A7C /* si-31-keychain-bad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-31-keychain-bad.c"; sourceTree = "<group>"; };
DCC78DCC1D8085FC00865A7C /* si-31-keychain-unreadable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-31-keychain-unreadable.c"; sourceTree = "<group>"; };
DCC78DE81D8085FC00865A7C /* si-65-cms-cert-policy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-65-cms-cert-policy.c"; sourceTree = "<group>"; };
DCC78DE91D8085FC00865A7C /* signed-receipt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "signed-receipt.h"; sourceTree = "<group>"; };
DCC78DEB1D8085FC00865A7C /* si-66-smime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-66-smime.c"; sourceTree = "<group>"; };
- DCC78DEC1D8085FC00865A7C /* Global Trustee.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Global Trustee.cer.h"; sourceTree = "<group>"; };
- DCC78DED1D8085FC00865A7C /* UTN-USERFirst-Hardware.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UTN-USERFirst-Hardware.cer.h"; sourceTree = "<group>"; };
- DCC78DEE1D8085FC00865A7C /* addons.mozilla.org.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = addons.mozilla.org.cer.h; sourceTree = "<group>"; };
- DCC78DEF1D8085FC00865A7C /* login.live.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.live.com.cer.h; sourceTree = "<group>"; };
- DCC78DF01D8085FC00865A7C /* login.skype.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.skype.com.cer.h; sourceTree = "<group>"; };
- DCC78DF11D8085FC00865A7C /* login.yahoo.com.1.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.yahoo.com.1.cer.h; sourceTree = "<group>"; };
- DCC78DF21D8085FC00865A7C /* login.yahoo.com.2.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.yahoo.com.2.cer.h; sourceTree = "<group>"; };
- DCC78DF31D8085FC00865A7C /* login.yahoo.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.yahoo.com.cer.h; sourceTree = "<group>"; };
- DCC78DF41D8085FC00865A7C /* mail.google.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mail.google.com.cer.h; sourceTree = "<group>"; };
- DCC78DF51D8085FC00865A7C /* www.google.com.cer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = www.google.com.cer.h; sourceTree = "<group>"; };
- DCC78DF71D8085FC00865A7C /* si-67-sectrust-blocklist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-67-sectrust-blocklist.c"; sourceTree = "<group>"; };
DCC78DF81D8085FC00865A7C /* si-68-secmatchissuer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-68-secmatchissuer.c"; sourceTree = "<group>"; };
DCC78DF91D8085FC00865A7C /* si-69-keydesc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-69-keydesc.c"; sourceTree = "<group>"; };
DCC78DFA1D8085FC00865A7C /* si-70-sectrust-unified.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-70-sectrust-unified.c"; sourceTree = "<group>"; };
DCC78DFB1D8085FC00865A7C /* si-71-mobile-store-policy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-71-mobile-store-policy.c"; sourceTree = "<group>"; };
DCC78DFC1D8085FC00865A7C /* si-72-syncableitems.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-72-syncableitems.c"; sourceTree = "<group>"; };
DCC78DFD1D8085FC00865A7C /* si-73-secpasswordgenerate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-73-secpasswordgenerate.c"; sourceTree = "<group>"; };
- DCC78DFE1D8085FC00865A7C /* si-74-OTAPKISigner.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-74-OTAPKISigner.c"; sourceTree = "<group>"; };
DCC78DFF1D8085FC00865A7C /* si-76-shared-credentials.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-76-shared-credentials.c"; sourceTree = "<group>"; };
DCC78E001D8085FC00865A7C /* si_77_SecAccessControl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = si_77_SecAccessControl.c; sourceTree = "<group>"; };
DCC78E011D8085FC00865A7C /* si-78-query-attrs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-78-query-attrs.c"; sourceTree = "<group>"; };
DCD7DD9D22B868C200161396 /* TPPBDispositionDuplicateMachineID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TPPBDispositionDuplicateMachineID.h; sourceTree = "<group>"; };
DCD7EE9B1F4F51D9007D9804 /* ios_tapi_hacks.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ios_tapi_hacks.h; sourceTree = "<group>"; };
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 = "<group>"; };
DCDCC7DD1D9B54DF006487E8 /* secd-202-recoverykey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-202-recoverykey.m"; sourceTree = "<group>"; };
DCDCC7E41D9B551C006487E8 /* SOSAccountSync.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SOSAccountSync.m; sourceTree = "<group>"; };
DCDCCB8D1DF7B8D4006E840E /* CKKSItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSItem.h; sourceTree = "<group>"; };
DCE405C423A04A7F00C4343B /* OctagonTests+CKKSConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OctagonTests+CKKSConfiguration.swift"; sourceTree = "<group>"; };
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 = "<group>"; };
- 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 = "<group>"; };
DCE4E6D71D7A420D00AFB96E /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = OSX/SecurityTestsOSX/main.m; sourceTree = "<group>"; };
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; };
DCEA5D541E2826DB0089CF55 /* CKKSSIV.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSSIV.m; sourceTree = "<group>"; };
DCEA5D831E2F14810089CF55 /* OctagonAPSReceiver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OctagonAPSReceiver.h; sourceTree = "<group>"; };
DCEA5D841E2F14810089CF55 /* OctagonAPSReceiver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OctagonAPSReceiver.m; sourceTree = "<group>"; };
- DCEA5D951E3014250089CF55 /* CKKSZone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSZone.h; sourceTree = "<group>"; };
- DCEA5D961E3014250089CF55 /* CKKSZone.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSZone.m; sourceTree = "<group>"; };
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; };
DCF12671218A7579000124C6 /* OTLeaveCliqueOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTLeaveCliqueOperation.h; sourceTree = "<group>"; };
DCF12672218A757A000124C6 /* OTLeaveCliqueOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OTLeaveCliqueOperation.m; sourceTree = "<group>"; };
DCFABF8D20081E2F001128B5 /* CKKSDeviceStateUploadTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CKKSDeviceStateUploadTests.m; sourceTree = "<group>"; };
DCFAEDC81D999851005187E4 /* SOSAccountGhost.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SOSAccountGhost.m; sourceTree = "<group>"; };
DCFAEDC91D999851005187E4 /* SOSAccountGhost.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSAccountGhost.h; sourceTree = "<group>"; };
- DCFAEDD11D9998DD005187E4 /* secd-668-ghosts.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-668-ghosts.m"; sourceTree = "<group>"; };
DCFAEDD51D99A464005187E4 /* secd-36-ks-encrypt.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-36-ks-encrypt.m"; sourceTree = "<group>"; };
DCFB12C31E95A4C000510F5F /* CKKSAccountStateTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKKSAccountStateTracker.h; sourceTree = "<group>"; };
DCFB12C41E95A4C000510F5F /* CKKSAccountStateTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CKKSAccountStateTracker.m; sourceTree = "<group>"; };
E7F4809D1C74E86D00390FDB /* KCAESGCMTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KCAESGCMTest.m; path = Tests/KCAESGCMTest.m; sourceTree = "<group>"; };
E7F4826F1C74FDD100390FDB /* KCJoiningSessionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KCJoiningSessionTest.m; path = Tests/KCJoiningSessionTest.m; sourceTree = "<group>"; };
E7F482A21C7544E600390FDB /* libctkclient_test.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libctkclient_test.a; path = ../../../../../usr/local/lib/libctkclient_test.a; sourceTree = "<group>"; };
- E7F482A51C75453900390FDB /* libcoreauthd_test_client.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcoreauthd_test_client.a; path = ../../../../../usr/local/lib/libcoreauthd_test_client.a; sourceTree = "<group>"; };
E7F482A91C7554F500390FDB /* NSError+KCCreationHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+KCCreationHelpers.m"; sourceTree = "<group>"; };
E7F482AB1C7558F700390FDB /* KCJoiningAcceptSession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KCJoiningAcceptSession.m; sourceTree = "<group>"; };
E7FC30AB1332DE9000802946 /* MobileKeyBag.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileKeyBag.framework; path = System/Library/PrivateFrameworks/MobileKeyBag.framework; sourceTree = SDKROOT; };
EB433A1E1CC3242C00A7EACE /* secitemstresstest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = secitemstresstest.m; path = secitemstresstest/secitemstresstest.m; sourceTree = "<group>"; };
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 = "<group>"; };
+ EB45ED2E24749DE9008A1F6F /* gen_test_plist.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; name = gen_test_plist.py; path = tests/TrustTests/gen_test_plist.py; sourceTree = "<group>"; };
+ EB45ED3024749E63008A1F6F /* gen_test_plist.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = gen_test_plist.py; sourceTree = "<group>"; };
+ EB45ED3124749ECC008A1F6F /* OTTests-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "OTTests-Info.plist"; sourceTree = "<group>"; };
+ EB45ED3224749ECC008A1F6F /* gen_test_plist.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = gen_test_plist.py; sourceTree = "<group>"; };
EB48C19E1E573EDC00EC5E57 /* sos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sos.m; sourceTree = "<group>"; };
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; };
EB8021411D3D90BB008540C4 /* Security.iOS.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; name = Security.iOS.modulemap; path = Modules/Security.iOS.modulemap; sourceTree = "<group>"; };
EB8021421D3D90BB008540C4 /* Security.macOS.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; name = Security.macOS.modulemap; path = Modules/Security.macOS.modulemap; sourceTree = "<group>"; };
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 = "<group>"; };
- EB82A2A51FAFF26900CA64A9 /* SFBehavior.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFBehavior.m; sourceTree = "<group>"; };
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 = "<group>"; };
EB89111020E3C15D00DE533F /* UserManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserManagement.framework; path = System/Library/PrivateFrameworks/UserManagement.framework; sourceTree = SDKROOT; };
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 = "<group>"; };
EBF3747F1DC057FE0065D840 /* security-sysdiagnose.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = "security-sysdiagnose.1"; sourceTree = "<group>"; };
- EBF3749A1DC064200065D840 /* SecADWrapper.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SecADWrapper.c; sourceTree = "<group>"; };
- EBF3749B1DC064200065D840 /* SecADWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecADWrapper.h; sourceTree = "<group>"; };
EBF9AE171F536D0300FECBF7 /* Version.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Version.xcconfig; path = xcconfig/Version.xcconfig; sourceTree = "<group>"; };
F619D71D1ED70BB0005B5F46 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = OSX/authorizationdump/main.m; sourceTree = "<group>"; };
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 = "<group>"; };
F667EC601E96E9B100203D5C /* authdtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = authdtest; sourceTree = BUILT_PRODUCTS_DIR; };
+ F681C3A82386B8B40083F22C /* PreloginUserDb.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PreloginUserDb.m; path = OSX/authd/PreloginUserDb.m; sourceTree = "<group>"; };
+ F681C3AA2386B8B40083F22C /* PreloginUserDb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PreloginUserDb.h; path = OSX/authd/PreloginUserDb.h; sourceTree = "<group>"; };
F682C1CE1F4486F600F1B029 /* libctkloginhelper.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libctkloginhelper.a; path = usr/local/lib/libctkloginhelper.a; sourceTree = SDKROOT; };
F6A0971E1E953A1500B1E7D6 /* authdtestlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = authdtestlist.h; path = OSX/authd/tests/authdtestlist.h; sourceTree = "<group>"; };
F6A0971F1E953ABD00B1E7D6 /* authdtests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = authdtests.m; path = OSX/authd/tests/authdtests.m; sourceTree = "<group>"; };
F6A3CB0D1E7062BA00E7821F /* authd-Entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "authd-Entitlements.plist"; path = "OSX/authd/authd-Entitlements.plist"; sourceTree = "<group>"; };
+ 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 = "<group>"; };
F9B458272183E01100F6BCEB /* SignatureEditing.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = SignatureEditing.sh; path = OSX/codesign_tests/SignatureEditing.sh; sourceTree = "<group>"; };
F9F77E96223C2F7B00E5CBF6 /* requirement.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = requirement.c; sourceTree = "<group>"; };
F9F77E97223C2F7C00E5CBF6 /* requirement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = requirement.h; sourceTree = "<group>"; };
+ FC637229237B5CF800973738 /* SecItemServer+SWC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SecItemServer+SWC.h"; sourceTree = "<group>"; };
+ FC63722A237B5CF900973738 /* SecItemServer+SWC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "SecItemServer+SWC.m"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
0C0BDB881756A51000BC1A7E /* libsqlite3.dylib in Frameworks */,
BE8ABDD81DC2DD9100EC2D58 /* libz.dylib in Frameworks */,
4469FBFF1AA0A4820021AA26 /* libctkclient_test.a in Frameworks */,
+ DA53FC4523A9C801002D5EA9 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
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;
};
3DD1FFA5201FC59D0086D049 /* libsecurity_ssl.a in Frameworks */,
3DD1FFA4201FC58F0086D049 /* libutilities.a in Frameworks */,
3DD1FFA3201FC5870086D049 /* libDiagnosticMessagesClient.tbd in Frameworks */,
- 3DD1FFA2201FC5800086D049 /* SecurityFoundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
3DD1FFC6201FDB1D0086D049 /* Foundation.framework in Frameworks */,
3DD1FFC8201FDB1D0086D049 /* libsecurity_ssl.a in Frameworks */,
3DD1FFC9201FDB1D0086D049 /* libutilities.a in Frameworks */,
- 3DD1FFCB201FDB1D0086D049 /* SecurityFoundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 3E88360B24F068EF00E9F4D6 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 3E88361B24F08DA100E9F4D6 /* Security.framework in Frameworks */,
+ 3E88360D24F068EF00E9F4D6 /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
438169E41B4EE13B00C54D58 /* Accounts.framework in Frameworks */,
438169E51B4EE14D00C54D58 /* Security.framework in Frameworks */,
4381690D1B4EDCBD00C54D58 /* Foundation.framework in Frameworks */,
+ DA2F592723A99F2900C30285 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
4718AE23205B39620068EC3F /* IOKit.framework in Frameworks */,
4718AE24205B39620068EC3F /* libaks_acl.a in Frameworks */,
4718AE25205B39620068EC3F /* libsqlite3.dylib in Frameworks */,
+ DA2F592523A99E8400C30285 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
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;
};
);
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;
438166ED1B4ECF9400C54D58 /* CoreFoundation.framework in Frameworks */,
4CAF67AC0F3A70220064A534 /* IOKit.framework in Frameworks */,
0940F6F82151316500C06F18 /* libACM.a in Frameworks */,
+ 0C2B32A523C4001900A97B18 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
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 */,
4381603B1B4DCEFF00C54D58 /* AggregateDictionary.framework in Frameworks */,
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 */,
4C711D6D13AFCD0900FE865D /* Security.framework in Frameworks */,
D418CC701E690CAD00330A44 /* MobileAsset.framework in Frameworks */,
E71F3E4216EA6A6300FAF9B4 /* SystemConfiguration.framework in Frameworks */,
+ DA3862AA23AAD959001E21F1 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
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 */,
52D82BEE16A622370078DFE5 /* Security.framework in Frameworks */,
52D82BDF16A621F70078DFE5 /* Foundation.framework in Frameworks */,
E72D462B175FBF3E00F70B9B /* IOKit.framework in Frameworks */,
+ DA53FC3D23A9BF28002D5EA9 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
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 */,
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;
};
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 */,
6C39237221F13E4D00D018AD /* libutilities.a in Frameworks */,
6C39237321F13E4D00D018AD /* libsecdRegressions.a in Frameworks */,
6C39237421F13E4D00D018AD /* Foundation.framework in Frameworks */,
+ DA53FC3F23A9C26F002D5EA9 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
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 */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 6C9808841E788AFD00E70590 /* 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;
+ };
+ 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;
};
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;
E71F3E3116EA69A900FAF9B4 /* SystemConfiguration.framework in Frameworks */,
4CAF66190F3A6FCD0064A534 /* IOKit.framework in Frameworks */,
4C2215220F3A612C00835155 /* libsqlite3.dylib in Frameworks */,
+ 0C2B32A423C4000F00A97B18 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
D401E8B420A26F1F00CD8BB4 /* CoreData.framework in Frameworks */,
DC340C54208E828F004D7EEC /* TrustedPeers.framework in Frameworks */,
BE9F8D15206C2E0200B53D16 /* libutilities.a in Frameworks */,
+ DA53FC4923A9CC8D002D5EA9 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
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 */,
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;
};
D41257E21E94138600781F23 /* CoreFoundation.framework in Frameworks */,
D41257D01E9410A300781F23 /* Foundation.framework in Frameworks */,
D450686A1E948D2200FA7675 /* Security.framework in Frameworks */,
+ DA53FC3C23A9BDD5002D5EA9 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
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 */,
D453A4B92122236D00850A26 /* Foundation.framework in Frameworks */,
D453A4BA2122236D00850A26 /* IOKit.framework in Frameworks */,
D40B7CA021605BF800AC9A75 /* OCMock.framework in Frameworks */,
+ DA3862AB23AAE3A8001E21F1 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
files = (
D458C512214E20850043D982 /* XCTest.framework in Frameworks */,
D458C507214E20540043D982 /* Foundation.framework in Frameworks */,
+ DA2F592623A99EC900C30285 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
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 */,
D4B68C60211A80BC009FED69 /* CoreFoundation.framework in Frameworks */,
D4B68C61211A80C4009FED69 /* Foundation.framework in Frameworks */,
D4B68C63211A80DA009FED69 /* IOKit.framework in Frameworks */,
+ DA53FC4723A9CBAA002D5EA9 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
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 */,
DC1789251D7799CD00B50D50 /* CoreFoundation.framework in Frameworks */,
DC1789271D7799D400B50D50 /* IOKit.framework in Frameworks */,
0940F6F92151316600C06F18 /* libACM.a in Frameworks */,
+ DA2F591823A32BC100C30285 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
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 */,
DC222C361E02419B00B09171 /* libbsm.dylib in Frameworks */,
DC3502CA1E020DC100BC0587 /* libsqlite3.0.dylib in Frameworks */,
DC222C321E0240D300B09171 /* libz.dylib in Frameworks */,
+ DA53FC4023A9C351002D5EA9 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
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 */,
);
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 */,
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 */,
DCD22D6B1D8CC685001C9B81 /* AppleSystemInfo.framework in Frameworks */,
DC610A291D78F129002223DE /* IOKit.framework in Frameworks */,
DC610A271D78F129002223DE /* Security.framework in Frameworks */,
+ DA3862AE23AAE65E001E21F1 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
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 */,
DC99B88920EACA470065B73B /* libSecureObjectSyncServer.a in Frameworks */,
DC99B88A20EACA470065B73B /* libutilities.a in Frameworks */,
DC99B88B20EACA470065B73B /* libASN1.a in Frameworks */,
+ DA3862A923AAD1FD001E21F1 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
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 */,
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 */,
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 */,
DCD504C320CB293700F37D26 /* Security.framework in Frameworks */,
DC4DB16A1E26E9F900CD6769 /* ProtocolBuffer.framework in Frameworks */,
DCE4E82C1D7A56FF00AFB96E /* AppleSystemInfo.framework in Frameworks */,
+ DA53FC3923A9BA68002D5EA9 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
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;
};
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;
};
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 */,
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 */,
E71F3E4116EA6A5100FAF9B4 /* SystemConfiguration.framework in Frameworks */,
D418CC711E690CBC00330A44 /* MobileAsset.framework in Frameworks */,
0CFC029C1D41650700E6283B /* libcoretls.dylib in Frameworks */,
+ DA53FC4423A9C779002D5EA9 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
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;
};
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;
};
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 */,
EB49B2CD202DF0F9003F34A0 /* SystemConfiguration.framework in Frameworks */,
EB49B2C7202DF0E9003F34A0 /* IOKit.framework in Frameworks */,
EB49B2BC202DEF14003F34A0 /* libsqlite3.tbd in Frameworks */,
+ DA53FC4223A9C442002D5EA9 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
EB6952B1223B75C300F02C1C /* CoreData.framework in Frameworks */,
EB6952B2223B75C300F02C1C /* SystemConfiguration.framework in Frameworks */,
EB6952B3223B75C300F02C1C /* libsqlite3.dylib in Frameworks */,
+ DA2F592823A99F6300C30285 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
EB89087921F17D3C00F0DDDB /* Security.framework in Frameworks */,
EB89087B21F17D3C00F0DDDB /* SystemConfiguration.framework in Frameworks */,
EB89087E21F17D3C00F0DDDB /* libsqlite3.dylib in Frameworks */,
+ DA3862AC23AAE3D3001E21F1 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
EBB8521D22F7948B00424FD0 /* libutilities.a in Frameworks */,
EBB8521B22F7945600424FD0 /* XCTest.framework in Frameworks */,
EBB852CF22F7A05600424FD0 /* OCMock.framework in Frameworks */,
+ DA53FC4823A9CC16002D5EA9 /* SoftLinking.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
+ 0C0203DE23A855B8005D0A68 /* proto */ = {
+ isa = PBXGroup;
+ children = (
+ 0C0203E023A8564E005D0A68 /* OTEscrowRecord.proto */,
+ 0C0D920523BFEA740070A68C /* OTCDPRecoveryInformation.proto */,
+ 0C0203E523A85780005D0A68 /* generated_source */,
+ );
+ name = proto;
+ sourceTree = "<group>";
+ };
+ 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 = "<group>";
+ };
0C0BDB30175685B000BC1A7E /* secdtests */ = {
isa = PBXGroup;
children = (
path = Categories;
sourceTree = "<group>";
};
- 0C4C546C20E19CF200BA61BA /* Recovered References */ = {
- isa = PBXGroup;
- children = (
- 0C9FB40120D8729A00864612 /* CoreCDP.framework */,
- );
- name = "Recovered References";
- sourceTree = "<group>";
- };
0C7382E52386379E004F98CB /* ResetCloudKeychainAccount */ = {
isa = PBXGroup;
children = (
path = regressions;
sourceTree = "<group>";
};
- 0C7CEA391FE9CE3900125C79 /* behavior */ = {
- isa = PBXGroup;
- children = (
- EB82A2A41FAFF26900CA64A9 /* SFBehavior.h */,
- EB82A2A51FAFF26900CA64A9 /* SFBehavior.m */,
- );
- path = behavior;
- sourceTree = "<group>";
- };
- 0C8BBE831FC9DA1700580909 /* Octagon Trust */ = {
+ 0C8BBE831FC9DA1700580909 /* OT */ = {
isa = PBXGroup;
children = (
DCD33D7D220B9D98000A390B /* State Machine Machinery */,
BE34059B1FD71BA700933DAC /* Protocol Buffers */,
0C8BBEB11FC9DCAC00580909 /* tests */,
);
- name = "Octagon Trust";
+ name = OT;
path = ot;
sourceTree = "<group>";
};
isa = PBXGroup;
children = (
DC99B89720EAD4D20065B73B /* Octagon */,
+ EB45ED3124749ECC008A1F6F /* OTTests-Info.plist */,
+ EB45ED3224749ECC008A1F6F /* gen_test_plist.py */,
);
path = tests;
sourceTree = "<group>";
path = generated_source;
sourceTree = "<group>";
};
+ 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 = "<group>";
+ };
+ 0CCC22CB23F3958B00E1FCD0 /* categories */ = {
+ isa = PBXGroup;
+ children = (
+ 0CCC22CC23F395A100E1FCD0 /* OctagonTrustEscrowRecoverer.h */,
+ );
+ path = categories;
+ sourceTree = "<group>";
+ };
+ 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 = "<group>";
+ };
0CE15E29222DF5FF00B7EAA4 /* RecoveryKey */ = {
isa = PBXGroup;
children = (
0CF405FB2072E351003D6A7F /* Resources */,
0CD9E33E235928D1002995DE /* OctagonSignPosts.h */,
0CD9E340235928E9002995DE /* OctagonSignPosts.m */,
- 0CF0E2E71F8EE40700BD18E4 /* SFSignInAnalytics.h */,
- 0CF0E2E31F8EE3B000BD18E4 /* SFSignInAnalytics.m */,
- 0C108C4B208A677100E8CF70 /* SFSignInAnalytics+Internal.h */,
0CF405F32072E295003D6A7F /* tests */,
);
path = SigninMetrics;
0CF405F32072E295003D6A7F /* tests */ = {
isa = PBXGroup;
children = (
- 0CF405F42072E2BF003D6A7F /* SFSignInAnalyticsTests.m */,
);
path = tests;
sourceTree = "<group>";
0C78F1C816A5E13400654E08 /* regressions */,
107226D00D91DB32003CF14F /* SecTask.c */,
4C7CE56E0DC7DB0A00AE53FC /* SecEntitlements.h */,
+ 6C54BE0C23F41497004716CB /* SystemEntitlements.h */,
);
name = sectask;
path = ../../../sectask;
path = SecureTransportTests;
sourceTree = "<group>";
};
+ 3E88361224F0693200E9F4D6 /* secseccodeapitest */ = {
+ isa = PBXGroup;
+ children = (
+ 3E88361324F0699F00E9F4D6 /* secseccodeapitest.c */,
+ );
+ name = secseccodeapitest;
+ sourceTree = "<group>";
+ };
4381690E1B4EDCBD00C54D58 /* SOSCCAuthPlugin */ = {
isa = PBXGroup;
children = (
4727FBB81F9918590003AE36 /* secdxctests */ = {
isa = PBXGroup;
children = (
+ 6CD8412B23F5D871003DDF34 /* KeychainBackupTests.m */,
477A1FEB2037A0E000ACD81D /* KeychainXCTest.h */,
477A1FEC2037A0E000ACD81D /* KeychainXCTest.m */,
4727FBB91F9918590003AE36 /* KeychainCryptoTests.m */,
47B503C5203B97A000722164 /* SFCredentialStoreTests.m */,
477A1FE1203763A500ACD81D /* KeychainAPITests.m */,
09BFE35A20A32E0E008511E9 /* KeychainEntitlementsTest.m */,
+ 6C84E3C723ECBC84003C9710 /* KeychainAppClipTests.m */,
4727FBBB1F9918590003AE36 /* Info.plist */,
+ 6C5D62A5221B6E3F00AF79DC /* secdxctests-entitlements.plist */,
);
path = secdxctests;
sourceTree = "<group>";
47922D171FAA65120008F7E0 /* SecDbKeychainSerializedAKSWrappedKey.proto */,
47922D201FAA75FF0008F7E0 /* SecDbKeychainSerializedMetadata.proto */,
47922D2C1FAA77970008F7E0 /* SecDbKeychainSerializedSecretData.proto */,
+ 6C6AF178221A03930091CE0A /* SecDbKeychainSerializedMetadataKey.proto */,
);
path = "SecDbKeychainV7-protobufs";
sourceTree = "<group>";
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 */,
);
4C35DB67094F906D002917C4 = {
isa = PBXGroup;
children = (
+ 3DC5BD58241830D50039ABF4 /* SecureTransportTests_macos.xctestplan */,
+ 3DC5BD59241845100039ABF4 /* SecureTransportTests_ios.xctestplan */,
DC6D2C941DD3B20400BE372D /* keychain */,
DC5AC2021D83668700CF422C /* Security.framework */,
DC5AC1FD1D83647300CF422C /* SecureObjectSync */,
4CAB97FD1114CC5300EFB38D /* README.keychain */,
4C4CE9070AF81ED80056B01D /* TODO */,
EBAC4A512189743D00FBEC43 /* rio.yml */,
- 0C4C546C20E19CF200BA61BA /* Recovered References */,
);
sourceTree = "<group>";
};
D4ADA3191E2B41670031CEA3 /* libtrustd.a */,
6CCDF7841E3C25FA003F2555 /* KeychainEntitledTestRunner */,
6CF4A0B41E45488B00ECD7B5 /* KeychainEntitledTestApp.app */,
- 6CF4A0E01E4549F200ECD7B5 /* KeychainEntitledTestApp.app */,
EB27FF111E402CD300EC9E3A /* ckksctl */,
470415CF1E5E14B5001F3D95 /* seckeychainnetworkextensionstest */,
47702B1E1E5F409700B29577 /* seckeychainnetworkextensionsystemdaemontest */,
EB108F411E6CE4D2003B0456 /* KCPairingTests.xctest */,
F667EC601E96E9B100203D5C /* authdtest */,
D41257CF1E9410A300781F23 /* trustd */,
- 6C9808611E788AEB00E70590 /* CKKSCloudKitTests.xctest */,
- 6C98089D1E788AFD00E70590 /* CKKSCloudKitTests.xctest */,
ACBAF6DD1E9417F40007BA2F /* libsecurity_transform_regressions.a */,
BEF88C281EAFFC3F00357577 /* TrustedPeers.framework */,
BEF88C301EAFFC3F00357577 /* TrustedPeersTests.xctest */,
BED208DD1EDF950E00753952 /* manifeststresstest */,
47C51B841EEA657D0032D9E5 /* SecurityUnitTests.xctest */,
EB2D54AA1F02A45E00E46890 /* secatomicfile */,
- 4727FBB71F9918580003AE36 /* secdxctests_ios.xctest */,
+ 4727FBB71F9918580003AE36 /* secdxctests.xctest */,
0C85E0031FB38BB6000343A7 /* OTTests.xctest */,
6C9AA79E1F7C1D8F00D08296 /* supdctl */,
6CAA8D201F842FB3007B6E03 /* securityuploadd */,
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 */,
DA41FE0E2241ADC000838FB3 /* otpaird */,
EBB851EC22F7912400424FD0 /* SecurityUtilitiesTests.xctest */,
5A442F90233C330F00918373 /* experimentTool */,
+ 0CD743A623C3EC8000FA0EC5 /* OctagonTrust.framework */,
+ 6C7BE2E723C3DD64003BB2CA /* securitytool_bridge */,
+ 0CCC227923F357EE00E1FCD0 /* OctagonTrustTests.xctest */,
+ 6C2045EA2424BA7E00F9461D /* KeychainStasher */,
+ 6C963281242A279B00C53CE2 /* stashtester */,
+ 3E88361124F068EF00E9F4D6 /* secseccodeapitest */,
);
name = Products;
sourceTree = "<group>";
path = secacltests;
sourceTree = "<group>";
};
+ 6C0535F422B7043B0064BA50 /* TestHostBinaries */ = {
+ isa = PBXGroup;
+ children = (
+ 6CB5F4791E402E5700DBF3F0 /* KeychainEntitledTestRunner.entitlements */,
+ 6CF4A0B51E45488B00ECD7B5 /* KeychainEntitledTestApp */,
+ 6CB5F4771E402D6D00DBF3F0 /* KeychainEntitledTestRunner */,
+ );
+ name = TestHostBinaries;
+ path = tests/TestHostBinaries;
+ sourceTree = "<group>";
+ };
6C34464D1E2534C200F9522B /* analytics */ = {
isa = PBXGroup;
children = (
path = analytics;
sourceTree = "<group>";
};
+ 6C534E0422C3E52600D4781F /* Discovery Plists */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = "Discovery Plists";
+ path = "tests/Discovery Plists";
+ sourceTree = "<group>";
+ };
6C69517B1F758E1000F68F91 /* supd */ = {
isa = PBXGroup;
children = (
6C1260F21F7D5F25001B2EEC /* securityuploadd-osx.plist */,
6C5B10211F9164F5009B091E /* securityuploadd.8 */,
6CDB600E1FA92C1700410924 /* securityuploadd-Entitlements.plist */,
+ D42D044124733BEA004E7AA2 /* com.apple.securityuploadd.sb */,
);
path = supd;
sourceTree = "<group>";
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;
path = generated_source;
sourceTree = "<group>";
};
+ 6C963282242A279B00C53CE2 /* stashtester */ = {
+ isa = PBXGroup;
+ children = (
+ 6C963283242A279B00C53CE2 /* main.m */,
+ 6C963289242A27F300C53CE2 /* stashtester.entitlements */,
+ );
+ name = stashtester;
+ path = tests/stashtester;
+ sourceTree = "<group>";
+ };
+ 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 = "<group>";
+ };
6C9AA79F1F7C1D9000D08296 /* supdctl */ = {
isa = PBXGroup;
children = (
path = supdctl;
sourceTree = "<group>";
};
- 6CB5F4771E402D6D00DBF3F0 /* testrunner */ = {
+ 6CB5F4771E402D6D00DBF3F0 /* KeychainEntitledTestRunner */ = {
isa = PBXGroup;
children = (
- 6CB5F4791E402E5700DBF3F0 /* KeychainEntitledTestRunner-Entitlements.plist */,
6CB5F47A1E402E5700DBF3F0 /* KeychainEntitledTestRunner.m */,
);
- path = testrunner;
+ path = KeychainEntitledTestRunner;
sourceTree = "<group>";
};
6CB6CBFE2198D40B0080AD6F /* SecDbBackupManager-protobufs */ = {
path = "SecDbBackupManager-protobufs";
sourceTree = "<group>";
};
- 6CF4A0B51E45488B00ECD7B5 /* KeychainEntitledTestApp_mac */ = {
+ 6CF4A0B51E45488B00ECD7B5 /* KeychainEntitledTestApp */ = {
isa = PBXGroup;
children = (
6CF4A0B61E45488B00ECD7B5 /* AppDelegate.h */,
6CF4A0C41E45488B00ECD7B5 /* Info.plist */,
6CF4A0B91E45488B00ECD7B5 /* Supporting Files */,
);
- name = KeychainEntitledTestApp_mac;
- path = ../../../KeychainEntitledTestApp_mac;
+ path = KeychainEntitledTestApp;
sourceTree = "<group>";
};
6CF4A0B91E45488B00ECD7B5 /* Supporting Files */ = {
name = "Supporting Files";
sourceTree = "<group>";
};
- 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 = "<group>";
- };
- 6CF4A0E21E4549F200ECD7B5 /* Supporting Files */ = {
- isa = PBXGroup;
- children = (
- 6CF4A0E31E4549F200ECD7B5 /* main.m */,
- );
- name = "Supporting Files";
- sourceTree = "<group>";
- };
7908507E0CA87CF00083CC4D /* ipc */ = {
isa = PBXGroup;
children = (
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 */,
BEAA002C202A832500E51F45 /* TrustedPeersHelper */ = {
isa = PBXGroup;
children = (
- 0CE15E29222DF5FF00B7EAA4 /* RecoveryKey */,
DCB0C28F222F5DF80083AECB /* CuttlefishErrors.swift */,
+ 0CE15E29222DF5FF00B7EAA4 /* RecoveryKey */,
0C3BB3312187EC4D0018FC14 /* Categories */,
0C0C4F80216FB53A00C14C61 /* BottledPeer */,
BE9F4F852072D834004A52C2 /* Cuttlefish Client */,
BE55C77B2044D0C90045863D /* Client.swift */,
BE9F8D0F206C099800B53D16 /* Container.swift */,
DC3A9B2523A9D6120073ED06 /* Container_BottledPeers.swift */,
- DCAA209823AAF8BD00DCB594 /* Container_RecoveryKey.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 */,
0CB582BA218915010040C5F2 /* proto */,
DC391FA521C04D1500772585 /* OctagonPeerKeys.swift */,
DCF6320421C074F30030CCC0 /* CuttlefishAPIHelpers.swift */,
+ DCBDA460245A39A300B0938B /* com.apple.TrustedPeersHelper.sb */,
);
path = TrustedPeersHelper;
sourceTree = "<group>";
BEF88C5B1EB0005E00357577 /* TPPolicy.m */,
BEF88C5C1EB0005E00357577 /* TPPolicyDocument.h */,
BEF88C5D1EB0005E00357577 /* TPPolicyDocument.m */,
+ DCC03FA223FF521100A4DA3F /* TPSyncingPolicy.h */,
+ DCC03FA323FF521100A4DA3F /* TPSyncingPolicy.m */,
BEF88C5E1EB0005E00357577 /* TPKey.h */,
BECFA46320FFB87400B11002 /* TPKey.m */,
BEF88C5F1EB0005E00357577 /* TPTypes.h */,
D458C4CA214E1A420043D982 /* AppDelegate.m */,
D458C4C8214E1A410043D982 /* AppDelegate.h */,
D458C4C5214E1A400043D982 /* Assets.xcassets */,
- D458C4C7214E1A400043D982 /* Base.lproj */,
D458C4CC214E1A420043D982 /* Info.plist */,
D458C4C6214E1A400043D982 /* main.m */,
D458C4CB214E1A420043D982 /* trusttests_entitlements.plist */,
D4A0F8BB211E69CB00443CA1 /* TestMacroConversions.h */,
D44282FE22D68556001746B3 /* TrustEvaluationTestHelpers.m */,
D4A7946D22D7DD6E00D1B2B7 /* TrustEvaluationTestHelpers.h */,
+ EB45ED2E24749DE9008A1F6F /* gen_test_plist.py */,
);
name = TrustTests;
sourceTree = "<group>";
D4EA5CF622B225C000883439 /* LoggingServerTests.m */,
D49A370B23877ECC0065719F /* OCSPCacheTests.m */,
D4BA4FD22388687A000B9E64 /* OCSPCacheTests_data.h */,
- D49A370523873BD30065719F /* TrustDaemonTestCase.m */,
- D49A370823873BF10065719F /* TrustDaemonTestCase.h */,
+ D477CB5B237B6E0E00C02355 /* PersonalizationTests.m */,
+ D477CB69237CBA2C00C02355 /* TrustDaemonTestCase.m */,
+ D477CB6D237CBACD00C02355 /* TrustDaemonTestCase.h */,
);
name = DaemonTests;
sourceTree = "<group>";
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 */,
D4AC5766214E195300A32C01 /* ECTests.m */,
D4FD421F217D7B27002B7EE2 /* PathScoringTests.m */,
D4FD4222217D7B48002B7EE2 /* PathScoringTests_data.h */,
D458C513214E27620043D982 /* PolicyTests.m */,
+ D477CB81237F692400C02355 /* RevocationTests.m */,
+ D477CB85237F6A0700C02355 /* RevocationTests_data.h */,
D458C4B7214E19AF0043D982 /* SignatureAlgorithmTests.m */,
D458C4B6214E19AE0043D982 /* SignatureAlgorithmTests_data.h */,
+ D423114223725F9F000E470A /* SMIMEPolicyTests.m */,
D4056A1922712A650026E24E /* SSLPolicyTests.m */,
D4056A1C22712AD80026E24E /* SSLPolicyTests_data.h */,
- D49A370023873A570065719F /* RevocationTests.m */,
- D49A370223873A570065719F /* RevocationTests_data.h */,
+ D458DAC22375FEA300E5890E /* TrustSettingsTests.m */,
+ D458DAC52375FEE900E5890E /* TrustSettingsTests_data.h */,
+ D477CB8E237F975500C02355 /* ValidTests.m */,
D4AC5764214E195200A32C01 /* VerifyDateTests.m */,
D4AC5765214E195300A32C01 /* VerifyDateTests_data.h */,
D4A0F8CB211E6A8200443CA1 /* TrustEvaluationTestCase.h */,
D4A0F8C0211E69F500443CA1 /* TestData */ = {
isa = PBXGroup;
children = (
+ D4231147237261F7000E470A /* SMIMEPolicyTests-data */,
D4B2966822DBFDB100DCF250 /* TestCopyProperties_ios-data */,
D4D92DA72278904F0009A7CF /* nist-certs */,
D4AC8BED2132127A006E9871 /* si-18-certificate-parse */,
isa = PBXGroup;
children = (
DC0BC9DB1D8B827200070CB0 /* CipherSuite.h */,
- DC0BC9DC1D8B827200070CB0 /* SecureTransport.h */,
);
name = "Public Headers";
path = ../Security;
isa = PBXGroup;
children = (
DC0BC9DE1D8B827200070CB0 /* sslTypes.h */,
+ DC0BC9DC1D8B827200070CB0 /* SecureTransport.h */,
DC0BC9DF1D8B827200070CB0 /* SecureTransportPriv.h */,
);
name = "Private Headers";
DC0BCB191D8B898100070CB0 /* SecTranslocateUtilities.cpp */,
DC0BCB1A1D8B898100070CB0 /* SecTranslocateUtilities.hpp */,
DC0BCB1B1D8B898100070CB0 /* SecTranslocateInterface.cpp */,
+ 61BDC97E242932A100A2ABD8 /* SecTranslocateEnumUtils.hpp */,
);
path = lib;
sourceTree = "<group>";
DC0BCC3B1D8C68CF00070CB0 /* iCloudKeychainTrace.h */,
EB3FBBF42320629400DF52EA /* SecABC.h */,
EB3FBBF52320629400DF52EA /* SecABC.m */,
- EBF3749A1DC064200065D840 /* SecADWrapper.c */,
- EBF3749B1DC064200065D840 /* SecADWrapper.h */,
DC0BCC3C1D8C68CF00070CB0 /* SecAKSWrappers.c */,
DC0BCC3D1D8C68CF00070CB0 /* SecAKSWrappers.h */,
DA5B871A2065A8410093F083 /* SecAutorelease.h */,
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 */,
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 */,
E7C787311DD0FED50087FC34 /* NSURL+SOSPlistStore.m */,
DC0BCC6B1D8C68CF00070CB0 /* SecDb.c */,
DC0BCC6C1D8C68CF00070CB0 /* SecDb.h */,
+ 6C915BE3242E14BC00DBDAFB /* SecDbInternal.h */,
DC0BCC6D1D8C68CF00070CB0 /* SecFileLocations.c */,
DC0BCC6E1D8C68CF00070CB0 /* SecFileLocations.h */,
DC0BCC6F1D8C68CF00070CB0 /* SecXPCError.h */,
children = (
DCC78E281D8085FC00865A7C /* AppleBaselineEscrowCertificates.h */,
D41149A01E7C935D00C078C7 /* AppleiPhoneDeviceCACertificates.h */,
+ D47A085B2486EC1A000F2C49 /* AppleExternalRootCertificates.h */,
DCC78E301D8085FC00865A7C /* SecAccessControl.m */,
443381DA18A3D81400215606 /* SecAccessControlPriv.h */,
DCC78E351D8085FC00865A7C /* SecBase64.c */,
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 */,
DCC78E8A1D8085FC00865A7C /* SecServerEncryptionSupport.c */,
E7676DB519411DF300498DD4 /* SecServerEncryptionSupport.h */,
DCC78E8C1D8085FC00865A7C /* SecSharedCredential.c */,
+ BE7B8E112415579800E1CF4F /* SecSharedCredential.m */,
DCC78E8E1D8085FC00865A7C /* SecSignatureVerificationSupport.c */,
DCC78E8F1D8085FC00865A7C /* SecSignatureVerificationSupport.h */,
DCC78E901D8085FC00865A7C /* SecTrust.c */,
name = headers;
sourceTree = "<group>";
};
- 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 = "<group>";
- };
DC1789A31D779E2400B50D50 /* Security.framework macOS */ = {
isa = PBXGroup;
children = (
- DC17899F1D779DD600B50D50 /* SecBreadcrumb */,
DCF783091D88B4B500E694BB /* apple_csp */,
DCF785E61D88B96800E694BB /* apple_cspdl */,
DCF787341D88C84300E694BB /* apple_file_dl */,
D4C263C51F8FF2A9001317EA /* generateErrStrings.pl */,
DC178A321D77A1F500B50D50 /* SecDebugErrorMessages.strings */,
DC178A331D77A1F500B50D50 /* SecErrorMessages.strings */,
- DC178A351D77A1F500B50D50 /* framework.sb */,
DC178A381D77A1F500B50D50 /* InfoPlist.strings */,
DC178A3A1D77A1F500B50D50 /* TimeStampingPrefs.plist */,
DC178A3B1D77A1F500B50D50 /* authorization.dfr.prompts.strings */,
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 */,
DCE7F2081F21726500DDB0F7 /* OctagonAPSReceiverTests.m */,
DC9C95951F748D0B000D19E5 /* CKKSServerValidationRecoveryTests.m */,
EB0E1AD723576273002B6037 /* CKKSPBFileStorageTests.m */,
+ EB45ED3024749E63008A1F6F /* gen_test_plist.py */,
);
name = "Tests (Local)";
path = tests;
DC8506A42097E8CF00C712EC /* iOS Resources */,
DCC78E1C1D8085FC00865A7C /* add_internet_password.c */,
DC52EA8E1D80CC2A00B0A59C /* builtin_commands.h */,
+ BE57B1162509E0FF0045B7FD /* ca_revocation_additions.m */,
DCC78E1E1D8085FC00865A7C /* codesign.c */,
D4A3A596217A85CB00F0A8DA /* ct_exceptions.m */,
DC52EA8F1D80CC2A00B0A59C /* digest_calc.c */,
DC5ABFD11D83511A00CF422C /* notifications.cpp */,
DC5ABFD21D83511A00CF422C /* SharedMemoryServer.h */,
DC5ABFD31D83511A00CF422C /* SharedMemoryServer.cpp */,
+ 6C755604242121F000025D78 /* keychainstasherinterface.h */,
+ 6C755603242121F000025D78 /* keychainstasherinterface.m */,
);
name = Support;
sourceTree = "<group>";
DC5AC2011D83663C00CF422C /* tests */ = {
isa = PBXGroup;
children = (
+ 6C534E0422C3E52600D4781F /* Discovery Plists */,
+ 6C0535F422B7043B0064BA50 /* TestHostBinaries */,
EBDAF14021C75FC800EAE89F /* SharedMocks */,
DC05037721409A4100A8EDB7 /* OCMockUmbrella */,
F667EC541E96E8C800203D5C /* authdtests */,
EB49B2AF202D8780003F34A0 /* secdmockaks */,
6C7E8F1D21F7BD1C008A2D56 /* SecDbBackupTests */,
D4A0F8B9211E69A800443CA1 /* TrustTests */,
+ 6C963282242A279B00C53CE2 /* stashtester */,
);
name = tests;
sourceTree = "<group>";
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 = "<group>";
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 */,
path = OSX/libsecurity_asn1/lib;
sourceTree = "<group>";
};
- DC88467E223742CA00738068 /* View Matching */ = {
- isa = PBXGroup;
- children = (
- );
- name = "View Matching";
- path = view_matching;
- sourceTree = "<group>";
- };
DC90A4BD21F275EC001300EB /* escrowrequest */ = {
isa = PBXGroup;
children = (
DC99B89720EAD4D20065B73B /* Octagon */ = {
isa = PBXGroup;
children = (
- DCC0A4C52152C4AB000AF654 /* Pairing */,
- DC27C3C820EADD8200F7839C /* OctagonTests-BridgingHeader.h */,
+ DCEA0FF6213F1E6F0054A328 /* Octagon.plist */,
+ DC7EB928211E20DF00516452 /* OctagonDataPersistenceTests.swift */,
DC85687C2284E7850088D3EF /* OctagonTestMocks.swift */,
- DC4CD9822372294D00EF55FC /* OctagonTests+Helpers.swift */,
+ DC27C3C820EADD8200F7839C /* OctagonTests-BridgingHeader.h */,
+ DC99B89320EACA480065B73B /* OctagonTests-Info.plist */,
DC27C3C020EAD9C300F7839C /* OctagonTests.swift */,
DC4415B323610BF40087981C /* OctagonTests+Account.swift */,
DC7F79B522EA4ED4001FB69A /* OctagonTests+CKKS.swift */,
DC5BEACC2217509A001681F0 /* OctagonTests+CloudKitAccount.swift */,
DC5F2BBD2310B941001ADA5D /* OctagonTests+CoreFollowUp.swift */,
DC2819B822F8F6FE007829F5 /* OctagonTests+DeviceList.swift */,
- DC7F6A7C233D7FAC00DF5769 /* OctagonTests+ForwardCompatibility.swift */,
- 0C4CDE6D22922E360050C499 /* OctagonTests+RecoveryKey.swift */,
DC07090222936BCC002711B9 /* OctagonTests+ErrorHandling.swift */,
+ 0CBF883A23AAD9DC00652EDD /* OctagonTests+EscrowRecords.swift */,
DCDF03112284E34B008055BA /* OctagonTests+EscrowRecovery.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 */,
+ 5A04BAF922973EA9001848A0 /* OTFollowupTests.m */,
+ DCC0A4C52152C4AB000AF654 /* Pairing */,
0CBEF3422242C9BE00015691 /* TestsObjcTranslation.h */,
0CBEF3412242C9AE00015691 /* TestsObjcTranslation.m */,
+ DCA7F7EE23A44AA200927989 /* OctagonPolicyTests.swift */,
);
name = Octagon;
path = octagon;
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 */,
path = generated_source;
sourceTree = "<group>";
};
- DCA4D2121E5651950056214F /* Tests (Live CloudKit) */ = {
- isa = PBXGroup;
- children = (
- 6CF4A0B51E45488B00ECD7B5 /* KeychainEntitledTestApp_mac */,
- 6CF4A0E11E4549F200ECD7B5 /* KeychainEntitledTestApp_ios */,
- 6CB5F4771E402D6D00DBF3F0 /* testrunner */,
- 6CCDF7911E3C2D69003F2555 /* CKKSCloudKitTests.m */,
- 6CB5F4751E4025AB00DBF3F0 /* CKKSCloudKitTestsInfo.plist */,
- );
- name = "Tests (Live CloudKit)";
- path = tests;
- sourceTree = "<group>";
- };
DCA4D2191E569FFE0056214F /* Helpers */ = {
isa = PBXGroup;
children = (
EB4E0CD51FF36A1900CDCACC /* CKKSReachabilityTracker.m */,
DC207EB61ED4EAB600D46873 /* CKKSLockStateTracker.h */,
DC207EB71ED4EAB600D46873 /* CKKSLockStateTracker.m */,
+ DC3412E5245780B9008ABD0A /* CKKSOperationDependencies.h */,
+ DC3412E6245780BA008ABD0A /* CKKSOperationDependencies.m */,
DCCD88E61E42622200F5AA71 /* CKKSGroupOperation.h */,
DCCD88E71E42622200F5AA71 /* CKKSGroupOperation.m */,
DC1447881F5764C600236DB4 /* CKKSResultOperation.h */,
DCB344731D8A35270054D16E /* regressions */,
DCB342F81D8A32A20054D16E /* lib */,
DC1787281D77903700B50D50 /* SecAccessPriv.h */,
- DC1787291D77903700B50D50 /* SecCertificateBundle.h */,
DC17872A1D77903700B50D50 /* SecFDERecoveryAsymmetricCrypto.h */,
DC17872B1D77903700B50D50 /* SecIdentitySearchPriv.h */,
DC17872C1D77903700B50D50 /* SecKeychainItemExtendedAttributes.h */,
DCB342441D8A32A20054D16E /* SecBase.cpp */,
DCB342451D8A32A20054D16E /* SecBridge.h */,
DCB342461D8A32A20054D16E /* SecCertificate.cpp */,
- DCB342471D8A32A20054D16E /* SecCertificateBundle.cpp */,
DCB342491D8A32A20054D16E /* SecIdentity.cpp */,
DCB3424A1D8A32A20054D16E /* SecIdentitySearch.cpp */,
DCB3424B1D8A32A20054D16E /* SecItemConstants.c */,
DCB342551D8A32A20054D16E /* SecTrust.cpp */,
DCB342561D8A32A20054D16E /* SecTrustedApplication.cpp */,
DCB342571D8A32A20054D16E /* SecTrustSettings.cpp */,
+ 6C2D463924C88A700015C3C9 /* LegacyAPICounts.h */,
+ 6C2D463B24C88A870015C3C9 /* LegacyAPICounts.m */,
);
name = "API Bridge";
sourceTree = "<group>";
DCB342A51D8A32A20054D16E /* PolicyCursor.h */,
DCB342A61D8A32A20054D16E /* SecCFTypes.cpp */,
DCB342A71D8A32A20054D16E /* SecCFTypes.h */,
- DCB342A81D8A32A20054D16E /* SecKeychainAddIToolsPassword.cpp */,
DCB342AA1D8A32A20054D16E /* StorageManager.cpp */,
DCB342AB1D8A32A20054D16E /* Trust.cpp */,
DCB342AC1D8A32A20054D16E /* Trust.h */,
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 */,
- DCBFF830222611A200C5C044 /* OTFetchCKKSKeysOperation.h */,
- DCBFF831222611A200C5C044 /* OTFetchCKKSKeysOperation.m */,
- DCF12671218A7579000124C6 /* OTLeaveCliqueOperation.h */,
- DCF12672218A757A000124C6 /* OTLeaveCliqueOperation.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 */,
+ 0CA7020B2280D99D0085AC54 /* OTCheckHealthOperation.h */,
+ 0CA702082280D5600085AC54 /* OTCheckHealthOperation.m */,
0CC8A9002123AA3B005D7F6A /* OTClientVoucherOperation.h */,
0CC8A8FA2123A9EB005D7F6A /* OTClientVoucherOperation.m */,
- 0CC8A9052123AF16005D7F6A /* OTJoinWithVoucherOperation.h */,
- 0CC8A9012123AEF7005D7F6A /* OTJoinWithVoucherOperation.m */,
- 0C66046E2134985100BFBBB8 /* OTEstablishOperation.h */,
- 0C6604692134983900BFBBB8 /* OTEstablishOperation.m */,
- DC0D15FF2363A1D6007F0951 /* OTSetCDPBitOperation.h */,
- DC0D16002363A1D6007F0951 /* OTSetCDPBitOperation.m */,
DC0D16042363BAF4007F0951 /* OTDetermineCDPBitStatusOperation.h */,
DC0D16052363BAF4007F0951 /* OTDetermineCDPBitStatusOperation.m */,
- DCFF82722162876400D54B02 /* OTResetOperation.h */,
- DCFF82732162876400D54B02 /* OTResetOperation.m */,
- 0C00FC85217A972E00C8BF00 /* OTLocalCuttlefishReset.h */,
- 0C00FC81217A971800C8BF00 /* OTLocalCuttlefishReset.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 */,
- DCC5417F225C05170095D926 /* OTUploadNewCKKSTLKsOperation.h */,
- DCC54180225C05180095D926 /* OTUploadNewCKKSTLKsOperation.m */,
DC7250352296056000493D88 /* OTResetCKKSZonesLackingTLKsOperation.h */,
DC7250362296056000493D88 /* OTResetCKKSZonesLackingTLKsOperation.m */,
- 0CB8DC962194B1300021A7C8 /* OTVouchWithBottleOperation.h */,
- 0CB8DC992194B1440021A7C8 /* OTVouchWithBottleOperation.m */,
- 0C1B8BB3223323710094D5DA /* OTVouchWithRecoveryKeyOperation.h */,
- 0C1B8BB52233241E0094D5DA /* OTVouchWithRecoveryKeyOperation.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 */,
- 0CA7020B2280D99D0085AC54 /* OTCheckHealthOperation.h */,
- 0CA702082280D5600085AC54 /* OTCheckHealthOperation.m */,
- 0C87D3DA229326CB007853B5 /* OTEnsureOctagonKeyConsistency.h */,
- 0C87D3D6229326A2007853B5 /* OTEnsureOctagonKeyConsistency.m */,
+ DC221BA92267E2A60068DBCF /* OTUpdateTPHOperation.h */,
+ DC221BAA2267E2A60068DBCF /* OTUpdateTPHOperation.m */,
+ DCF46C2C214B1E0700319A93 /* OTUpdateTrustedDeviceListOperation.h */,
+ DCF46C2D214B1E0700319A93 /* OTUpdateTrustedDeviceListOperation.m */,
+ DCC5417F225C05170095D926 /* OTUploadNewCKKSTLKsOperation.h */,
+ DCC54180225C05180095D926 /* OTUploadNewCKKSTLKsOperation.m */,
+ 0CB8DC962194B1300021A7C8 /* OTVouchWithBottleOperation.h */,
+ 0CB8DC992194B1440021A7C8 /* OTVouchWithBottleOperation.m */,
+ 0C1B8BB3223323710094D5DA /* OTVouchWithRecoveryKeyOperation.h */,
+ 0C1B8BB52233241E0094D5DA /* OTVouchWithRecoveryKeyOperation.m */,
);
name = Operations;
sourceTree = "<group>";
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 */,
DCDCC7DD1D9B54DF006487E8 /* secd-202-recoverykey.m */,
7281E08E1DFD0D810021E1B7 /* secd-210-keyinterest.m */,
522B28081E64B48E002B5638 /* secd-230-keybagtable.m */,
- DCFAEDD11D9998DD005187E4 /* secd-668-ghosts.m */,
DCC78C791D8085D800865A7C /* SOSAccountTesting.h */,
DCC78C7A1D8085D800865A7C /* SecdTestKeychainUtilities.c */,
DCC78C7B1D8085D800865A7C /* SecdTestKeychainUtilities.h */,
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 */,
path = "si-66-smime";
sourceTree = "<group>";
};
- 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 = "<group>";
- };
DCC78E121D8085FC00865A7C /* secitem */ = {
isa = PBXGroup;
children = (
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 */,
DC0B62261D90973900D43BCB /* si-25-cms-skid.h */,
DC0B62271D90973900D43BCB /* si-25-cms-skid.m */,
DCC78DC61D8085FC00865A7C /* si-26-sectrust-copyproperties.c */,
- DCC78DC81D8085FC00865A7C /* si-28-sectrustsettings.m */,
- DCC78DC91D8085FC00865A7C /* si-28-sectrustsettings.h */,
D4AA0D9922FB959600D77FA4 /* si-29-cms-chain-mode.m */,
D4AA0D9C22FB962300D77FA4 /* si-29-cms-chain-mode.h */,
DCC78DCA1D8085FC00865A7C /* si-30-keychain-upgrade.c */,
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 */,
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 */,
DCD662F41E329B6800188186 /* CKKSNewTLKOperation.m */,
DCBF2F831F913EF000ED0CA4 /* CKKSHealTLKSharesOperation.h */,
DCBF2F841F913EF000ED0CA4 /* CKKSHealTLKSharesOperation.m */,
+ DC061A6E246211DD0026ADB3 /* CKKSLocalResetOperation.h */,
+ DC061A70246211DE0026ADB3 /* CKKSLocalResetOperation.m */,
DC7A17EB1E36ABC200EF14CE /* CKKSProcessReceivedKeysOperation.h */,
DC7A17EC1E36ABC200EF14CE /* CKKSProcessReceivedKeysOperation.m */,
DC5F65AC2225C22C0051E9FA /* CKKSProvideKeySetOperation.h */,
DC222CA91E08C57400B09171 /* CloudKitDependencies.h */,
DCEA5D831E2F14810089CF55 /* OctagonAPSReceiver.h */,
DCEA5D841E2F14810089CF55 /* OctagonAPSReceiver.m */,
- DCEA5D951E3014250089CF55 /* CKKSZone.h */,
- DCEA5D961E3014250089CF55 /* CKKSZone.m */,
DC18F76D1E43E116006B8B43 /* CKKSFetchAllRecordZoneChangesOperation.h */,
DC18F76E1E43E116006B8B43 /* CKKSFetchAllRecordZoneChangesOperation.m */,
DCFB12C31E95A4C000510F5F /* CKKSAccountStateTracker.h */,
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 = "<group>";
DCE0777C21ADE96C002662FD /* generated */ = {
isa = PBXGroup;
children = (
+ 6C6AF17D221A06F70091CE0A /* SecDbKeychainSerializedMetadataKey.h */,
+ 6C6AF17E221A06F80091CE0A /* SecDbKeychainSerializedMetadataKey.m */,
47922D501FAA7DF60008F7E0 /* SecDbKeychainSerializedItemV7.h */,
47922D511FAA7DF70008F7E0 /* SecDbKeychainSerializedItemV7.m */,
47922D371FAA7C040008F7E0 /* SecDbKeychainSerializedAKSWrappedKey.h */,
DC24B5641DA326B900330B48 /* Info.plist */,
DC24B5651DA326B900330B48 /* mechanism.h */,
DC24B5661DA326B900330B48 /* object.h */,
+ F681C3AA2386B8B40083F22C /* PreloginUserDb.h */,
DC24B5671DA326B900330B48 /* process.h */,
DC24B5681DA326B900330B48 /* rule.h */,
DC24B5691DA326B900330B48 /* server.h */,
DCE4E8AB1D7F353900AFB96E /* main.c */,
DCE4E8AC1D7F353900AFB96E /* mechanism.c */,
DCE4E8AD1D7F353900AFB96E /* object.c */,
+ F681C3A82386B8B40083F22C /* PreloginUserDb.m */,
DCE4E8AE1D7F353900AFB96E /* process.c */,
DCE4E8AF1D7F353900AFB96E /* rule.c */,
DCE4E8B01D7F353900AFB96E /* server.c */,
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 */,
E710C74B1331946500F85568 /* Supporting Files */,
E7FCBE401314471B000DE34E /* Frameworks */ = {
isa = PBXGroup;
children = (
+ 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 */,
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 */,
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 */,
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 */,
EB80211C1D3D9044008540C4 /* Modules */ = {
isa = PBXGroup;
children = (
+ 0CF7613D23F24B5D00A3C3AD /* KeychainCircle.modulemap */,
+ 0CF7613F23F24B5E00A3C3AD /* OctagonTrust.modulemap */,
EB8021411D3D90BB008540C4 /* Security.iOS.modulemap */,
EB8021421D3D90BB008540C4 /* Security.macOS.modulemap */,
617570BA22C2D19E00EFBA37 /* Security.macOS.private.modulemap */,
EB9C1DAA1BDFD0FE00F89272 /* RegressionTests */ = {
isa = PBXGroup;
children = (
+ 3E88361224F0693200E9F4D6 /* secseccodeapitest */,
+ 6CF33CA2238714C900D1E75D /* bats_utd_plist.h */,
+ 6CF33CA4238714C900D1E75D /* PreprocessPlist.sh */,
EB9C1DAD1BDFD49400F89272 /* Security.plist */,
EBDAA7E320EC46CF003EA6E5 /* SecurityLocalKeychain.plist */,
EBE202752092913500B48020 /* SecurityInduceLowDisk.plist */,
/* 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;
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 */,
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 */,
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 */,
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 */,
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 */,
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 */,
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 */,
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 */,
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 */,
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 */,
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 */,
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 */,
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 */,
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 */,
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 */,
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 */,
DC047081218BB21E0078BDAA /* OTCuttlefishAccountStateHolder.h in Headers */,
DC1DA65E1E4554620094CE7F /* CKKSScanLocalItemsOperation.h in Headers */,
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 */,
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 */,
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
- 0C78827520132074002B7475 /* SFSignInAnalytics.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
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 */,
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 */,
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 */,
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;
productReference = 3DD1FFD0201FDB1D0086D049 /* SecureTransport_ios_tests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
+ 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" */;
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 */,
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 */ = {
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" */;
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;
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 */,
- );
- name = CKKSCloudKitTests_mac;
- productName = CKKSTests;
- productReference = 6C9808611E788AEB00E70590 /* CKKSCloudKitTests.xctest */;
- productType = "com.apple.product-type.bundle.unit-test";
+ 6C16258423C4FFD40086A0FF /* PBXTargetDependency */,
+ 6C16258623C4FFD40086A0FF /* PBXTargetDependency */,
+ 6C16258123C4FFC40086A0FF /* PBXTargetDependency */,
+ 6C14CA0423C4F6830097B572 /* PBXTargetDependency */,
+ 6C7BE2AA23C3DD64003BB2CA /* PBXTargetDependency */,
+ 6C7BE2AC23C3DD64003BB2CA /* PBXTargetDependency */,
+ );
+ 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;
6CAA8D1D1F842FB3007B6E03 /* Frameworks */,
6CAA8D1E1F842FB3007B6E03 /* Copy Manpage */,
6CAA8D361F84317F007B6E03 /* Install launchd plist */,
+ D42D044424734050004E7AA2 /* Install sandbox profile for macOS */,
);
buildRules = (
);
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 */,
);
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" */;
BEAA0029202A832500E51F45 /* Resources */,
BEAA0028202A832500E51F45 /* Frameworks */,
EB3FB9A3231C125400DF52EA /* Copy Logging Files */,
+ DC2C884D245B4B3E0040CBEB /* Copy Sandbox Profile (macOS only) */,
);
buildRules = (
);
D4707A0221136E69005BCFDA /* Frameworks */,
D4707A0321136E69005BCFDA /* Resources */,
D4428B432122718400EB8448 /* Generate BATS Plist */,
+ D428337D24E1D0B10068B2F5 /* Remove Name Constraints Resources from watchOS */,
);
buildRules = (
);
DCE4E8541D7A57AE00AFB96E /* Copy LaunchDaemon Files */,
BEB463AD1E64F3C1008EB77E /* Copy Sandbox */,
D4ADA3111E2B209C0031CEA3 /* Install man8 page */,
+ D459364124BFBA700066FB43 /* Install Apple Corporate Roots */,
);
buildRules = (
);
4C35DB69094F906D002917C4 /* Project object */ = {
isa = PBXProject;
attributes = {
- LastSwiftUpdateCheck = 1000;
- LastUpgradeCheck = 1120;
+ LastSwiftUpdateCheck = 1200;
+ LastUpgradeCheck = 1200;
TargetAttributes = {
+ 0CD743A523C3EC8000FA0EC5 = {
+ CreatedOnToolsVersion = 12.0;
+ };
4381690B1B4EDCBD00C54D58 = {
CreatedOnToolsVersion = 7.0;
};
CreatedOnToolsVersion = 10.0;
ProvisioningStyle = Automatic;
};
- 478D426C1FD72A8100CAB645 = {
- ProvisioningStyle = Automatic;
- };
47C2F1822059CB680062DE30 = {
CreatedOnToolsVersion = 10.0;
ProvisioningStyle = Automatic;
5EBE24791B00CCAE0007DB0E = {
CreatedOnToolsVersion = 7.0;
};
- 6C39234421F13E4D00D018AD = {
- ProvisioningStyle = Manual;
+ 6C2045E92424BA7E00F9461D = {
+ CreatedOnToolsVersion = 12.0;
};
- 6C98082C1E788AEB00E70590 = {
- TestTargetID = 6CF4A0B31E45488B00ECD7B5;
+ 6C39234421F13E4D00D018AD = {
+ ProvisioningStyle = Automatic;
};
- 6C9808681E788AFD00E70590 = {
- TestTargetID = 6CF4A0DF1E4549F200ECD7B5;
+ 6C963280242A279B00C53CE2 = {
+ CreatedOnToolsVersion = 12.0;
};
6C9AA79D1F7C1D8F00D08296 = {
CreatedOnToolsVersion = 9.0;
CreatedOnToolsVersion = 8.3;
ProvisioningStyle = Automatic;
};
- 6CF4A0DF1E4549F200ECD7B5 = {
- CreatedOnToolsVersion = 8.3;
- ProvisioningStyle = Automatic;
- };
BEAA002A202A832500E51F45 = {
CreatedOnToolsVersion = 9.3;
LastSwiftMigration = 0930;
};
DCF216D621ADD5B10029CCC1 = {
CreatedOnToolsVersion = 11.0;
+ LastSwiftMigration = 1200;
ProvisioningStyle = Automatic;
};
DCF7889C1D88CB5200E694BB = {
};
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 */;
DC1789031D77980500B50D50 /* Security_osx */,
E7D847C41C6BE9710025BB44 /* KeychainCircle */,
BEF88C271EAFFC3F00357577 /* TrustedPeers */,
+ 0CD743A523C3EC8000FA0EC5 /* OctagonTrust */,
DC8E04911D7F6CED006D80EB /* ======= Daemons ========= */,
DCE4E8931D7F34F600AFB96E /* authd */,
DCE4E7F51D7A4DA800AFB96E /* secd */,
DC0BC5631D8B6E3D00070CB0 /* XPCTimeStampingService */,
BEAA002A202A832500E51F45 /* TrustedPeersHelper */,
DA41FE0D2241ADC000838FB3 /* otpaird */,
+ 6C2045E92424BA7E00F9461D /* KeychainStasher */,
DC8E04B11D7F6EC9006D80EB /* ======= Libraries ========= */,
DCDA5E4F2124B9C5009B11B2 /* aks_support */,
DC36895D21235F42003A3735 /* aks_mock */,
DC0067921D87876F005AF8DB /* securityd_server_macos */,
DC0067C51D878898005AF8DB /* securityd_ucspc */,
DC8E04951D7F6D80006D80EB /* ========= CLI =========== */,
+ 6C7BE2A923C3DD64003BB2CA /* securitytool_bridge */,
4CB740A20A47567C00D641BB /* securitytool_ios */,
DC5ABDC41D832DAB00CF422C /* securitytool_macos */,
DCE4E68A1D7A37FA00AFB96E /* security2tool_macos */,
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 */,
EB433A201CC3243600A7EACE /* secitemstresstest */,
EBA9AA7D1CE30E58004E2B68 /* secitemnotifications */,
DAE40BC520CF3E46002D5674 /* secitemcanarytest */,
+ 3E88360824F068EF00E9F4D6 /* secseccodeapitest */,
DCE4E7CB1D7A4AED00AFB96E /* sectests_macos */,
470415CE1E5E14B5001F3D95 /* seckeychainnetworkextensionstest */,
47702B1D1E5F409700B29577 /* seckeychainnetworkextensionsystemdaemontest */,
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 */,
D458C4E0214E1DE00043D982 /* TrustTestsRunner_ios */,
D4707A0421136E69005BCFDA /* TrustTests_ios */,
D453A4A42122236D00850A26 /* TrustTests_macos */,
+ 6C963280242A279B00C53CE2 /* stashtester */,
DC5AC1351D835D9700CF422C /* ===== Source Gen ===== */,
DC008B451D90CE53004002A3 /* securityd_macos_mig */,
DC6BC26C1D90CFEF00DD57B3 /* securityd_macos_startup */,
/* End PBXReferenceProxy section */
/* Begin PBXResourcesBuildPhase section */
+ 0CCC227423F357EE00E1FCD0 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
4381690A1B4EDCBD00C54D58 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
4C198F220ACDB4BF00AAB142 /* Certificate.strings in Resources */,
4C198F230ACDB4BF00AAB142 /* OID.strings in Resources */,
D479F6E21F980FAB00388D28 /* Trust.strings in Resources */,
+ 6C5D62A6221B6E3F00AF79DC /* secdxctests-entitlements.plist in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
files = (
52A23EDD161DEC3F00E271E0 /* Default-568h@2x.png in Resources */,
D4D886E91CEBDD2A00DC7583 /* nist-certs in Resources */,
- BE9B8B4B202BB4D10081EF87 /* si-88-sectrust-valid-data in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
);
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;
);
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;
files = (
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 */,
files = (
D458C51F214E2E0C0043D982 /* Main.storyboard in Resources */,
D458C51C214E2DEB0043D982 /* Assets.xcassets in Resources */,
- D458C51D214E2DEB0043D982 /* Base.lproj in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
files = (
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 */,
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 */,
DC99B88E20EACA470065B73B /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
- files = (
- );
runOnlyForDeploymentPostprocessing = 0;
};
DCE4E76B1D7A43B500AFB96E /* Resources */ = {
buildActionMask = 2147483647;
files = (
DCE4E76D1D7A43B500AFB96E /* nist-certs in Resources */,
- BE9B8B4D202BB4F30081EF87 /* si-88-sectrust-valid-data in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
files = (
52A23EDC161DEC3800E271E0 /* Default-568h@2x.png in Resources */,
D4D886EA1CEBDE0800DC7583 /* nist-certs in Resources */,
- BE9B8B4C202BB4E30081EF87 /* si-88-sectrust-valid-data in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
- 090585D020AEF9D300BB7490 /* Install OCMock framework */ = {
+ 090585D120AEF9FE00BB7490 /* Install OCMock framework */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 8;
files = (
shellPath = /bin/sh;
shellScript = "sh xcscripts/install-test-framework.sh OCMock.framework\n";
};
- 090585D120AEF9FE00BB7490 /* Install OCMock framework */ = {
+ 0C85DFFF1FB38BB6000343A7 /* ShellScript */ = {
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";
+ shellScript = "[ \"$(whoami)\" == \"root\" ] || exit 0\n#Disable until this places a plist in this directory\n#chown -f root:wheel ${DSTROOT}/AppleInternal/CoreOS/BATS/unit_tests/*.plist\n";
};
- 0C85DFFF1FB38BB6000343A7 /* ShellScript */ = {
+ 3DD1FF49201C07F30086D049 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 8;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = /bin/sh;
- shellScript = "[ \"$(whoami)\" == \"root\" ] || exit 0\n#Disable until this places a plist in this directory\n#chown -f root:wheel ${DSTROOT}/AppleInternal/CoreOS/BATS/unit_tests/*.plist\n";
+ shellScript = "[ \"$(whoami)\" == \"root\" ] || exit 0\nchown -f root:wheel ${DSTROOT}/AppleInternal/CoreOS/BATS/unit_tests/*.plist\n";
};
- 3DD1FF49201C07F30086D049 /* ShellScript */ = {
+ 3DD1FFCC201FDB1D0086D049 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 8;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = /bin/sh;
- shellScript = "[ \"$(whoami)\" == \"root\" ] || exit 0\nchown -f root:wheel ${DSTROOT}/AppleInternal/CoreOS/BATS/unit_tests/*.plist\n";
+ shellScript = "[ \"$(whoami)\" == \"root\" ] || exit 0\nchown -f root:wheel ${DSTROOT}/AppleInternal/CoreOS/BATS/unit_tests/*.plist";
};
- 3DD1FFCC201FDB1D0086D049 /* ShellScript */ = {
+ 6CAA8D361F84317F007B6E03 /* Install launchd plist */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 8;
files = (
);
inputPaths = (
);
+ name = "Install launchd plist";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = /bin/sh;
- shellScript = "[ \"$(whoami)\" == \"root\" ] || exit 0\nchown -f root:wheel ${DSTROOT}/AppleInternal/CoreOS/BATS/unit_tests/*.plist";
+ shellScript = "mkdir -p \"$LAUNCHD_PLIST_LOCATION\"\nplutil -convert binary1 -o \"$LAUNCHD_PLIST_LOCATION/com.apple.securityuploadd.plist\" \"$LAUNCHD_PLIST\"\n";
};
- 6C7E8F2121F7BE7F008A2D56 /* Chown BATS Test Discovery Plist */ = {
+ 8E64DB4E1C18A5B80076C9DF /* Install launchd plist */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 8;
files = (
);
- inputFileListPaths = (
- );
inputPaths = (
+ "$(PROJECT_DIR)/KVSKeychainSyncingProxy/com.apple.security.cloudkeychainproxy3.ios.plist",
+ "$(PROJECT_DIR)/KVSKeychainSyncingProxy/com.apple.security.cloudkeychainproxy3.osx.plist",
);
- name = "Chown BATS Test Discovery Plist";
- outputFileListPaths = (
- );
+ name = "Install launchd plist";
outputPaths = (
+ "$(INSTALL_ROOT)/$(INSTALL_DAEMON_AGENT_DIR)/com.apple.security.cloudkeychainproxy3.plist",
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = /bin/sh;
- shellScript = "[ \"$(whoami)\" == \"root\" ] || exit 0\n chown -f root:wheel ${DSTROOT}/AppleInternal/CoreOS/BATS/unit_tests/*.plist\n";
+ 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";
};
- 6CAA8D361F84317F007B6E03 /* Install launchd plist */ = {
+ D428337D24E1D0B10068B2F5 /* Remove Name Constraints Resources from watchOS */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 8;
files = (
);
+ inputFileListPaths = (
+ );
inputPaths = (
);
- name = "Install launchd plist";
+ name = "Remove Name Constraints Resources from watchOS";
+ outputFileListPaths = (
+ );
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = /bin/sh;
- shellScript = "mkdir -p \"$LAUNCHD_PLIST_LOCATION\"\nplutil -convert binary1 -o \"$LAUNCHD_PLIST_LOCATION/com.apple.securityuploadd.plist\" \"$LAUNCHD_PLIST\"\n";
+ shellScript = "# see <rdar://66792084>\nif [ \"${PLATFORM_NAME}\" == \"watchos\" ]; then\n rm -rf \"$DSTROOT/AppleInternal/XCTests/com.apple.security/TrustTests.xctest/si-87-sectrust-name-constraints\"\nfi\n";
};
- 8E64DB4E1C18A5B80076C9DF /* Install launchd plist */ = {
+ D42D044424734050004E7AA2 /* Install sandbox profile for macOS */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 8;
files = (
);
+ inputFileListPaths = (
+ );
inputPaths = (
- "$(PROJECT_DIR)/KVSKeychainSyncingProxy/com.apple.security.cloudkeychainproxy3.ios.plist",
- "$(PROJECT_DIR)/KVSKeychainSyncingProxy/com.apple.security.cloudkeychainproxy3.osx.plist",
+ "$(SRCROOT)/supd/com.apple.securityuploadd.sb",
+ );
+ name = "Install sandbox profile for macOS";
+ outputFileListPaths = (
);
- name = "Install launchd plist";
outputPaths = (
- "$(INSTALL_ROOT)/$(INSTALL_DAEMON_AGENT_DIR)/com.apple.security.cloudkeychainproxy3.plist",
+ "$(DSTROOT)/System/Library/Sandbox/Profiles/com.apple.securityuploadd.sb",
);
runOnlyForDeploymentPostprocessing = 1;
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";
+ 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;
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;
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;
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 */,
);
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 */,
);
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;
};
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 */,
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 3E88360924F068EF00E9F4D6 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 3E88361424F0699F00E9F4D6 /* secseccodeapitest.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
438169081B4EDCBD00C54D58 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
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 */,
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 */,
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 */,
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 */,
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;
};
);
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;
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 */,
DC3AA2862097E22A007CA68A /* codesign.c in Sources */,
DC8506AC2097EEBA00C712EC /* sos.m in Sources */,
E78A9ADA1D34959200006B5B /* NSFileHandle+Formatting.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 */,
);
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 */,
);
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 */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 6C9808791E788AFD00E70590 /* 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 */,
+ 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;
+ };
+ 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;
};
);
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;
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 */,
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 */,
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 */,
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 */,
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 */,
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 */,
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 */,
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- D49A370723873BD30065719F /* TrustDaemonTestCase.m in Sources */,
- D49A370423873A580065719F /* RevocationTests.m in Sources */,
+ 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 */,
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 */,
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 */,
+ D477CB5D237B6E0E00C02355 /* PersonalizationTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
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 */,
D40881F9217573EF00180E81 /* SecSignatureVerificationSupport.c in Sources */,
D40881F8217573E700180E81 /* SecCertificate.c in Sources */,
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 */,
+ 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 */,
- D49A370323873A580065719F /* RevocationTests.m in Sources */,
+ D477CB82237F692400C02355 /* RevocationTests.m in Sources */,
D458C4BA214E19AF0043D982 /* iAPTests.m in Sources */,
D458C4B8214E19AF0043D982 /* PathParseTests.m in Sources */,
D458C525214E33440043D982 /* VerifyDateTests.m in Sources */,
- D49A370623873BD30065719F /* TrustDaemonTestCase.m in Sources */,
D458C515214E286C0043D982 /* PolicyTests.m in Sources */,
+ D458DAC32375FEA300E5890E /* TrustSettingsTests.m in Sources */,
D477CB7B237E4BD700C02355 /* ExceptionTests.m in Sources */,
D4EF32182156DDEB000A31A5 /* TrustSettingsInterfaceTests.m in Sources */,
D44282FF22D68564001746B3 /* TrustEvaluationTestHelpers.m in Sources */,
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 */,
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 */,
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 */,
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 */,
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 */,
6CAA8CFE1F83E800007B6E03 /* SFSQLite.m in Sources */,
DC9C95C01F79DC89000D19E5 /* CKKSControl.m in Sources */,
5AF594001FA0EE5300A5C1EC /* SecProtocol.c in Sources */,
+ BE7B8E152415580D00E1CF4F /* SecSharedCredential.c in Sources */,
5A442FAA233C351100918373 /* SecExperiment.m in Sources */,
0C8884042154C4EA0053224D /* OTJoiningConfiguration.m in Sources */,
0C0E60E020D033E400E654F2 /* OTControl.m in Sources */,
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 */,
);
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 */,
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;
};
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 */,
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 */,
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 */,
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 */,
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 */,
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 */,
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 */,
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 */,
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 */,
DC52EDD41D80D5C500B0A59C /* secd-60-account-cloud-identity.m in Sources */,
DC52EDD51D80D5C500B0A59C /* secd60-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 */,
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 */,
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 */,
EB6928CA1D9C9E1800062A18 /* rk_01_recoverykey.m in Sources */,
D42CDC351DC12FE90090E2C9 /* si-66-smime.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 */,
DC52EE4C1D80D71900B0A59C /* si-24-sectrust-passbook.c in Sources */,
DC52EE4D1D80D71900B0A59C /* si-26-sectrust-copyproperties.c in Sources */,
5E7793751E5F025A0074A2D1 /* si-44-seckey-aks.m 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 */,
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;
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 */,
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 */,
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 */,
DC07090422936DB2002711B9 /* OctagonTests+ErrorHandling.swift in Sources */,
DC99B86C20EACA470065B73B /* FakeCuttlefish.swift in Sources */,
0CBEF3432242CA0600015691 /* TestsObjcTranslation.m in Sources */,
+ 0C468FFE23C7D4F9006F4582 /* OTEscrowRecordMetadata.m in Sources */,
5A04BB0222982733001848A0 /* OTFollowupTests.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 */,
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 */,
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 */,
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 */,
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 */,
DCAB17CE21FFF75B00E1DFCF /* MockSynchronousEscrowServer.m in Sources */,
DCBF4ABB21FFC82100539F0A /* SecFramework.c in Sources */,
DCBF4ABE21FFC82100539F0A /* server_entitlement_helpers.c in Sources */,
+ A6C737C123F37AC00009C930 /* entitlements.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
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 */,
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 */,
DC3AA2852097E22A007CA68A /* codesign.c in Sources */,
DC8506AD2097EEBC00C712EC /* sos.m in Sources */,
DCE4E6931D7A37FA00AFB96E /* NSFileHandle+Formatting.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 */,
buildActionMask = 2147483647;
files = (
DCE4E7B51D7A43FF00AFB96E /* main.m in Sources */,
- DCE4E7B61D7A440A00AFB96E /* bc-10-knife-on-bread.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
buildActionMask = 2147483647;
files = (
DCE4E7E21D7A4B7F00AFB96E /* main.c in Sources */,
- DCE4E7DF1D7A4B4C00AFB96E /* bc-10-knife-on-bread.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
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 */,
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 */,
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 */,
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 */,
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 */,
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 */,
EB49B2D9202DF1F7003F34A0 /* server_security_helpers.m in Sources */,
EBC73F2B2099785900AE3350 /* SFObjCType.m in Sources */,
480ADDB22155A0CE00318FC6 /* SOSAnalytics.m 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 */,
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 */,
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 */,
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 */;
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;
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 */;
target = DCC78EA81D8088E200865A7C /* security */;
targetProxy = 0C85DFE11FB38BB6000343A7 /* PBXContainerItemProxy */;
};
- 0C9AEEBA20783FE000BF6237 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = DC1789031D77980500B50D50 /* Security_osx */;
- targetProxy = 0C9AEEB920783FE000BF6237 /* PBXContainerItemProxy */;
- };
0CA378E923876E0900090B7E /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 0CA378E123876DD100090B7E /* reset_account */;
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 */;
target = DC0BCC211D8C684F00070CB0 /* utilities */;
targetProxy = 3DD258A1204B7DA800F5DA78 /* PBXContainerItemProxy */;
};
+ 3E88361D24F08F5400E9F4D6 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 3E88360824F068EF00E9F4D6 /* secseccodeapitest */;
+ targetProxy = 3E88361C24F08F5400E9F4D6 /* PBXContainerItemProxy */;
+ };
438169E71B4EE4B300C54D58 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 4381690B1B4EDCBD00C54D58 /* SOSCCAuthPlugin */;
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 */;
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 */;
target = 5346480017331E1100FE9172 /* KeychainSyncAccountNotification */;
targetProxy = 5346481A17331ED800FE9172 /* PBXContainerItemProxy */;
};
- 6C4AA1AA2228B640006FA945 /* PBXTargetDependency */ = {
+ 5AAE383623D261CF0025CF9E /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
- target = EB9C1DAE1BDFD4DE00F89272 /* SecurityBatsTests */;
- targetProxy = 6C4AA1A92228B640006FA945 /* PBXContainerItemProxy */;
+ target = 5A442F81233C330F00918373 /* experimentTool */;
+ targetProxy = 5AAE383523D261CF0025CF9E /* PBXContainerItemProxy */;
};
- 6C8FF4B6224C1A9800E5C812 /* PBXTargetDependency */ = {
+ 6C14CA0423C4F6830097B572 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
- target = BEF88C271EAFFC3F00357577 /* TrustedPeers */;
- targetProxy = 6C8FF4B5224C1A9800E5C812 /* PBXContainerItemProxy */;
- };
- 6C98082F1E788AEB00E70590 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = DC8834011D8A218F00CE0ACA /* ASN1 */;
- targetProxy = 6C9808301E788AEB00E70590 /* PBXContainerItemProxy */;
+ target = 4718AE2E205B39C40068EC3F /* libsecurityd_bridge */;
+ targetProxy = 6C14CA0323C4F6830097B572 /* PBXContainerItemProxy */;
};
- 6C9808311E788AEB00E70590 /* PBXTargetDependency */ = {
+ 6C16258123C4FFC40086A0FF /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
- target = DC0BCC211D8C684F00070CB0 /* utilities */;
- targetProxy = 6C9808321E788AEB00E70590 /* PBXContainerItemProxy */;
+ target = D4ADA3181E2B41670031CEA3 /* libtrustd */;
+ targetProxy = 6C16258023C4FFC40086A0FF /* PBXContainerItemProxy */;
};
- 6C9808351E788AEB00E70590 /* PBXTargetDependency */ = {
+ 6C16258423C4FFD40086A0FF /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = DCD8A1061E09EE0F00E4FA0A /* SecureObjectSyncFramework */;
- targetProxy = 6C9808361E788AEB00E70590 /* PBXContainerItemProxy */;
+ targetProxy = 6C16258323C4FFD40086A0FF /* PBXContainerItemProxy */;
};
- 6C9808371E788AEB00E70590 /* PBXTargetDependency */ = {
+ 6C16258623C4FFD40086A0FF /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = DC52E8BE1D80C25800B0A59C /* SecureObjectSyncServer */;
- targetProxy = 6C9808381E788AEB00E70590 /* PBXContainerItemProxy */;
+ targetProxy = 6C16258523C4FFD40086A0FF /* PBXContainerItemProxy */;
};
- 6C9808391E788AEB00E70590 /* PBXTargetDependency */ = {
+ 6C2045F82424BC4400F9461D /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
- target = DCC78EA81D8088E200865A7C /* security */;
- targetProxy = 6C98083A1E788AEB00E70590 /* PBXContainerItemProxy */;
+ target = 6C2045E92424BA7E00F9461D /* KeychainStasher */;
+ targetProxy = 6C2045F72424BC4400F9461D /* PBXContainerItemProxy */;
};
- 6C98086B1E788AFD00E70590 /* PBXTargetDependency */ = {
+ 6C2D797322C06CEB00C3CE32 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
- target = DC8834011D8A218F00CE0ACA /* ASN1 */;
- targetProxy = 6C98086C1E788AFD00E70590 /* PBXContainerItemProxy */;
+ target = 6C39234421F13E4D00D018AD /* SecDbBackupTests */;
+ targetProxy = 6C2D797222C06CEB00C3CE32 /* PBXContainerItemProxy */;
};
- 6C98086D1E788AFD00E70590 /* PBXTargetDependency */ = {
+ 6C2D797522C06CEF00C3CE32 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
- target = DC0BCC211D8C684F00070CB0 /* utilities */;
- targetProxy = 6C98086E1E788AFD00E70590 /* PBXContainerItemProxy */;
+ target = 4727FBB61F9918580003AE36 /* secdxctests */;
+ targetProxy = 6C2D797422C06CEF00C3CE32 /* PBXContainerItemProxy */;
};
- 6C9808711E788AFD00E70590 /* PBXTargetDependency */ = {
+ 6C4AA1AA2228B640006FA945 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
- target = DCD8A1061E09EE0F00E4FA0A /* SecureObjectSyncFramework */;
- targetProxy = 6C9808721E788AFD00E70590 /* PBXContainerItemProxy */;
+ target = EB9C1DAE1BDFD4DE00F89272 /* SecurityBatsTests */;
+ targetProxy = 6C4AA1A92228B640006FA945 /* PBXContainerItemProxy */;
};
- 6C9808731E788AFD00E70590 /* PBXTargetDependency */ = {
+ 6C61D3E8242A29BA008AB9BB /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
- target = DC52E8BE1D80C25800B0A59C /* SecureObjectSyncServer */;
- targetProxy = 6C9808741E788AFD00E70590 /* PBXContainerItemProxy */;
+ target = 6C963280242A279B00C53CE2 /* stashtester */;
+ targetProxy = 6C61D3E7242A29BA008AB9BB /* PBXContainerItemProxy */;
};
- 6C9808751E788AFD00E70590 /* PBXTargetDependency */ = {
+ 6C7BE2AA23C3DD64003BB2CA /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
- target = DCC78EA81D8088E200865A7C /* security */;
- targetProxy = 6C9808761E788AFD00E70590 /* PBXContainerItemProxy */;
+ target = DCDA5E4F2124B9C5009B11B2 /* aks_support */;
+ targetProxy = 6C7BE2AB23C3DD64003BB2CA /* PBXContainerItemProxy */;
};
- 6C9808A01E788B9400E70590 /* PBXTargetDependency */ = {
+ 6C7BE2AC23C3DD64003BB2CA /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
- target = 6CF4A0B31E45488B00ECD7B5 /* KeychainEntitledTestApp_mac */;
- targetProxy = 6C98089F1E788B9400E70590 /* PBXContainerItemProxy */;
+ target = DC0BCC211D8C684F00070CB0 /* utilities */;
+ targetProxy = 6C7BE2AD23C3DD64003BB2CA /* PBXContainerItemProxy */;
};
- 6C9808A41E788CB100E70590 /* PBXTargetDependency */ = {
+ 6C7BE2EA23C3DD9C003BB2CA /* 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 */;
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 */;
target = 6CCDF7831E3C25FA003F2555 /* KeychainEntitledTestRunner */;
targetProxy = D45D8F812224DBE300D6C124 /* PBXContainerItemProxy */;
};
- D45D8F842224DBEF00D6C124 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 6C9808681E788AFD00E70590 /* CKKSCloudKitTests_ios */;
- targetProxy = D45D8F832224DBEF00D6C124 /* PBXContainerItemProxy */;
- };
D45D8F862224DBF800D6C124 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = DC3502B41E0208BE00BC0587 /* CKKSTests */;
target = BEF88C2F1EAFFC3F00357577 /* TrustedPeersTests */;
targetProxy = D477EE8021ED48DF00C9AAFF /* PBXContainerItemProxy */;
};
- D477EE8321ED48E800C9AAFF /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 478D426C1FD72A8100CAB645 /* secdxctests_mac */;
- targetProxy = D477EE8221ED48E800C9AAFF /* PBXContainerItemProxy */;
- };
D4794E6B21222E72007C6725 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = DC8834011D8A218F00CE0ACA /* ASN1 */;
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 */;
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 */;
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 */;
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 */;
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 */;
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 */;
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 */;
target = DCDA5E4F2124B9C5009B11B2 /* aks_support */;
targetProxy = DCDA5E632124BCA9009B11B2 /* PBXContainerItemProxy */;
};
+ DCE27861245B81BD00381FE8 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4771D971209A755800BA9772 /* KeychainDataclassOwner */;
+ targetProxy = DCE27860245B81BD00381FE8 /* PBXContainerItemProxy */;
+ };
DCE4E8D81D7F37F200AFB96E /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = DCE4E8931D7F34F600AFB96E /* authd */;
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 */;
"$(OTHER_LDFLAGS_IMG4DECODE)",
"$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)",
"$(OTHER_LDFLAGS_FOR_SECURITYD)",
+ "$(OTHER_LDFLAGS_MSUDATAACCESSOR)",
);
PRODUCT_NAME = secdtests;
STRIP_STYLE = debugging;
"$(OTHER_LDFLAGS_IMG4DECODE)",
"$(OTHER_LDFLAGS_SHAREDWEBCREDENTIALS)",
"$(OTHER_LDFLAGS_FOR_SECURITYD)",
+ "$(OTHER_LDFLAGS_MSUDATAACCESSOR)",
);
PRODUCT_NAME = secdtests;
STRIP_STYLE = debugging;
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;
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_OBJC_ROOT_CLASS = YES_ERROR;
- CLANG_WARN_UNREACHABLE_CODE = YES;
- CODE_SIGN_IDENTITY = "";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 0CA378E523876DD100090B7E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 0CCC227723F357EE00E1FCD0 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 725D438D212CAA3B007B49E4 /* xcconfig/swift_binary_shim.xcconfig */;
+ buildSettings = {
+ 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",
+ /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Frameworks,
);
- "LD_RUNPATH_SEARCH_PATHS[sdk=iphonesimulator*]" = (
+ "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = (
"$(inherited)",
- "@executable_path/../Frameworks",
- "@loader_path/../Frameworks",
+ /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Versions/A/Frameworks,
);
- "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = (
+ LIBRARY_SEARCH_PATHS = (
"$(inherited)",
- "@executable_path/../Frameworks",
- "@loader_path/../Frameworks",
+ "$(SDKROOT)/usr/local/lib/security_libDER",
);
- 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)",
"$(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;
};
- 0C9AEEB620783FBB00BF6237 /* 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",
+ /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Frameworks,
);
- "LD_RUNPATH_SEARCH_PATHS[sdk=iphonesimulator*]" = (
+ "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = (
"$(inherited)",
- "@executable_path/../Frameworks",
- "@loader_path/../Frameworks",
+ /AppleInternal/CoreOS/BATS/unit_tests/Frameworks/OCMockUmbrella.framework/Versions/A/Frameworks,
);
- "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = (
+ LIBRARY_SEARCH_PATHS = (
"$(inherited)",
- "@executable_path/../Frameworks",
- "@loader_path/../Frameworks",
+ "$(SDKROOT)/usr/local/lib/security_libDER",
);
- 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)",
"$(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;
- PRODUCT_NAME = "$(TARGET_NAME)";
- USE_XCTRUNNER = YES;
- VALIDATE_PRODUCT = YES;
- };
- name = Release;
- };
- 0CA378E423876DD100090B7E /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- PRODUCT_NAME = "$(TARGET_NAME)";
- };
- name = Debug;
- };
- 0CA378E523876DD100090B7E /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
+ OTHER_SWIFT_FLAGS = "";
+ PRODUCT_BUNDLE_IDENTIFIER = com.apple.OctagonTrustTests;
PRODUCT_NAME = "$(TARGET_NAME)";
+ SKIP_INSTALL = NO;
+ SWIFT_OBJC_BRIDGING_HEADER = "";
+ SWIFT_OBJC_INTERFACE_HEADER_NAME = "";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = "";
};
name = Release;
};
- 0CF4064E2072E3E3003D6A7F /* Debug */ = {
+ 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_IDENTITY = "";
- GCC_PREPROCESSOR_DEFINITIONS = (
- "NO_SERVER=1",
- "$(inherited)",
- );
+ 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;
- 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;
+ 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_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)",
+ "$(OTHER_LDFLAGS_UPWARD_PROTOCOLBUFFER)",
+ "$(OTHER_LDFLAGS_UPWARD_FOUNDATION)",
);
- PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.SFTMTests;
- PRODUCT_NAME = "$(TARGET_NAME)";
- USE_XCTRUNNER = YES;
+ 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;
};
- 0CF4064F2072E3E3003D6A7F /* Release */ = {
+ 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_IDENTITY = "";
- GCC_PREPROCESSOR_DEFINITIONS = (
- "NO_SERVER=1",
- "$(inherited)",
- );
+ 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;
- 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",
- );
+ 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_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)",
+ "$(OTHER_LDFLAGS_UPWARD_PROTOCOLBUFFER)",
+ "$(OTHER_LDFLAGS_UPWARD_FOUNDATION)",
);
- PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.SFTMTests;
- PRODUCT_NAME = "$(TARGET_NAME)";
- USE_XCTRUNNER = YES;
+ 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;
};
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;
"-Wglobal-constructors",
"-Wmost",
"-Wno-four-char-constants",
- "-Wno-unknown-pragmas",
"$(inherited)",
- "-Wno-error=c++11-narrowing",
);
};
name = Debug;
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;
"-Wglobal-constructors",
"-Wmost",
"-Wno-four-char-constants",
- "-Wno-unknown-pragmas",
"$(inherited)",
- "-Wno-error=c++11-narrowing",
);
};
name = Release;
};
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 = {
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;
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;
);
PRODUCT_NAME = securityd;
STRIP_STYLE = debugging;
- WARNING_CFLAGS = (
- "$(inherited)",
- "-Wno-error=modules-ambiguous-internal-linkage",
- );
+ WARNING_CFLAGS = "$(inherited)";
};
name = Debug;
};
);
PRODUCT_NAME = securityd;
STRIP_STYLE = debugging;
- WARNING_CFLAGS = (
- "$(inherited)",
- "-Wno-error=modules-ambiguous-internal-linkage",
- );
+ WARNING_CFLAGS = "$(inherited)";
};
name = Release;
};
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;
"$(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)",
);
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;
"$(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)",
);
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;
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;
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;
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;
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_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;
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_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;
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_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_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;
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;
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;
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;
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;
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",
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;
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)",
"$(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;
"$(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;
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;
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;
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;
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 = (
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;
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";
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;
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;
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;
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;
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;
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",
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;
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;
};
name = Release;
};
- 6C39237721F13E4D00D018AD /* Debug */ = {
+ 6C2045EF2424BA7F00F9461D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
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_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;
);
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;
};
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_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;
);
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;
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";
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";
};
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)",
+ "-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)",
- "-framework",
- 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";
+ 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;
};
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;
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;
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;
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;
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;
};
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;
};
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;
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 = {
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;
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;
REEXPORTED_LIBRARY_NAMES = "";
STRIP_STYLE = debugging;
USE_HEADERMAP = NO;
- WARNING_CFLAGS = (
- "$(inherited)",
- "-Wno-error=modules-ambiguous-internal-linkage",
- );
+ WARNING_CFLAGS = "$(inherited)";
};
name = Debug;
};
REEXPORTED_LIBRARY_NAMES = "";
STRIP_STYLE = debugging;
USE_HEADERMAP = NO;
- WARNING_CFLAGS = (
- "$(inherited)",
- "-Wno-error=modules-ambiguous-internal-linkage",
- );
+ WARNING_CFLAGS = "$(inherited)";
};
name = Release;
};
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;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
- CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
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;
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 = (
"$(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;
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";
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;
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;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
- CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
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;
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 = (
"$(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;
"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";
"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 = "";
baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_WARN_SUSPICIOUS_MOVES = YES;
- GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_PREPROCESSOR_DEFINITIONS = (
COM_APPLE_SECURITY_SANE_INCLUDES,
"$(inherited)",
baseConfigurationReference = DC0067911D87816C005AF8DB /* macos_legacy_lib.xcconfig */;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_WARN_SUSPICIOUS_MOVES = YES;
- GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_PREPROCESSOR_DEFINITIONS = (
COM_APPLE_SECURITY_SANE_INCLUDES,
"$(inherited)",
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;
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";
"$(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;
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;
"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;
"$(SDKROOT)/usr/local/lib/security_libDER",
);
OTHER_LDFLAGS = (
- "$(OTHER_LDFLAGS_AKS_LIBRARY)",
"$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)",
"$(OTHER_LDFLAGS_PROTOBUF)",
"$(OTHER_LDFLAGS_MOBILEGESTALT)",
"$(OTHER_LDFLAGS_FOR_SECURITYD)",
"-framework",
Security,
+ "$(OTHER_LDFLAGS_MOCK_AKS_LIBRARY)",
);
PRODUCT_BUNDLE_IDENTIFIER = com.apple.TrustedPeersHelperUnitTests;
PRODUCT_NAME = "$(TARGET_NAME)";
"$(SDKROOT)/usr/local/lib/security_libDER",
);
OTHER_LDFLAGS = (
- "$(OTHER_LDFLAGS_AKS_LIBRARY)",
"$(OTHER_LDFLAGS_APPLEIDAUTHSUPPORT)",
"$(OTHER_LDFLAGS_PROTOBUF)",
"$(OTHER_LDFLAGS_MOBILEGESTALT)",
"$(OTHER_LDFLAGS_FOR_SECURITYD)",
"-framework",
Security,
+ "$(OTHER_LDFLAGS_MOCK_AKS_LIBRARY)",
);
PRODUCT_BUNDLE_IDENTIFIER = com.apple.TrustedPeersHelperUnitTests;
PRODUCT_NAME = "$(TARGET_NAME)";
};
BEF88C391EAFFC4000357577 /* Debug */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = BE8351D41EC0EEDD00ACD5FD /* framework_requiring_modern_objc_runtime.xcconfig */;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
};
BEF88C3A1EAFFC4000357577 /* Release */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = BE8351D41EC0EEDD00ACD5FD /* framework_requiring_modern_objc_runtime.xcconfig */;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
OTHER_LDFLAGS = (
"$(OTHER_LDFLAGS_MOBILEASSET)",
"$(OTHER_LDFLAGS_IMG4DECODE)",
+ "$(OTHER_LDFLAGS_MSUDATAACCESSOR)",
);
PRODUCT_NAME = trustd;
STRIP_STYLE = debugging;
OTHER_LDFLAGS = (
"$(OTHER_LDFLAGS_MOBILEASSET)",
"$(OTHER_LDFLAGS_IMG4DECODE)",
+ "$(OTHER_LDFLAGS_MSUDATAACCESSOR)",
);
PRODUCT_NAME = trustd;
STRIP_STYLE = debugging;
OTHER_LDFLAGS = (
"$(OTHER_LDFLAGS_MOBILEASSET)",
"$(OTHER_LDFLAGS_IMG4DECODE)",
+ "$(OTHER_LDFLAGS_MSUDATAACCESSOR)",
);
PRODUCT_BUNDLE_IDENTIFIER = com.apple.TrustTests;
PRODUCT_NAME = TrustTests;
OTHER_LDFLAGS = (
"$(OTHER_LDFLAGS_MOBILEASSET)",
"$(OTHER_LDFLAGS_IMG4DECODE)",
+ "$(OTHER_LDFLAGS_MSUDATAACCESSOR)",
);
PRODUCT_BUNDLE_IDENTIFIER = com.apple.TrustTests;
PRODUCT_NAME = TrustTests;
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_OBJC_ROOT_CLASS = YES_ERROR;
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;
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_OBJC_ROOT_CLASS = YES_ERROR;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
+ /Developer/Library/Frameworks,
+ /AppleInternal/Developer/Library/Frameworks,
);
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
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_OBJC_ROOT_CLASS = YES_ERROR;
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;
};
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_OBJC_ROOT_CLASS = YES_ERROR;
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;
"$(OTHER_LDFLAGS_MOBILEASSET)",
"$(OTHER_LDFLAGS_IMG4DECODE)",
"$(OTHER_LDFLAGS_OCMOCK)",
+ "$(OTHER_LDFLAGS_MSUDATAACCESSOR)",
);
PRODUCT_BUNDLE_IDENTIFIER = com.apple.TrustTests;
PRODUCT_NAME = TrustTests;
"$(OTHER_LDFLAGS_MOBILEASSET)",
"$(OTHER_LDFLAGS_IMG4DECODE)",
"$(OTHER_LDFLAGS_OCMOCK)",
+ "$(OTHER_LDFLAGS_MSUDATAACCESSOR)",
);
PRODUCT_BUNDLE_IDENTIFIER = com.apple.TrustTests;
PRODUCT_NAME = TrustTests;
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;
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 = (
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;
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;
CLANG_ANALYZER_NONNULL = 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)";
};
CLANG_ANALYZER_NONNULL = 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)";
};
};
DC0BC9CD1D8B824700070CB0 /* Debug */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = D47C56FB1DCA8F4900E18518 /* all_arches.xcconfig */;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_WARN_ENUM_CONVERSION = NO;
};
DC0BC9CE1D8B824700070CB0 /* Release */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = D47C56FB1DCA8F4900E18518 /* all_arches.xcconfig */;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_WARN_ENUM_CONVERSION = NO;
SKIP_INSTALL = YES;
WARNING_CFLAGS = (
"$(inherited)",
- "-Wno-int-to-void-pointer-cast",
"-Wno-sign-compare",
);
};
SKIP_INSTALL = YES;
WARNING_CFLAGS = (
"$(inherited)",
- "-Wno-int-to-void-pointer-cast",
"-Wno-sign-compare",
);
};
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)",
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)",
};
DC0BCC341D8C684F00070CB0 /* Debug */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = D47C56FB1DCA8F4900E18518 /* all_arches.xcconfig */;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ENABLE_OBJC_ARC = YES;
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;
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;
};
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;
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;
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;
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;
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;
};
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;
};
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;
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;
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;
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;
"$(OTHER_LDFLAGS_IMCORE)",
"$(OTHER_LDFLAGS_MOBILE_KEYBAG)",
"$(OTHER_LDFLAGS_FOR_SECURITYD)",
+ "$(OTHER_LDFLAGS_IMG4DECODE)",
+ "$(OTHER_LDFLAGS_MSUDATAACCESSOR)",
);
PRODUCT_NAME = secdtests;
STRIP_STYLE = debugging;
"$(OTHER_LDFLAGS_IMCORE)",
"$(OTHER_LDFLAGS_MOBILE_KEYBAG)",
"$(OTHER_LDFLAGS_FOR_SECURITYD)",
+ "$(OTHER_LDFLAGS_IMG4DECODE)",
+ "$(OTHER_LDFLAGS_MSUDATAACCESSOR)",
);
PRODUCT_NAME = secdtests;
STRIP_STYLE = debugging;
};
DC8834061D8A218F00CE0ACA /* Debug */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = D47C56FB1DCA8F4900E18518 /* all_arches.xcconfig */;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ENABLE_MODULES = NO;
};
DC8834071D8A218F00CE0ACA /* Release */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = D47C56FB1DCA8F4900E18518 /* all_arches.xcconfig */;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ENABLE_MODULES = NO;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)";
MTL_ENABLE_DEBUG_INFO = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
- WARNING_CFLAGS = (
- "$(inherited)",
- "-Wno-switch",
- );
+ WARNING_CFLAGS = "$(inherited)";
};
name = Debug;
};
GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)";
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_NAME = "$(TARGET_NAME)";
- WARNING_CFLAGS = (
- "$(inherited)",
- "-Wno-switch",
- );
+ WARNING_CFLAGS = "$(inherited)";
};
name = Release;
};
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 = (
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;
};
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 = (
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;
};
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;
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;
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;
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;
WARNING_CFLAGS = (
"$(inherited)",
"-Wno-sign-compare",
- "-Wno-deprecated-register",
);
};
name = Debug;
WARNING_CFLAGS = (
"$(inherited)",
"-Wno-sign-compare",
- "-Wno-deprecated-register",
);
};
name = Release;
"$(OTHER_LDFLAGS_FOR_SECURITYD)",
);
PRODUCT_NAME = "$(TARGET_NAME)";
- WARNING_CFLAGS = (
- "$(inherited)",
- "-Wno-error=modules-ambiguous-internal-linkage",
- );
+ WARNING_CFLAGS = "$(inherited)";
};
name = Debug;
};
"$(OTHER_LDFLAGS_FOR_SECURITYD)",
);
PRODUCT_NAME = "$(TARGET_NAME)";
- WARNING_CFLAGS = (
- "$(inherited)",
- "-Wno-error=modules-ambiguous-internal-linkage",
- );
+ WARNING_CFLAGS = "$(inherited)";
};
name = Release;
};
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;
};
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;
};
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;
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;
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;
};
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;
};
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;
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;
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;
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;
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__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 = (
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;
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;
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;
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;
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;
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;
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;
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;
"$(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)";
"$(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)";
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 = (
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)",
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;
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",
TAPI_VERIFY_MODE = ErrorsOnly;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
- WARNING_CFLAGS = "-Wno-objc-designated-initializers";
+ WARNING_CFLAGS = "$(inherited)";
};
name = Debug;
};
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;
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;
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;
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;
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;
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;
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;
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 = (
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;
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;
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;
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;
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;
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;
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;
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;
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;
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";
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;
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;
PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.KeychainCircle.KeychainCircleTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTS_TEXT_BASED_API = YES;
+ TEST_BUILD_STYLE = _APPLEINTERNAL;
};
name = Debug;
};
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;
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;
PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.KeychainCircle.KeychainCircleTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTS_TEXT_BASED_API = YES;
+ TEST_BUILD_STYLE = _APPLEINTERNAL;
};
name = Release;
};
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;
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;
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;
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 = (
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;
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;
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;
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 = (
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;
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;
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;
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 = (
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;
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;
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;
"-framework",
Security,
"$(OTHER_LDFLAGS_FOR_SECURITYD)",
+ "$(OTHER_LDFLAGS_MOCK_AKS_LIBRARY)",
);
PRODUCT_BUNDLE_IDENTIFIER = com.apple.Security.secdmockaks;
PRODUCT_NAME = "$(TARGET_NAME)";
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;
"-framework",
Security,
"$(OTHER_LDFLAGS_FOR_SECURITYD)",
+ "$(OTHER_LDFLAGS_MOCK_AKS_LIBRARY)",
);
PRODUCT_BUNDLE_IDENTIFIER = com.apple.Security.secdmockaks;
PRODUCT_NAME = "$(TARGET_NAME)";
REEXPORTED_LIBRARY_NAMES = "";
STRIP_STYLE = debugging;
USE_HEADERMAP = YES;
- WARNING_CFLAGS = (
- "$(inherited)",
- "-Wno-error=modules-ambiguous-internal-linkage",
- );
+ WARNING_CFLAGS = "$(inherited)";
};
name = Debug;
};
REEXPORTED_LIBRARY_NAMES = "";
STRIP_STYLE = debugging;
USE_HEADERMAP = YES;
- WARNING_CFLAGS = (
- "$(inherited)",
- "-Wno-error=modules-ambiguous-internal-linkage",
- );
+ WARNING_CFLAGS = "$(inherited)";
};
name = Release;
};
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_OBJC_ROOT_CLASS = YES_ERROR;
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_OBJC_ROOT_CLASS = YES_ERROR;
REEXPORTED_LIBRARY_NAMES = "";
STRIP_STYLE = debugging;
USE_HEADERMAP = YES;
- WARNING_CFLAGS = (
- "$(inherited)",
- "-Wno-error=modules-ambiguous-internal-linkage",
- );
+ WARNING_CFLAGS = "$(inherited)";
};
name = Debug;
};
REEXPORTED_LIBRARY_NAMES = "";
STRIP_STYLE = debugging;
USE_HEADERMAP = YES;
- WARNING_CFLAGS = (
- "$(inherited)",
- "-Wno-error=modules-ambiguous-internal-linkage",
- );
+ WARNING_CFLAGS = "$(inherited)";
};
name = Release;
};
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;
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 = (
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;
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;
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;
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 = (
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;
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;
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)";
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;
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;
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 = (
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;
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;
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_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;
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_OBJC_ROOT_CLASS = YES_ERROR;
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;
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;
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;
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;
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;
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;
};
- 0CA378E323876DD100090B7E /* Build configuration list for PBXAggregateTarget "reset_account" */ = {
+ 0CCC227623F357EE00E1FCD0 /* Build configuration list for PBXNativeTarget "OctagonTrustTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- 0CA378E423876DD100090B7E /* Debug */,
- 0CA378E523876DD100090B7E /* Release */,
+ 0CCC227723F357EE00E1FCD0 /* Debug */,
+ 0CCC227823F357EE00E1FCD0 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- 0CF4064D2072E3E3003D6A7F /* Build configuration list for PBXNativeTarget "SignInAnalyticsTests_ios" */ = {
+ 0CD743AB23C3EC8000FA0EC5 /* Build configuration list for PBXNativeTarget "OctagonTrust" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- 0CF4064E2072E3E3003D6A7F /* Debug */,
- 0CF4064F2072E3E3003D6A7F /* Release */,
+ 0CD743AC23C3EC8000FA0EC5 /* Debug */,
+ 0CD743AD23C3EC8000FA0EC5 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = 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 = (
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- 4727FBC31F9918590003AE36 /* Build configuration list for PBXNativeTarget "secdxctests_ios" */ = {
+ 4727FBC31F9918590003AE36 /* Build configuration list for PBXNativeTarget "secdxctests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
4727FBBC1F9918590003AE36 /* Debug */,
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 = (
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 = (
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;
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- 6CF4A0CC1E45488B00ECD7B5 /* Build configuration list for PBXNativeTarget "KeychainEntitledTestApp_mac" */ = {
+ 6CF4A0CC1E45488B00ECD7B5 /* Build configuration list for PBXNativeTarget "KeychainEntitledTestApp" */ = {
isa = XCConfigurationList;
buildConfigurations = (
6CF4A0C51E45488B00ECD7B5 /* Debug */,
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 = (
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "1120"
+ LastUpgradeVersion = "1200"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "1120"
+ LastUpgradeVersion = "1200"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "1200"
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "NO"
+ buildImplicitDependencies = "NO">
+ </BuildAction>
+ <TestAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES">
+ <TestPlans>
+ <TestPlanReference
+ reference = "container:OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransportTests_ios.xctestplan"
+ default = "YES">
+ </TestPlanReference>
+ </TestPlans>
+ <Testables>
+ <TestableReference
+ skipped = "NO">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "3DD1FFAC201FDB1D0086D049"
+ BuildableName = "SecureTransport_ios_tests.xctest"
+ BlueprintName = "SecureTransportTests_ios"
+ ReferencedContainer = "container:Security.xcodeproj">
+ </BuildableReference>
+ </TestableReference>
+ </Testables>
+ </TestAction>
+ <LaunchAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ </LaunchAction>
+ <ProfileAction
+ buildConfiguration = "Release"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ debugDocumentVersioning = "YES">
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "1200"
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "NO"
+ buildImplicitDependencies = "NO">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "NO"
+ buildForArchiving = "NO"
+ buildForAnalyzing = "NO">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "3DD1FEF5201C07F30086D049"
+ BuildableName = "SecureTransport_macos_tests.xctest"
+ BlueprintName = "SecureTransportTests_macos"
+ ReferencedContainer = "container:Security.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES">
+ <TestPlans>
+ <TestPlanReference
+ reference = "container:OSX/libsecurity_ssl/regressions/SecureTransportTests/SecureTransportTests_macos.xctestplan"
+ default = "YES">
+ </TestPlanReference>
+ </TestPlans>
+ <Testables>
+ <TestableReference
+ skipped = "NO">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "3DD1FEF5201C07F30086D049"
+ BuildableName = "SecureTransport_macos_tests.xctest"
+ BlueprintName = "SecureTransportTests_macos"
+ ReferencedContainer = "container:Security.xcodeproj">
+ </BuildableReference>
+ </TestableReference>
+ </Testables>
+ </TestAction>
+ <LaunchAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ </LaunchAction>
+ <ProfileAction
+ buildConfiguration = "Release"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ debugDocumentVersioning = "YES">
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "1120"
+ LastUpgradeVersion = "1200"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "YES"
onlyGenerateCoverageForSpecifiedTargets = "YES">
- <MacroExpansion>
- <BuildableReference
- BuildableIdentifier = "primary"
- BlueprintIdentifier = "D4707A0421136E69005BCFDA"
- BuildableName = "TrustTests.xctest"
- BlueprintName = "TrustTests_ios"
- ReferencedContainer = "container:Security.xcodeproj">
- </BuildableReference>
- </MacroExpansion>
<CodeCoverageTargets>
<BuildableReference
BuildableIdentifier = "primary"
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "1120"
+ LastUpgradeVersion = "1200"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "YES"
onlyGenerateCoverageForSpecifiedTargets = "YES">
- <MacroExpansion>
- <BuildableReference
- BuildableIdentifier = "primary"
- BlueprintIdentifier = "D453A4A42122236D00850A26"
- BuildableName = "TrustTests.xctest"
- BlueprintName = "TrustTests_macos"
- ReferencedContainer = "container:Security.xcodeproj">
- </BuildableReference>
- </MacroExpansion>
<CodeCoverageTargets>
<BuildableReference
BuildableIdentifier = "primary"
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "1120"
+ LastUpgradeVersion = "1200"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "YES">
- <MacroExpansion>
- <BuildableReference
- BuildableIdentifier = "primary"
- BlueprintIdentifier = "BEF88C271EAFFC3F00357577"
- BuildableName = "TrustedPeers.framework"
- BlueprintName = "TrustedPeers"
- ReferencedContainer = "container:Security.xcodeproj">
- </BuildableReference>
- </MacroExpansion>
<Testables>
<TestableReference
skipped = "NO">
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "1120"
+ LastUpgradeVersion = "1200"
version = "1.8">
<BuildAction
parallelizeBuildables = "NO"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
- <MacroExpansion>
- <BuildableReference
- BuildableIdentifier = "primary"
- BlueprintIdentifier = "4C711D5813AFCD0900FE865D"
- BuildableName = "SecurityDevTests.app"
- BlueprintName = "SecurityDevTests"
- ReferencedContainer = "container:Security.xcodeproj">
- </BuildableReference>
- </MacroExpansion>
<Testables>
<TestableReference
skipped = "NO">
ReferencedContainer = "container:Security.xcodeproj">
</BuildableReference>
</TestableReference>
- <TestableReference
- skipped = "NO">
- <BuildableReference
- BuildableIdentifier = "primary"
- BlueprintIdentifier = "4727FBB61F9918580003AE36"
- BuildableName = "secdxctests_ios.xctest"
- BlueprintName = "secdxctests_ios"
- ReferencedContainer = "container:Security.xcodeproj">
- </BuildableReference>
- </TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
argument = "si_22_sectrust_iap"
isEnabled = "NO">
</CommandLineArgument>
- <CommandLineArgument
- argument = "si_23_sectrust_ocsp"
- isEnabled = "NO">
- </CommandLineArgument>
<CommandLineArgument
argument = "si_24_sectrust_itms"
isEnabled = "NO">
argument = "si_26_sectrust_copyproperties"
isEnabled = "NO">
</CommandLineArgument>
- <CommandLineArgument
- argument = "si_28_sectrustsettings"
- isEnabled = "NO">
- </CommandLineArgument>
<CommandLineArgument
argument = "si_29_cms_chain_mode"
isEnabled = "NO">
argument = "si_66_smime"
isEnabled = "NO">
</CommandLineArgument>
- <CommandLineArgument
- argument = "si_67_sectrust_blocklist"
- isEnabled = "NO">
- </CommandLineArgument>
<CommandLineArgument
argument = "si_68_secmatchissuer"
isEnabled = "NO">
argument = "si_73_secpasswordgenerate"
isEnabled = "NO">
</CommandLineArgument>
- <CommandLineArgument
- argument = "si_74_OTA_PKI_Signer"
- isEnabled = "NO">
- </CommandLineArgument>
<CommandLineArgument
argument = "si_76_shared_credentials"
isEnabled = "NO">
argument = "si_83_seccertificate_sighashalg"
isEnabled = "NO">
</CommandLineArgument>
- <CommandLineArgument
- argument = "si_84_sectrust_allowlist"
- isEnabled = "NO">
- </CommandLineArgument>
- <CommandLineArgument
- argument = "si_88_sectrust_valid"
- isEnabled = "NO">
- </CommandLineArgument>
<CommandLineArgument
argument = "si_89_cms_hash_agility"
isEnabled = "NO">
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "1120"
+ LastUpgradeVersion = "1200"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
- <MacroExpansion>
- <BuildableReference
- BuildableIdentifier = "primary"
- BlueprintIdentifier = "E710C7411331946400F85568"
- BuildableName = "SecurityTests.app"
- BlueprintName = "SecurityTests"
- ReferencedContainer = "container:Security.xcodeproj">
- </BuildableReference>
- </MacroExpansion>
<Testables>
<TestableReference
skipped = "NO">
argument = "si_22_sectrust_iap"
isEnabled = "NO">
</CommandLineArgument>
- <CommandLineArgument
- argument = "si_23_sectrust_ocsp"
- isEnabled = "NO">
- </CommandLineArgument>
<CommandLineArgument
argument = "si-23-sectrust-ocsp-wwdr"
isEnabled = "NO">
argument = "si_26_sectrust_copyproperties"
isEnabled = "NO">
</CommandLineArgument>
- <CommandLineArgument
- argument = "si_28_sectrustsettings"
- isEnabled = "NO">
- </CommandLineArgument>
<CommandLineArgument
argument = "si_29_cms_chain_mode"
isEnabled = "NO">
argument = "si_66_smime"
isEnabled = "NO">
</CommandLineArgument>
- <CommandLineArgument
- argument = "si_67_sectrust_blocklist"
- isEnabled = "NO">
- </CommandLineArgument>
<CommandLineArgument
argument = "si_68_secmatchissuer"
isEnabled = "NO">
argument = "si_73_secpasswordgenerate"
isEnabled = "NO">
</CommandLineArgument>
- <CommandLineArgument
- argument = "si_74_OTA_PKI_Signer"
- isEnabled = "NO">
- </CommandLineArgument>
<CommandLineArgument
argument = "si_76_shared_credentials"
isEnabled = "NO">
argument = "si_83_seccertificate_sighashalg"
isEnabled = "NO">
</CommandLineArgument>
- <CommandLineArgument
- argument = "si_84_sectrust_allowlist"
- isEnabled = "NO">
- </CommandLineArgument>
<CommandLineArgument
argument = "si_87_sectrust_name_constraints"
isEnabled = "NO">
</CommandLineArgument>
- <CommandLineArgument
- argument = "si_88_sectrust_valid"
- isEnabled = "NO">
- </CommandLineArgument>
<CommandLineArgument
argument = "si_89_cms_hash_agility"
isEnabled = "NO">
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "1120"
+ LastUpgradeVersion = "1200"
version = "2.0">
<BuildAction
parallelizeBuildables = "NO"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
- <MacroExpansion>
- <BuildableReference
- BuildableIdentifier = "primary"
- BlueprintIdentifier = "0C0BDB2E175685B000BC1A7E"
- BuildableName = "secdtests"
- BlueprintName = "secdtests_ios"
- ReferencedContainer = "container:Security.xcodeproj">
- </BuildableReference>
- </MacroExpansion>
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4727FBB61F9918580003AE36"
- BuildableName = "secdxctests_ios.xctest"
- BlueprintName = "secdxctests_ios"
+ BuildableName = "secdxctests.xctest"
+ BlueprintName = "secdxctests"
ReferencedContainer = "container:Security.xcodeproj">
</BuildableReference>
</TestableReference>
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "1120"
+ LastUpgradeVersion = "1200"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
- <MacroExpansion>
- <BuildableReference
- BuildableIdentifier = "primary"
- BlueprintIdentifier = "DCE4E7311D7A43B500AFB96E"
- BuildableName = "SecurityTestsOSX.app"
- BlueprintName = "SecurityTestsOSX"
- ReferencedContainer = "container:Security.xcodeproj">
- </BuildableReference>
- </MacroExpansion>
<Testables>
<TestableReference
skipped = "NO">
ReferencedContainer = "container:Security.xcodeproj">
</BuildableReference>
</TestableReference>
- <TestableReference
- skipped = "NO">
- <BuildableReference
- BuildableIdentifier = "primary"
- BlueprintIdentifier = "478D426C1FD72A8100CAB645"
- BuildableName = "secdxctests_mac.xctest"
- BlueprintName = "secdxctests_mac"
- ReferencedContainer = "container:Security.xcodeproj">
- </BuildableReference>
- </TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
ReferencedContainer = "container:Security.xcodeproj">
</BuildableReference>
</TestableReference>
+ <TestableReference
+ skipped = "NO">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "4727FBB61F9918580003AE36"
+ BuildableName = "secdxctests.xctest"
+ BlueprintName = "secdxctests"
+ ReferencedContainer = "container:Security.xcodeproj">
+ </BuildableReference>
+ </TestableReference>
</Testables>
</TestAction>
<LaunchAction
argument = "smime_cms_test"
isEnabled = "NO">
</CommandLineArgument>
- <CommandLineArgument
- argument = "bc_10_password"
- isEnabled = "NO">
- </CommandLineArgument>
<CommandLineArgument
argument = "kc_40_seckey"
isEnabled = "NO">
argument = "si_22_sectrust_iap"
isEnabled = "NO">
</CommandLineArgument>
- <CommandLineArgument
- argument = "si_23_sectrust_ocsp"
- isEnabled = "NO">
- </CommandLineArgument>
<CommandLineArgument
argument = "si_24_sectrust_itms"
isEnabled = "NO">
argument = "si_26_sectrust_copyproperties"
isEnabled = "NO">
</CommandLineArgument>
- <CommandLineArgument
- argument = "si_28_sectrustsettings"
- isEnabled = "NO">
- </CommandLineArgument>
<CommandLineArgument
argument = "si_29_cms_chain_mode"
isEnabled = "NO">
argument = "si_68_secmatchissuer"
isEnabled = "NO">
</CommandLineArgument>
- <CommandLineArgument
- argument = "si_67_sectrust_blocklist"
- isEnabled = "NO">
- </CommandLineArgument>
<CommandLineArgument
argument = "si_70_sectrust_unified"
isEnabled = "NO">
argument = "si_71_mobile_store_policy"
isEnabled = "NO">
</CommandLineArgument>
- <CommandLineArgument
- argument = "si_74_OTA_PKI_Signer"
- isEnabled = "NO">
- </CommandLineArgument>
<CommandLineArgument
argument = "si_83_seccertificate_sighashalg"
isEnabled = "NO">
</CommandLineArgument>
- <CommandLineArgument
- argument = "si_84_sectrust_allowlist"
- isEnabled = "NO">
- </CommandLineArgument>
- <CommandLineArgument
- argument = "si_88_sectrust_valid"
- isEnabled = "NO">
- </CommandLineArgument>
<CommandLineArgument
argument = "si_89_cms_hash_agility"
isEnabled = "NO">
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "1120"
+ LastUpgradeVersion = "1200"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
- <MacroExpansion>
- <BuildableReference
- BuildableIdentifier = "primary"
- BlueprintIdentifier = "DC610A021D78F129002223DE"
- BuildableName = "secdtests"
- BlueprintName = "secdtests_macos"
- ReferencedContainer = "container:Security.xcodeproj">
- </BuildableReference>
- </MacroExpansion>
<Testables>
<TestableReference
skipped = "NO">
argument = "secd_61_account_leave_not_in_kansas_anymore"
isEnabled = "NO">
</CommandLineArgument>
+ <CommandLineArgument
+ argument = "secd_68_fullPeerInfoIntegrity"
+ isEnabled = "NO">
+ </CommandLineArgument>
<CommandLineArgument
argument = "secd_70_engine"
isEnabled = "NO">
argument = "secd_71_engine_save"
isEnabled = "NO">
</CommandLineArgument>
+ <CommandLineArgument
+ argument = "secd_74_engine_beer_servers"
+ isEnabled = "NO">
+ </CommandLineArgument>
<CommandLineArgument
argument = "secd_76_idstransport"
isEnabled = "NO">
isEnabled = "NO">
</CommandLineArgument>
</CommandLineArguments>
+ <EnvironmentVariables>
+ <EnvironmentVariable
+ key = ""
+ value = ""
+ isEnabled = "YES">
+ </EnvironmentVariable>
+ <EnvironmentVariable
+ key = ""
+ value = ""
+ isEnabled = "YES">
+ </EnvironmentVariable>
+ </EnvironmentVariables>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "1120"
+ LastUpgradeVersion = "1200"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
- <MacroExpansion>
- <BuildableReference
- BuildableIdentifier = "primary"
- BlueprintIdentifier = "DCE4E7CB1D7A4AED00AFB96E"
- BuildableName = "sectests"
- BlueprintName = "sectests_macos"
- ReferencedContainer = "container:Security.xcodeproj">
- </BuildableReference>
- </MacroExpansion>
<Testables>
</Testables>
</TestAction>
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "1120"
+ LastUpgradeVersion = "1200"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
<string>123456.test.group</string>
<string>123456.test.group2</string>
<string>com.apple.bluetooth</string>
+ <string>com.apple.token</string>
</array>
<key>com.apple.developer.associated-domains</key>
<array>
<string>webcredentials:localhost</string>
</array>
+ <key>com.apple.private.security.storage.Keychains</key>
+ <true/>
</dict>
</plist>
retval = (status ? -1 : 0);
bail:
- if (rights)
+ if (rights) {
free(rights);
-
- return retval;
+ }
+
+ return retval;
}
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;
}
// 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,
return SHOW_USAGE_MESSAGE;
keychainName = (argc == 1)?*argv:_masterKeychainName;
- if (!keychainName || *keychainName == '\0')
+ if (!keychainName || *keychainName == '\0') {
return -1;
+ }
if (!password && !do_prompt)
{
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);
safe_CFRelease(&idStr);
safe_CFRelease(&policy);
- safe_CFRelease(policySearch);
+ safe_CFRelease(&policySearch);
}
static void
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
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
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;
}
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)) {
do_lock_all(void)
{
OSStatus result = SecKeychainLockAll();
- if (result)
+ if (result) {
sec_perror("SecKeychainLockAll", result);
+ }
- return result;
+ return result;
}
static int
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);
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);
CFDataIncreaseLength(bin, bytes);
if(!bin || (size_t) CFDataGetLength(bin) != bytes) {
+ free(chex);
CFReleaseNull(bin);
return NULL;
}
data[i] = (uint8)(hexValue(chex[2*i]) << 4 | hexValue(chex[2*i+1]));
}
+ free(chex);
return bin;
}
return result;
loser:
- if (fd != -1)
+ if (fd != -1) {
close(fd);
- if (buffer)
- free(buffer);
+ }
+ if (buffer) {
+ free(buffer);
+ }
return result;
}
fprintf(stderr, "parsing requirement failed (%d): %s\n", status, errorStr);
free(errorStr);
+ CFReleaseSafe(errorDesc);
err = 1;
}
}
CFArrayAppendValue(certs, cert);
- CFRelease(cert);
+ CFReleaseSafe(cert);
}
// Evaluate!
- (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;
}
}
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;
}
"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"
" -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.")
/* @@@ 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);
#include "SecurityTool/sharedTool/security_tool_commands.h"
+#include <TargetConditionals.h>
SECURITY_COMMAND("help", help,
"[command ...]",
"",
"Ask securityd who you are.")
+#if !TARGET_OS_BRIDGE
SECURITY_COMMAND("sos-stats", command_sos_stats,
"",
"SOS for performance numbers.")
" check-period <x>\n"
" graceful-exit-time <x>\n",
"Show current watchdog parameters or set an individual parameter")
+#endif
SECURITY_COMMAND("keychain-check", command_keychain_check,
"",
--- /dev/null
+/*
+ * 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 <Foundation/Foundation.h>
+#include <Security/SecTrustSettingsPriv.h>
+#include <Security/SecCertificatePriv.h>
+#include <utilities/fileIo.h>
+#include <utilities/SecCFWrappers.h>
+
+#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<NSDictionary *>*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;
+}
<string>com.apple.security</string>
<key>com.apple.private.keychain.keychaincontrol</key>
<true/>
+ <key>com.apple.private.keychain.inet_expansion_fields</key>
+ <true/>
<key>com.apple.developer.icloud-services</key>
<array>
<string>CloudKit</string>
</array>
<key>com.apple.private.keychain.keychaincontrol</key>
<true/>
+ <key>com.apple.private.keychain.inet_expansion_fields</key>
+ <true/>
<key>com.apple.private.syncbubble-keychain</key>
<true/>
<key>com.apple.private.system-keychain</key>
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);
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<NSDictionary*>* reportedMismatches = [[NSMutableArray<NSDictionary*> alloc] init];
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);
}
(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;
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 <rdar://problem/15010402> 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)
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) {
} 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) {
bool gbinfo = false;
bool gbtriggered = false;
bool circleHash = false;
+ bool triggerRingUpdate = false;
+ bool iCloudIdentityStatus = false;
static struct option long_options[] =
{
/* These options set a flag. */
{"assertStashAccountKey", no_argument, NULL, 'a'},
{"trigger-backup", optional_argument, NULL, 'B'},
+ {"trigger-ring-update", no_argument, NULL, 'R'},
{"trigger-sync", optional_argument, NULL, 's'},
{"circle-hash", optional_argument, NULL, 'H'},
{"ghostbustByMID", optional_argument, NULL, 'M'},
{"ghostbustByAge", optional_argument, NULL, 'A'},
{"ghostbustInfo", optional_argument, NULL, 'G'},
{"ghostbustTriggered", optional_argument, NULL, 'T'},
+ {"icloudIdentityStatus", optional_argument, NULL, 'i'},
{0, 0, 0, 0}
};
- while ((ch = getopt_long(argc, argv, "as:AB:GHMSIT", long_options, &option_index)) != -1) {
+ while ((ch = getopt_long(argc, argv, "as:AB:GHIMRSTi", long_options, &option_index)) != -1) {
switch (ch) {
case 'a': {
assertStashAccountKey = true;
gboptions |= SOSGhostBustByMID;
break;
}
+ case 'R':
+ triggerRingUpdate = true;
+ break;
case 'S': {
gboptions |= SOSGhostBustBySerialNumber;
break;
case 'H':
circleHash = true;
break;
+ case 'i':
+ iCloudIdentityStatus = true;
+ break;
case '?':
default:
{
} else if (triggerSync) {
[[control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) {
printControlFailureMessage(error);
- }] triggerSync:syncingPeers complete:^(bool res, NSError *error) {
+ }] rpcTriggerSync:syncingPeers complete:^(bool res, NSError *error) {
if (res) {
printf("starting to sync was successful\n");
} else {
} else if (triggerBackup) {
[[control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) {
printControlFailureMessage(error);
- }] triggerBackup:backupPeers complete:^(NSError *error) {
+ }] rpcTriggerBackup:backupPeers complete:^(NSError *error) {
if (error == NULL) {
printf("trigger backup was successful\n");
} else {
- printf("%s", [[NSString stringWithFormat:@"Failed to start sync: %@\n", error] UTF8String]);
+ printf("%s", [[NSString stringWithFormat:@"Failed to start backup: %@\n", error] UTF8String]);
+ }
+ }];
+ } else if (triggerRingUpdate) {
+ [[control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) {
+ printControlFailureMessage(error);
+ }] rpcTriggerRingUpdate:^(NSError *error) {
+ if (error == NULL) {
+ printf("trigger ring update was successful\n");
+ } else {
+ printf("%s", [[NSString stringWithFormat:@"Failed to start ring update: %@\n", error] UTF8String]);
}
}];
}
}];
+ } 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 {
[[control.connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError *error) {
// 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/recovery_key.h"
+#endif
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;
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;
@implementation NSXPCConnectionMock
- (instancetype) initWithRealObject:(id)reality
{
- self = [super init];
- if (self) {
+ if ((self = [super init])) {
_reality = reality;
}
return self;
//
#import <UIKit/UIKit.h>
+#if !TARGET_OS_TV
#import <SpringBoardUIServices/SBSUIRemoteAlertItemContentViewController.h>
+#endif
@interface SWCViewController : SBSUIRemoteAlertItemContentViewController <UITableViewDelegate, UITableViewDataSource>
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;
}
<true/>
<key>com.apple.private.associated-domains</key>
<true/>
+ <key>com.apple.security.iokit-user-client-class</key>
+ <array>
+ <string>AGXDevice</string>
+ <string>AGXDeviceUserClient</string>
+ <string>AGXSharedUserClient</string>
+ <string>AGXCommandQueue</string>
+ <string>IOAccelContext</string>
+ <string>IOAccelContext2</string>
+ <string>IOAccelDevice</string>
+ <string>IOAccelDevice2</string>
+ <string>IOAccelSharedUserClient</string>
+ <string>IOAccelSharedUserClient2</string>
+ <string>IOAccelSubmitter</string>
+ <string>IOAccelSubmitter2</string>
+ <string>IOAVControllerConcreteUserClient</string>
+ <string>IOMobileFramebufferUserClient</string>
+ <string>IOSurfaceRootUserClient</string>
+ <string>RootDomainUserClient</string>
+ </array>
</dict>
</plist>
+++ /dev/null
-{
- "configurations" : [
- {
- "id" : "E61600EC-4F68-414B-932D-2A0655D233A4",
- "name" : "Configuration 1",
- "options" : {
-
- }
- }
- ],
- "defaultOptions" : {
-
- },
- "testTargets" : [
-
- ],
- "version" : 1
-}
// 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
#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
#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
@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
@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
@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;
@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
@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
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. */
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 */
};
@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
*/
/*
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
* 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);
#ifndef _SECURITY_SECINTERNAL_H_
#define _SECURITY_SECINTERNAL_H_
-#include <assert.h>
+#include "utilities/simulatecrash_assert.h"
#include <CoreFoundation/CFNumber.h>
#include <CoreFoundation/CFString.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/socket.h>
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. */
enum
{
- CSSM_APPLEDL_OPEN_PARAMETERS_VERSION = 1
+ CSSM_APPLEDL_OPEN_PARAMETERS_VERSION = 1u
};
enum cssm_appledl_open_parameters_mask
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;
}
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;
}
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;
}
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];
}
self.configurationData = [configuration objectForKey:SecExperimentConfigurationKeyConfigurationData];
+ } else {
+ return SEC_EXP_NIL_OUT_OF_MEMORY;
}
+
return self;
}
@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;
* Create an ARC-able `sec_experiment_t` instance wrapping an internal `SecExperiment` object.
*
* @param experiment
- * Name of the experiment.
+ * The experiment
*
* @return a `sec_experiment_t` instance.
*/
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) {
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':
break;
default:
fprintf(stderr, "%s: FAILURE: unknown option \"%c\"\n", argv[0], arg);
+ free(experiment_name);
return -1;
}
}
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
+ <key>SecErrorNestedErrorCapping</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ </dict>
+ <key>OctagonEscrowRecordFetch</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ </dict>
<key>EnableSecureObjectSync</key>
<dict>
<key>Enabled</key>
<key>CKKSViewsFromPolicy</key>
<dict>
<key>Enabled</key>
- <false/>
+ <true/>
</dict>
<key>securitydReportPolicy</key>
<dict>
<key>Enabled</key>
<false/>
</dict>
+ <key>OctagonOptimization</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ </dict>
+ <key>SecItemRateLimiting</key>
+ <dict>
+ <key>Enabled</key>
+ <false/>
+ </dict>
+ <key>LegacyAPICounts</key>
+ <dict>
+ <key>Enabled</key>
+ <true/>
+ </dict>
</dict>
</plist>
--- /dev/null
+./..//keychain/ot/proto/generated_source/OTCDPRecoveryInformation.h
\ No newline at end of file
--- /dev/null
+./..//keychain/ot/proto/generated_source/OTEscrowAuthenticationInformation.h
\ No newline at end of file
--- /dev/null
+./..//keychain/ot/proto/generated_source/OTEscrowRecord.h
\ No newline at end of file
--- /dev/null
+./..//keychain/ot/proto/generated_source/OTEscrowRecordMetadata.h
\ No newline at end of file
--- /dev/null
+./..//keychain/ot/proto/generated_source/OTEscrowRecordMetadataClientMetadata.h
\ No newline at end of file
--- /dev/null
+./../keychain/OctagonTrust/OTEscrowTranslation.h
\ No newline at end of file
--- /dev/null
+./..//keychain/ot/proto/generated_source/OTICDPRecordContext.h
\ No newline at end of file
--- /dev/null
+./..//keychain/ot/proto/generated_source/OTICDPRecordSilentContext.h
\ No newline at end of file
--- /dev/null
+./../keychain/OctagonTrust/OctagonTrust.h
\ No newline at end of file
+++ /dev/null
-./../keychain/Signin Metrics/SFSignInAnalytics.h
\ No newline at end of file
-./../SecExperiment/SecExperimentPriv.h
\ No newline at end of file
+./../experiment/SecExperimentPriv.h
\ No newline at end of file
-./OSX/libsecurity_asn1/lib/certExtensionTemplates.h
\ No newline at end of file
+./../OSX/libsecurity_asn1/lib/certExtensionTemplates.h
\ No newline at end of file
+++ /dev/null
-./../../OSX/Breadcrumb/SecBreadcrumb.h
\ No newline at end of file
+++ /dev/null
-./../../OSX/libsecurity_keychain/lib/SecCertificateBundle.h
\ No newline at end of file
- (NSData*)_onQueueGetDatabaseKeyDataWithError:(NSError**)error
{
+ dispatch_assert_queue(_queue);
NSData* keyData = nil;
NSDictionary* databaseKeyQuery = @{ (id)kSecClass : (id)kSecClassGenericPassword,
(id)kSecAttrAccessGroup : @"com.apple.security.securityd",
- (void)_onQueueDropClassAPersistentStore
{
+ dispatch_assert_queue(_queue);
for (NSPersistentStore* store in _classAPersistentStores) {
NSError* error = nil;
if (![_persistentStoreCoordinator removePersistentStore:store error:&error]) {
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);
}
}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
+ <key>CFBundleDisplayName</key>
+ <string>KeychainStasher</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIdentifier</key>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundlePackageType</key>
+ <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+</dict>
+</plist>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>application-identifier</key>
+ <string>com.apple.security.KeychainStasher</string>
+ <key>com.apple.private.keychain.sysbound</key>
+ <true/>
+</dict>
+</plist>
--- /dev/null
+#import <Foundation/Foundation.h>
+#import "KeychainStasherProtocol.h"
+
+@interface KeychainStasher : NSObject <KeychainStasherProtocol>
+@end
--- /dev/null
+#import <xpc/private.h>
+
+#import "utilities/debugging.h"
+#import <Security/SecItemPriv.h>
+#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
--- /dev/null
+#ifndef KeychainStasherProtocol_h
+#define KeychainStasherProtocol_h
+
+#import <Foundation/Foundation.h>
+
+@protocol KeychainStasherProtocol
+
+- (void)stashKey:(NSData*)key withReply:(void (^)(NSError*))reply;
+- (void)loadKeyWithReply:( void (^)(NSData*, NSError*))reply;
+
+@end
+
+#endif /* KeychainStasherProtocol_h */
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+ <dict>
+ <key>EnablePressuredExit</key>
+ <true/>
+ <key>EnableTransactions</key>
+ <true/>
+ <key>LimitLoadToSessionType</key>
+ <string>Background</string>
+ <key>POSIXSpawnType</key>
+ <string>Adaptive</string>
+ <key>Label</key>
+ <string>com.apple.security.KeychainStasher</string>
+ <key>MachServices</key>
+ <dict>
+ <key>com.apple.security.KeychainStasher</key>
+ <true/>
+ </dict>
+ <key>ProgramArguments</key>
+ <array>
+ <string>/usr/libexec/KeychainStasher</string>
+ </array>
+ </dict>
+</plist>
--- /dev/null
+(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"))
--- /dev/null
+#import <Foundation/Foundation.h>
+#import <Foundation/NSXPCConnection_Private.h>
+#import <unistd.h>
+#import <xpc/private.h>
+#import <sandbox.h>
+
+#import <Security/SecEntitlements.h>
+#import <utilities/debugging.h>
+#import <utilities/SecFileLocations.h>
+
+#import "KeychainStasher.h"
+
+NSString* const KeychainStasherMachServiceName = @"com.apple.security.KeychainStasher";
+
+@interface ServiceDelegate : NSObject <NSXPCListenerDelegate>
+@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;
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIdentifier</key>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundlePackageType</key>
+ <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>$(CURRENT_PROJECT_VERSION)</string>
+</dict>
+</plist>
--- /dev/null
+/*
+* 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 <Foundation/Foundation.h>
+#import <Security/Security.h>
+#import <OctagonTrust/OTEscrowRecord.h>
+#import <OctagonTrust/OTEscrowAuthenticationInformation.h>
+#import <OctagonTrust/OTICDPRecordContext.h>
+#import <OctagonTrust/OTCDPRecoveryInformation.h>
+
+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 */
--- /dev/null
+/*
+* 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 <Foundation/Foundation.h>
+#import "OTEscrowTranslation.h"
+
+#import <SoftLinking/SoftLinking.h>
+#import <CloudServices/SecureBackup.h>
+#import <CloudServices/SecureBackupConstants.h>
+#import "keychain/ot/categories/OctagonEscrowRecoverer.h"
+#import <OctagonTrust/OTEscrowRecordMetadata.h>
+#import <OctagonTrust/OTEscrowRecordMetadataClientMetadata.h>
+#import <Security/OTConstants.h>
+#import "keychain/ot/OTClique+Private.h"
+#import <utilities/debugging.h>
+
+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";
+
+@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.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[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
+
--- /dev/null
+/*
+ * 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 <Foundation/Foundation.h>
+#import <Security/OTClique.h>
+#import <OctagonTrust/OTEscrowRecord.h>
+#import <OctagonTrust/OTEscrowTranslation.h>
+#import <OctagonTrust/OTEscrowAuthenticationInformation.h>
+#import <OctagonTrust/OTICDPRecordContext.h>
+#import <OctagonTrust/OTICDPRecordSilentContext.h>
+#import <OctagonTrust/OTEscrowRecordMetadata.h>
+#import <OctagonTrust/OTEscrowRecordMetadataClientMetadata.h>
+
+
+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<OTEscrowRecord*>* _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<OTEscrowRecord*>* _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<OTEscrowRecord*>*)allRecords
+ error:(NSError**)error;
+
++ (BOOL) invalidateEscrowCache:(OTConfigurationContext*)data error:(NSError**)error;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif
--- /dev/null
+/*
+* 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 "OctagonTrust.h"
+#import <Security/OTClique+Private.h>
+#import <utilities/debugging.h>
+#import "OTEscrowTranslation.h"
+
+#import <SoftLinking/SoftLinking.h>
+#import <CloudServices/SecureBackup.h>
+#import <CloudServices/SecureBackupConstants.h>
+#import "keychain/OctagonTrust/categories/OctagonTrustEscrowRecoverer.h"
+#import "keychain/ot/OTDefines.h"
+#import "keychain/ot/OTControl.h"
+#import "keychain/ot/OTClique+Private.h"
+#import <Security/OctagonSignPosts.h>
+#include <utilities/SecCFRelease.h>
+
+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<OTEscrowRecord*>*)filterViableSOSRecords:(NSArray<OTEscrowRecord*>*)nonViable
+{
+ NSMutableArray<OTEscrowRecord*>* 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<OTEscrowRecord*>* _Nullable)filterRecords:(NSArray<OTEscrowRecord*>*)allRecords
+{
+ NSMutableArray<OTEscrowRecord*>* viable = [NSMutableArray array];
+ NSMutableArray<OTEscrowRecord*>* partial = [NSMutableArray array];
+ NSMutableArray<OTEscrowRecord*>* 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<OTEscrowRecord*>* 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<OTEscrowRecord*>* _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<OTEscrowRecord*>* 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<OTEscrowRecord*>* _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<OTEscrowRecord*>* _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<OctagonEscrowRecovererPrococol> 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<OTEscrowRecord*>* 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<OctagonEscrowRecovererPrococol> sb = data.sbd ?: [[getSecureBackupClass() alloc] init];
+ NSError* restoreError = nil;
+
+ NSMutableSet <NSString *> *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<OctagonEscrowRecovererPrococol> 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<OTEscrowRecord*>*)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<OTEscrowRecord*>*)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<OctagonEscrowRecovererPrococol> 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
--- /dev/null
+
+#if OCTAGON
+
+#ifndef OctagonTrustEscrowRecoverer_h
+#define OctagonTrustEscrowRecoverer_h
+
+@protocol OctagonEscrowRecovererPrococol <NSObject>
+- (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<OTEscrowRecord*>*)allRecords
+ error:(NSError**)error;
+- (void)restoreKeychainAsyncWithPassword:password
+ keybagDigest:(NSData *)keybagDigest
+ haveBottledPeer:(BOOL)haveBottledPeer
+ viewsNotToBeRestored:(NSMutableSet <NSString*>*)viewsNotToBeRestored
+ error:(NSError **)error;
+
+@end
+
+#endif /* OctagonTrustEscrowRecoverer_h */
+
+#endif // OCTAGON
--- /dev/null
+/*
+ * 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 <Foundation/Foundation.h>
+#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
--- /dev/null
+/*
+* 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 <Foundation/Foundation.h>
+#import <XCTest/XCTest.h>
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wquoted-include-in-framework-header"
+#import <OCMock/OCMock.h>
+#pragma clang diagnostic pop
+
+#import <OctagonTrust/OctagonTrust.h>
+#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 <Foundation/NSPropertyList.h>
+
+#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 <OctagonEntitlementBearerProtocol>
+@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 <OctagonEscrowRecovererPrococol>
+@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<OTEscrowRecord *> *)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<NSString *> *)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<NSData*>* _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<NSData*>* _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<NSData*>* _Nullable)mockFetchEscrowRecordsInternalReturnPartiallyViableRecords:(OTConfigurationContext*)data
+ error:(NSError* __autoreleasing *)error
+{
+ return @[[self createPartialRecord].data, [self createPartialRecord].data];
+}
+
+- (NSArray<NSData*>* _Nullable)mockFetchEscrowRecordsInternalReturnOctagonViableSOSViableRecords:(OTConfigurationContext*)data
+ error:(NSError* __autoreleasing *)error
+{
+ return @[[self createOctagonViableSOSViableRecord].data, [self createOctagonViableSOSViableRecord].data];
+}
+
+- (NSArray<NSData*>* _Nullable)mockFetchEscrowRecordsInternalReturnLegacyRecords:(OTConfigurationContext*)data
+ error:(NSError* __autoreleasing *)error
+{
+ return @[[self createLegacyRecord].data, [self createLegacyRecord].data];
+}
+
+- (NSArray<NSData*>* _Nullable)mockFetchEscrowRecordsInternalReturnLegacyNonViableSOSRecords:(OTConfigurationContext*)data
+ error:(NSError* __autoreleasing *)error
+{
+ return @[[self createLegacyRecordWithSOSNotViable].data, [self createLegacyRecordWithSOSNotViable].data];
+}
+
+- (NSArray<NSData*>* _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
+
--- /dev/null
+/*
+* 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 = @"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
+<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\
+<plist version=\"1.0\">\
+<dict>\
+ <key>SecureBackupAccountIsHighSecurity</key>\
+ <false/>\
+ <key>SecureBackupAlliCDPRecords</key>\
+ <array>\
+ <dict>\
+ <key>SecureBackupEscrowDate</key>\
+ <date>2020-01-31T03:07:40Z</date>\
+ <key>SecureBackupRemainingAttempts</key>\
+ <integer>10</integer>\
+ <key>encodedMetadata</key>\
+ <string>YnBsaXN0MDDZAQIDBAUGBwgJCgsMDQ4PECYgVnNlcmlhbF8QEkJhY2t1cEtleWJhZ0RpZ2VzdFVidWlsZFhwZWVySW5mb18QIGNvbS5hcHBsZS5zZWN1cmViYWNrdXAudGltZXN0YW1wWGJvdHRsZUlEXkNsaWVudE1ldGFkYXRhXGVzY3Jvd2VkU1BLSV8QHVNlY3VyZUJhY2t1cFVzZXNNdWx0aXBsZWlDU0NzXEMzOVYyMDlBSjlMNU8QFMhRrcsWNmcw7dI/9uhpDUpq4FZ2VjE4QTIxNE8RBLIwggSuMYIEYTAUDA9Db25mbGljdFZlcnNpb24CAQMwKwwPQXBwbGljYXRpb25EYXRlBBgYFjIwMjAwMTMwMjI0MTI2LjI4MDA1N1owVQwQUHVibGljU2lnbmluZ0tleQRBBOW+fXyAnCMa6by/cKGf1iHkcz9VEsa6rocBXgrLGVSb7Dy4XzT7fa1jf+X2co6ZTrXr3Vt56TBJZx8X6YNMY+swWAwPQXBwbGljYXRpb25Vc2lnBEUwQwIgY4hdZ7zcWd+Ue77JKF2OK99No8MUe9f5Fg2AzLviJKcCH04d5DOYNyFk6LTzWVuHD/2uMR7zASajNdfXbpFQ578wcAwNRGV2aWNlR2VzdGFsdDFfMBMMCU1vZGVsTmFtZQwGaVBob25lMBMMCU9TVmVyc2lvbgwGMThBMjE0MBYMDENvbXB1dGVyTmFtZQwGaVBob25lMBsMFk1lc3NhZ2VQcm90b2NvbFZlcnNpb24CAQAwfAwXT2N0YWdvblB1YmxpY1NpZ25pbmdLZXkEYQSguiFhjcalFK/bQBPruMsnWzZ0qv7VtPwmhjbdCQJ4mCMY1v6+60RCEsWMs+wQ200Tv40DvCBpzRABcsM70f8tuk1Q/wMXVDQ2kVfgmIVmobzvqNLwcSBHpU44nOEnNRkwfwwaT2N0YWdvblB1YmxpY0VuY3J5cHRpb25LZXkEYQQNGdKw9D+ZMSXl2YwRidBiFyb2GI/MGdDSCFDNvvRq5ig9sJHGMKgbswKltv7gkYzgvvg51slkltO0d5nQm0Juqj3dnIh9QtbPXfUew7LGjBNJIj3IOI8DJdnPqdGee+cwggH4DBBWMkRpY3Rpb25hcnlEYXRhBIIB4jGCAd4wEAwMRXNjcm93UmVjb3JkBQAwHAwMU2VyaWFsTnVtYmVyDAxDMzlWMjA5QUo5TDUwLQwJQmFja3VwS2V5BCBmWfEWzk0k71iVH/hINYf572sP/4l/uVZaMyhNb36frzBgDAxNYWNoaW5lSURLZXkMUHlXbkk4dmROZzZFV2F5ZVcvRlA0Y0RaUnNlM0xNbjhQeGcveC9zUHpaSklTNWNzM1JLbzQvc3RPVzQ2blE5OGlObHBTSHJuUjBrZnNiUjNYMIIBGQwFVmlld3PRggEODAdBcHBsZVRWDAdIb21lS2l0DAdQQ1MtRkRFDAlQQ1MtTm90ZXMMClBDUy1CYWNrdXAMClBDUy1Fc2Nyb3cMClBDUy1QaG90b3MMC0JhY2t1cEJhZ1YwDAtQQ1MtU2hhcmluZwwMTmFub1JlZ2lzdHJ5DAxQQ1MtQ2xvdWRLaXQMDFBDUy1GZWxkc3BhcgwMUENTLU1haWxkcm9wDAxQQ1MtaU1lc3NhZ2UMDVBDUy1NYXN0ZXJLZXkMDldhdGNoTWlncmF0aW9uDA5pQ2xvdWRJZGVudGl0eQwPUENTLWlDbG91ZERyaXZlDBBBY2Nlc3NvcnlQYWlyaW5nDBBDb250aW51aXR5VW5sb2NrBEcwRQIgRLmiTIo/hgxmoOMgZEygsTzdJiHOMTI68Y8DQGgXpWICIQCHr913nsr4kFaYZd3i/ioYQum8B5KOpxFR90u1CPgPEl8QEzIwMjAtMDEtMzEgMDM6MDc6NDBfECRERDVFM0Y5Ri0zNzAyLTQ3ODktOEFDRi0yRDI4QkM4NkE5NEPcERITFBUWFxgZGhscHQ4eHR8gISIjICMlXxAWZGV2aWNlX2VuY2xvc3VyZV9jb2xvcl8QHVNlY3VyZUJhY2t1cE1ldGFkYXRhVGltZXN0YW1wXxAPZGV2aWNlX3BsYXRmb3JtXGRldmljZV9jb2xvcl8QI1NlY3VyZUJhY2t1cE51bWVyaWNQYXNzcGhyYXNlTGVuZ3RoXxAhU2VjdXJlQmFja3VwVXNlc0NvbXBsZXhQYXNzcGhyYXNlWmRldmljZV9taWRfEBRkZXZpY2VfbW9kZWxfdmVyc2lvbltkZXZpY2VfbmFtZV8QIVNlY3VyZUJhY2t1cFVzZXNOdW1lcmljUGFzc3BocmFzZV8QEmRldmljZV9tb2RlbF9jbGFzc1xkZXZpY2VfbW9kZWxRMRQAAAAAAAAAAAAAAAAAAAABEAYJXxBQeVduSTh2ZE5nNkVXYXllVy9GUDRjRFpSc2UzTE1uOFB4Zy94L3NQelpKSVM1Y3MzUktvNC9zdE9XNDZuUTk4aU5scFNIcm5SMGtmc2JSM1haaVBob25lMTAsNVZpUGhvbmUJXWlQaG9uZSA4IFBsdXNPEHgwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATIde8QFJDJYQJa6NrxP5WDLEhPNga9732ZGyoVoKi0RnxT6aIlb/LBrRvnrdZFyGUMlSYGSY3GIgrLz3YJ0A0W4BN6YKMtsgGCDONSD5/KHRzTEAE5e3Yp26nshhMavOcJAAgAGwAiADcAPQBGAGkAcgCBAI4ArgC7ANIA2QWPBaUFzAXlBf4GHgYwBj0GYwaHBpIGqQa1BtkG7gb7Bv0HDgcQBxEHZAdvB3YHdweFCAAAAAAAAAACAQAAAAAAAAAoAAAAAAAAAAAAAAAAAAAIAQ==</string>\
+ <key>label</key>\
+ <string>com.apple.icdp.record</string>\
+ <key>metadata</key>\
+ <dict>\
+ <key>BackupKeybagDigest</key>\
+ <data>\
+ yFGtyxY2ZzDt0j/26GkNSmrgVnY=\
+ </data>\
+ <key>ClientMetadata</key>\
+ <dict>\
+ <key>SecureBackupMetadataTimestamp</key>\
+ <string>2020-01-31 03:07:40</string>\
+ <key>SecureBackupNumericPassphraseLength</key>\
+ <integer>6</integer>\
+ <key>SecureBackupUsesComplexPassphrase</key>\
+ <true/>\
+ <key>SecureBackupUsesNumericPassphrase</key>\
+ <true/>\
+ <key>device_color</key>\
+ <string>1</string>\
+ <key>device_enclosure_color</key>\
+ <string>1</string>\
+ <key>device_mid</key>\
+ <string>yWnI8vdNg6EWayeW/FP4cDZRse3LMn8Pxg/x/sPzZJIS5cs3RKo4/stOW46nQ98iNlpSHrnR0kfsbR3X</string>\
+ <key>device_model</key>\
+ <string>iPhone 8 Plus</string>\
+ <key>device_model_class</key>\
+ <string>iPhone</string>\
+ <key>device_model_version</key>\
+ <string>iPhone10,5</string>\
+ <key>device_name</key>\
+ <string>iPhone</string>\
+ <key>device_platform</key>\
+ <integer>1</integer>\
+ </dict>\
+ <key>SecureBackupUsesMultipleiCSCs</key>\
+ <true/>\
+ <key>bottleID</key>\
+ <string>DD5E3F9F-3702-4789-8ACF-2D28BC86A94C</string>\
+ <key>build</key>\
+ <string>18A214</string>\
+ <key>com.apple.securebackup.timestamp</key>\
+ <string>2020-01-31 03:07:40</string>\
+ <key>escrowedSPKI</key>\
+ <data>\
+ MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEyHXvEBSQyWEC\
+ Wuja8T+VgyxITzYGve99mRsqFaCotEZ8U+miJW/ywa0b\
+ 563WRchlDJUmBkmNxiIKy892CdANFuATemCjLbIBggzj\
+ Ug+fyh0c0xABOXt2Kdup7IYTGrzn\
+ </data>\
+ <key>peerInfo</key>\
+ <data>\
+ 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=\
+ </data>\
+ <key>serial</key>\
+ <string>C39V209AJ9L5</string>\
+ </dict>\
+ <key>osVersion</key>\
+ <string>18A214</string>\
+ <key>peerInfoSerialNumber</key>\
+ <string>C39V209AJ9L5</string>\
+ <key>recordID</key>\
+ <string>sNs6voV0N35D/T91SuGmJnGO29</string>\
+ <key>recordStatus</key>\
+ <string>valid</string>\
+ <key>silentAttemptAllowed</key>\
+ <true/>\
+ </dict>\
+ </array>\
+ <key>SecureBackupContainsiCloudIdentity</key>\
+ <true/>\
+ <key>SecureBackupEnabled</key>\
+ <true/>\
+ <key>SecureBackupEscrowTrustStatus</key>\
+ <integer>0</integer>\
+ <key>SecureBackupRecoveryRequiresVerificationToken</key>\
+ <false/>\
+ <key>SecureBackupUsesRecoveryKey</key>\
+ <false/>\
+ <key>SecureBackupiCDPRecords</key>\
+ <array>\
+ <dict>\
+ <key>SecureBackupEscrowDate</key>\
+ <date>2020-01-31T03:07:40Z</date>\
+ <key>SecureBackupRemainingAttempts</key>\
+ <integer>10</integer>\
+ <key>encodedMetadata</key>\
+ <string>YnBsaXN0MDDZAQIDBAUGBwgJCgsMDQ4PECYgVnNlcmlhbF8QEkJhY2t1cEtleWJhZ0RpZ2VzdFVidWlsZFhwZWVySW5mb18QIGNvbS5hcHBsZS5zZWN1cmViYWNrdXAudGltZXN0YW1wWGJvdHRsZUlEXkNsaWVudE1ldGFkYXRhXGVzY3Jvd2VkU1BLSV8QHVNlY3VyZUJhY2t1cFVzZXNNdWx0aXBsZWlDU0NzXEMzOVYyMDlBSjlMNU8QFMhRrcsWNmcw7dI/9uhpDUpq4FZ2VjE4QTIxNE8RBLIwggSuMYIEYTAUDA9Db25mbGljdFZlcnNpb24CAQMwKwwPQXBwbGljYXRpb25EYXRlBBgYFjIwMjAwMTMwMjI0MTI2LjI4MDA1N1owVQwQUHVibGljU2lnbmluZ0tleQRBBOW+fXyAnCMa6by/cKGf1iHkcz9VEsa6rocBXgrLGVSb7Dy4XzT7fa1jf+X2co6ZTrXr3Vt56TBJZx8X6YNMY+swWAwPQXBwbGljYXRpb25Vc2lnBEUwQwIgY4hdZ7zcWd+Ue77JKF2OK99No8MUe9f5Fg2AzLviJKcCH04d5DOYNyFk6LTzWVuHD/2uMR7zASajNdfXbpFQ578wcAwNRGV2aWNlR2VzdGFsdDFfMBMMCU1vZGVsTmFtZQwGaVBob25lMBMMCU9TVmVyc2lvbgwGMThBMjE0MBYMDENvbXB1dGVyTmFtZQwGaVBob25lMBsMFk1lc3NhZ2VQcm90b2NvbFZlcnNpb24CAQAwfAwXT2N0YWdvblB1YmxpY1NpZ25pbmdLZXkEYQSguiFhjcalFK/bQBPruMsnWzZ0qv7VtPwmhjbdCQJ4mCMY1v6+60RCEsWMs+wQ200Tv40DvCBpzRABcsM70f8tuk1Q/wMXVDQ2kVfgmIVmobzvqNLwcSBHpU44nOEnNRkwfwwaT2N0YWdvblB1YmxpY0VuY3J5cHRpb25LZXkEYQQNGdKw9D+ZMSXl2YwRidBiFyb2GI/MGdDSCFDNvvRq5ig9sJHGMKgbswKltv7gkYzgvvg51slkltO0d5nQm0Juqj3dnIh9QtbPXfUew7LGjBNJIj3IOI8DJdnPqdGee+cwggH4DBBWMkRpY3Rpb25hcnlEYXRhBIIB4jGCAd4wEAwMRXNjcm93UmVjb3JkBQAwHAwMU2VyaWFsTnVtYmVyDAxDMzlWMjA5QUo5TDUwLQwJQmFja3VwS2V5BCBmWfEWzk0k71iVH/hINYf572sP/4l/uVZaMyhNb36frzBgDAxNYWNoaW5lSURLZXkMUHlXbkk4dmROZzZFV2F5ZVcvRlA0Y0RaUnNlM0xNbjhQeGcveC9zUHpaSklTNWNzM1JLbzQvc3RPVzQ2blE5OGlObHBTSHJuUjBrZnNiUjNYMIIBGQwFVmlld3PRggEODAdBcHBsZVRWDAdIb21lS2l0DAdQQ1MtRkRFDAlQQ1MtTm90ZXMMClBDUy1CYWNrdXAMClBDUy1Fc2Nyb3cMClBDUy1QaG90b3MMC0JhY2t1cEJhZ1YwDAtQQ1MtU2hhcmluZwwMTmFub1JlZ2lzdHJ5DAxQQ1MtQ2xvdWRLaXQMDFBDUy1GZWxkc3BhcgwMUENTLU1haWxkcm9wDAxQQ1MtaU1lc3NhZ2UMDVBDUy1NYXN0ZXJLZXkMDldhdGNoTWlncmF0aW9uDA5pQ2xvdWRJZGVudGl0eQwPUENTLWlDbG91ZERyaXZlDBBBY2Nlc3NvcnlQYWlyaW5nDBBDb250aW51aXR5VW5sb2NrBEcwRQIgRLmiTIo/hgxmoOMgZEygsTzdJiHOMTI68Y8DQGgXpWICIQCHr913nsr4kFaYZd3i/ioYQum8B5KOpxFR90u1CPgPEl8QEzIwMjAtMDEtMzEgMDM6MDc6NDBfECRERDVFM0Y5Ri0zNzAyLTQ3ODktOEFDRi0yRDI4QkM4NkE5NEPcERITFBUWFxgZGhscHQ4eHR8gISIjICMlXxAWZGV2aWNlX2VuY2xvc3VyZV9jb2xvcl8QHVNlY3VyZUJhY2t1cE1ldGFkYXRhVGltZXN0YW1wXxAPZGV2aWNlX3BsYXRmb3JtXGRldmljZV9jb2xvcl8QI1NlY3VyZUJhY2t1cE51bWVyaWNQYXNzcGhyYXNlTGVuZ3RoXxAhU2VjdXJlQmFja3VwVXNlc0NvbXBsZXhQYXNzcGhyYXNlWmRldmljZV9taWRfEBRkZXZpY2VfbW9kZWxfdmVyc2lvbltkZXZpY2VfbmFtZV8QIVNlY3VyZUJhY2t1cFVzZXNOdW1lcmljUGFzc3BocmFzZV8QEmRldmljZV9tb2RlbF9jbGFzc1xkZXZpY2VfbW9kZWxRMRQAAAAAAAAAAAAAAAAAAAABEAYJXxBQeVduSTh2ZE5nNkVXYXllVy9GUDRjRFpSc2UzTE1uOFB4Zy94L3NQelpKSVM1Y3MzUktvNC9zdE9XNDZuUTk4aU5scFNIcm5SMGtmc2JSM1haaVBob25lMTAsNVZpUGhvbmUJXWlQaG9uZSA4IFBsdXNPEHgwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATIde8QFJDJYQJa6NrxP5WDLEhPNga9732ZGyoVoKi0RnxT6aIlb/LBrRvnrdZFyGUMlSYGSY3GIgrLz3YJ0A0W4BN6YKMtsgGCDONSD5/KHRzTEAE5e3Yp26nshhMavOcJAAgAGwAiADcAPQBGAGkAcgCBAI4ArgC7ANIA2QWPBaUFzAXlBf4GHgYwBj0GYwaHBpIGqQa1BtkG7gb7Bv0HDgcQBxEHZAdvB3YHdweFCAAAAAAAAAACAQAAAAAAAAAoAAAAAAAAAAAAAAAAAAAIAQ==</string>\
+ <key>label</key>\
+ <string>com.apple.icdp.record</string>\
+ <key>metadata</key>\
+ <dict>\
+ <key>BackupKeybagDigest</key>\
+ <data>\
+ yFGtyxY2ZzDt0j/26GkNSmrgVnY=\
+ </data>\
+ <key>ClientMetadata</key>\
+ <dict>\
+ <key>SecureBackupMetadataTimestamp</key>\
+ <string>2020-01-31 03:07:40</string>\
+ <key>SecureBackupNumericPassphraseLength</key>\
+ <integer>6</integer>\
+ <key>SecureBackupUsesComplexPassphrase</key>\
+ <true/>\
+ <key>SecureBackupUsesNumericPassphrase</key>\
+ <true/>\
+ <key>device_color</key>\
+ <string>1</string>\
+ <key>device_enclosure_color</key>\
+ <string>1</string>\
+ <key>device_mid</key>\
+ <string>yWnI8vdNg6EWayeW/FP4cDZRse3LMn8Pxg/x/sPzZJIS5cs3RKo4/stOW46nQ98iNlpSHrnR0kfsbR3X</string>\
+ <key>device_model</key>\
+ <string>iPhone 8 Plus</string>\
+ <key>device_model_class</key>\
+ <string>iPhone</string>\
+ <key>device_model_version</key>\
+ <string>iPhone10,5</string>\
+ <key>device_name</key>\
+ <string>iPhone</string>\
+ <key>device_platform</key>\
+ <integer>1</integer>\
+ </dict>\
+ <key>SecureBackupUsesMultipleiCSCs</key>\
+ <true/>\
+ <key>bottleID</key>\
+ <string>DD5E3F9F-3702-4789-8ACF-2D28BC86A94C</string>\
+ <key>bottleValid</key>\
+ <string>valid</string>\
+ <key>build</key>\
+ <string>18A214</string>\
+ <key>com.apple.securebackup.timestamp</key>\
+ <string>2020-01-31 03:07:40</string>\
+ <key>escrowedSPKI</key>\
+ <data>\
+ MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEyHXvEBSQyWEC\
+ Wuja8T+VgyxITzYGve99mRsqFaCotEZ8U+miJW/ywa0b\
+ 563WRchlDJUmBkmNxiIKy892CdANFuATemCjLbIBggzj\
+ Ug+fyh0c0xABOXt2Kdup7IYTGrzn\
+ </data>\
+ <key>peerInfo</key>\
+ <data>\
+ 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=\
+ </data>\
+ <key>serial</key>\
+ <string>C39V209AJ9L5</string>\
+ </dict>\
+ <key>osVersion</key>\
+ <string>18A214</string>\
+ <key>peerInfoSerialNumber</key>\
+ <string>C39V209AJ9L5</string>\
+ <key>recordID</key>\
+ <string>sNs6voV0N35D/T91SuGmJnGO29</string>\
+ <key>recordStatus</key>\
+ <string>valid</string>\
+ <key>silentAttemptAllowed</key>\
+ <true/>\
+ </dict>\
+ </array>\
+ <key>SecureBackupiCloudDataProtectionEnabled</key>\
+ <false/>\
+</dict>\
+</plist>";
+
+NSString *testCDPRemoteRecordContextTestVector = @"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
+<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\
+<plist version=\"1.0\">\
+<dict>\
+ <key>SecureBackupAuthenticationAppleID</key>\
+ <string>anna.535.paid@icloud.com</string>\
+ <key>SecureBackupAuthenticationAuthToken</key>\
+ <string>EAAbAAAABLwIAAAAAF5PGvkRDmdzLmljbG91ZC5hdXRovQBx359KJvlZTwe1q6BwXvK4gQUYo2WQbKT8UDtn8rcA6FvEYBANaAk1ofWx/bcfB4pcLiXR3Y0kncELCwFCEEpqpZS+klD9AY1oT9zW6VtyOgQTZJ4mfWz103+FoMh8nLJAVpYVfM/UjsiNsLfTX+rUmevfeA==</string>\
+ <key>SecureBackupAuthenticationDSID</key>\
+ <string>16187698960</string>\
+ <key>SecureBackupAuthenticationEscrowProxyURL</key>\
+ <string>https://p97-escrowproxy.icloud.com:443</string>\
+ <key>SecureBackupAuthenticationPassword</key>\
+ <string>PETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPET</string>\
+ <key>SecureBackupAuthenticationiCloudEnvironment</key>\
+ <string>PROD</string>\
+ <key>SecureBackupContainsiCDPData</key>\
+ <true/>\
+ <key>SecureBackupMetadata</key>\
+ <dict>\
+ <key>BackupKeybagDigest</key>\
+ <data>\
+ uZ+vDf1JWIHh+MXIi487iENG2fk=\
+ </data>\
+ <key>ClientMetadata</key>\
+ <dict>\
+ <key>SecureBackupMetadataTimestamp</key>\
+ <string>2020-02-20 00:38:28</string>\
+ <key>SecureBackupNumericPassphraseLength</key>\
+ <integer>6</integer>\
+ <key>SecureBackupUsesComplexPassphrase</key>\
+ <true/>\
+ <key>SecureBackupUsesNumericPassphrase</key>\
+ <integer>1</integer>\
+ <key>device_color</key>\
+ <string>1</string>\
+ <key>device_enclosure_color</key>\
+ <string>1</string>\
+ <key>device_mid</key>\
+ <string>vsoWCkYtidlo3QGgt6jvLDfeTWqKKQwHITeUEuYM7ZoyWI6CRH/ZUqsdg1fT96TyAyxUuYUF3fjRs5b1</string>\
+ <key>device_model</key>\
+ <string>iPhone 8 Plus</string>\
+ <key>device_model_class</key>\
+ <string>iPhone</string>\
+ <key>device_model_version</key>\
+ <string>iPhone10,2</string>\
+ <key>device_name</key>\
+ <string>One</string>\
+ <key>device_platform</key>\
+ <integer>1</integer>\
+ </dict>\
+ <key>SecureBackupUsesMultipleiCSCs</key>\
+ <true/>\
+ <key>bottleID</key>\
+ <string>0125E97E-B124-4556-881A-A355805EBE47</string>\
+ <key>bottleValid</key>\
+ <string>valid</string>\
+ <key>build</key>\
+ <string>18A230</string>\
+ <key>com.apple.securebackup.timestamp</key>\
+ <string>2020-02-20 00:38:28</string>\
+ <key>escrowedSPKI</key>\
+ <data>\
+ MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEB48BVh0D++mTSm9ucXC/a5M0CxFm\
+ 4QfFktDjGV0Oo3z7xLSBiqxOwvzl1Vt7m45Rbfk4YnyguNan7aDzD1X6S2zU\
+ HhJ8nXro1aAn8tnUX6+EGV2v4iScbkeOrWkqQoWw\
+ </data>\
+ <key>peerInfo</key>\
+ <data>\
+ 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\
+ </data>\
+ <key>serial</key>\
+ <string>C39V20EKJ9KT</string>\
+ </dict>\
+ <key>SecureBackupPassphrase</key>\
+ <string>333333</string>\
+ <key>SecureBackupUsesMultipleiCSCs</key>\
+ <true/>\
+ <key>recordID</key>\
+ <string>nDF7K/s5knTXbH6/+ERe2LPFZR</string>\
+</dict>\
+</plist>";
+
+NSString* CDPRecordContextSilentTestVector = @"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
+<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\
+<plist version=\"1.0\">\
+<dict>\
+ <key>SecureBackupAuthenticationAppleID</key>\
+ <string>anna.535.paid@icloud.com</string>\
+ <key>SecureBackupAuthenticationAuthToken</key>\
+ <string>EAAbAAAABLwIAAAAAF5PHOERDmdzLmljbG91ZC5hdXRovQDwjwm2kXoklEtO/xeL3YCPlBr7IkVuV26y2BfLco+QhJFm4VhgFZSBFUg5l4g/uV2DG95xadgk0+rWLhyXDGZwHN2V9jju3eo6sRwGVj4g5iBFStuj4unTKylu3iFkNSKtTMXAyBXpn4EiRX+8dwumC2FKkA==</string>\
+ <key>SecureBackupAuthenticationDSID</key>\
+ <string>16187698960</string>\
+ <key>SecureBackupAuthenticationEscrowProxyURL</key>\
+ <string>https://p97-escrowproxy.icloud.com:443</string>\
+ <key>SecureBackupAuthenticationPassword</key>\
+ <string>PETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPETPET</string>\
+ <key>SecureBackupAuthenticationiCloudEnvironment</key>\
+ <string>PROD</string>\
+ <key>SecureBackupContainsiCDPData</key>\
+ <true/>\
+ <key>SecureBackupPassphrase</key>\
+ <string>333333</string>\
+ <key>SecureBackupSilentRecoveryAttempt</key>\
+ <true/>\
+ <key>SecureBackupUsesMultipleiCSCs</key>\
+ <true/>\
+</dict>\
+</plist>";
+
+#endif
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIdentifier</key>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundlePackageType</key>
+ <string>BNDL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+</dict>
+</plist>
--- /dev/null
+/*
+* 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 <NSXPCListenerDelegate>
+@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 */
-#!/usr/bin/python
-#
+#!/usr/local/bin/python3
import sys
from glob import glob
def security_cmd_by_platform():
swVers = subprocess.check_output(["sw_vers"])
- deviceInformation = str(swVers, 'utf-8')
- if "Mac OS X" in deviceInformation:
- print("using security2 command on macosx")
+ 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")
security_cmd = security_cmd_by_platform()
-print("resetting octagon")
-subprocess.check_output(["otctl", "resetoctagon"])
-
-print("resetting ckks")
-subprocess.check_output(["ckksctl", "reset-cloudkit"])
+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("deleting all escrow records")
-subprocess.check_output(["stingrayutil", "--deleteAll", "ReallyDeleteAll"])
+print("resetting octagon")
+subprocess.check_output(["otctl", "resetoctagon"])
print("creating new escrow record")
subprocess.check_output(["sbdtool", "passcode_request_trigger"])
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;
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);
});
- (NSDictionary<NSString *, id>*) copyAsDictionary;
-- (void)pushWrites;
+- (void)pushWrites:(NSArray<NSString*>*)keys requiresForceSync:(BOOL)requiresForceSync;
- (BOOL)pullUpdates:(NSError**) failure;
- (void)addOneToOutGoing;
}
- (instancetype)init {
- self = [super init];
-
- self.proxy = nil;
- self.data = [NSMutableDictionary<NSString*, NSObject*> dictionary];
-
+ if ((self = [super init])) {
+ self.proxy = nil;
+ self.data = [NSMutableDictionary<NSString*, NSObject*> dictionary];
+ }
return self;
}
[self.data removeAllObjects];
}
-- (void)pushWrites {
+- (void)pushWrites:(NSArray<NSString*>*)keys requiresForceSync:(BOOL)requiresForceSync
+{
}
- (void)addOneToOutGoing{
return [[CKDSimulatedAccount alloc] init];
}
- (instancetype) init {
- self = [super init];
- if (self) {
+ if ((self = [super init])) {
self.keysToNotHandle = [NSMutableSet<NSString*> set];
self.keyChanges = [NSMutableDictionary<NSString*, NSObject*> dictionary];
#include <Security/SecKey.h>
#include <Security/SecureObjectSync/SOSPeerInfo.h>
#include "keychain/SecureObjectSync/SOSFullPeerInfo.h"
+#include <TargetConditionals.h>
__BEGIN_DECLS
+#define SOS_ENABLED (TARGET_OS_OSX || TARGET_OS_IOS)
+
CFStringRef myMacAddress(void);
const char *cfabsoluteTimeToString(CFAbsoluteTime abstime);
const char *cfabsoluteTimeToStringLocal(CFAbsoluteTime abstime);
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
{
require(gestalt, exit);
result = SOSPeerInfoCreate(NULL, gestalt, NULL, *outSigningKey,
- *outOctagonSigningKey, *outOctagonEncryptionKey, error);
+ *outOctagonSigningKey, *outOctagonEncryptionKey,
+ // Always support CKKS4All for now
+ true,
+ error);
exit:
CFReleaseNull(gestalt);
// 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;
#include "SOSRegressionUtilities.h"
+#if SOS_ENABLED
+
typedef struct piStuff_t {
SecKeyRef signingKey;
SecKeyRef octagonSigningKey;
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;
}
#include "SOSRegressionUtilities.h"
#include "keychain/SecureObjectSync/SOSInternal.h"
+#if SOS_ENABLED
+
#if 0
static inline CFMutableDataRef CFDataCreateMutableWithRandom(CFAllocatorRef allocator, CFIndex size) {
CFMutableDataRef result = NULL;
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();
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;
}
#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;
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,
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;
SOSBackupSliceKeyBagRef vb2 = NULL;
-#if !TARGET_OS_SIMULATOR
vb = SOSBackupSliceKeyBagCreate(kCFAllocatorDefault, piSet, &localError);
ok(vb != NULL, "Allocation: (%@)", localError);
CFReleaseNull(localError);
vb2 = EncodeDecode(vb);
ok(vb2 != NULL, "transcoded");
-#endif
-#if 0
- // <rdar://problem/20561988> 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);
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;
}
#include "SOSRegressionUtilities.h"
+#if SOS_ENABLED
+
static int kTestTestCount = 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;
}
#include "SOSCircle_regressions.h"
#include "SOSRegressionUtilities.h"
+
+#if SOS_ENABLED
+
#include <corecrypto/ccrng.h>
#include <corecrypto/ccrng_pbkdf2_prng.h>
#include <corecrypto/ccec.h>
return NULL;
}
- debugDumpUserParameters(CFSTR("params-keygen"), parameters);
const uint8_t *password_bytes = CFDataGetBytePtr(password);
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,
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;
}
#include "SOSRegressionUtilities.h"
+#if SOS_ENABLED
+
#if TARGET_OS_IPHONE
#include <MobileGestalt.h>
#endif
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;
}
#include "SOSCircle_regressions.h"
#include "SOSRegressionUtilities.h"
+#if SOS_ENABLED
#if TARGET_OS_IPHONE
#include <MobileGestalt.h>
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;
}
#include "SOSRegressionUtilities.h"
+#if SOS_ENABLED
+
static int kTestGenerationCount = 2;
static void test_generation(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;
}
#include "SOSCircle_regressions.h"
#include "SOSRegressionUtilities.h"
-
-static int kTestTestCount = 7;
+#if SOS_ENABLED
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;
}
#include <utilities/SecCFRelease.h>
#include <stdlib.h>
-
-static int kTestTestCount = 15;
+#include "SOSRegressionUtilities.h"
static void testNullDigestVector(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;
}
#import "keychain/SecureObjectSync/SOSAccountTransaction.h"
#include <dispatch/dispatch.h>
+extern NSString* const kSOSIdentityStatusCompleteIdentity;
+extern NSString* const kSOSIdentityStatusKeyOnly;
+extern NSString* const kSOSIdentityStatusPeerOnly;
+
@class SOSAccount;
__BEGIN_DECLS
CFStringRef SOSAccountGetSOSCCStatusString(SOSCCStatus status);
SOSCCStatus SOSAccountGetSOSCCStatusFromString(CFStringRef status);
-bool SOSAccountJoinCircles(SOSAccountTransaction* aTxn, NSData* parentEvent, CFErrorRef* error);
-bool SOSAccountJoinCirclesAfterRestore(SOSAccountTransaction* aTxn, NSData* parentEvent, CFErrorRef* error);
-bool SOSAccountRemovePeersFromCircle(SOSAccount* account, CFArrayRef peers, NSData* parentEvent, CFErrorRef* error);
+bool SOSAccountJoinCircles(SOSAccountTransaction* aTxn, CFErrorRef* error);
+bool SOSAccountJoinCirclesAfterRestore(SOSAccountTransaction* aTxn, CFErrorRef* error);
+bool SOSAccountRemovePeersFromCircle(SOSAccount* account, CFArrayRef peers, 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);
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
//
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 SOSAccountRemoveBackupPublickey(SOSAccountTransaction* aTxn, CFErrorRef *error);
void SOSAccountTimerFiredSendNextMessage(SOSAccountTransaction* txn, NSString* peerid, NSString* accessGroup);
NSArray<NSDictionary *>* SOSAccountGetAllTLKs(void);
+NSArray<NSDictionary *>* SOSAccountGetSelectedTLKs(void);
+
CF_RETURNS_RETAINED CFMutableArrayRef SOSAccountCopyiCloudIdentities(SOSAccount* account);
bool SOSAccountEvaluateKeysAndCircle(SOSAccountTransaction *txn, CFErrorRef *block_error);
#include <utilities/SecCFWrappers.h>
#include <utilities/SecCFError.h>
-#include <utilities/SecADWrapper.h>
#include <utilities/SecFileLocations.h>
#include <os/activity.h>
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;
@property (readwrite) CKKSPBFileStorage<SOSAccountConfiguration*>* accountConfiguration;
@property CKKSNearFutureScheduler *performBackups;
+@property CKKSNearFutureScheduler *performRingUpdates;
@end
#endif
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];
+ [self.stateMachine haltOperation];
+#endif
}
}
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
-(bool) ensureFactoryCircles
{
- if (!self){
- return false;
- }
-
- if (!self.factory){
+ if (self.factory == nil){
return false;
}
- NSString* circle_name = (__bridge_transfer NSString*)SOSDataSourceFactoryCopyName(self.factory);
-
+ NSString* circle_name = CFBridgingRelease(SOSDataSourceFactoryCopyName(self.factory));
if (!circle_name){
return false;
}
-(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)];
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;
self.settings = [[NSUserDefaults alloc] initWithSuiteName:SOSAccountUserDefaultsSuite];
+ [self ensureFactoryCircles];
+ SOSAccountEnsureUUID(self);
+ self.accountIsChanging = false;
+
#if OCTAGON
[self setupStateMachine];
#endif
return self;
}
+- (void)startStateMachine
+{
+#if OCTAGON
+ [self.stateMachine startOperation];
+#endif
+}
+
-(BOOL)isEqual:(id) object
{
if(![object isKindOfClass:[SOSAccount class]])
- (void)kvsPerformanceCounters:(void(^)(NSDictionary <NSString *, NSNumber *> *))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);
});
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);
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);
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;
- }
- sleep(1); // make up for keygen time in password based version - let syncdefaults catch up
+ dispatch_sync(SOSCCCredentialQueue(), ^{
+ CFErrorRef syncerror = NULL;
- [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,
- };
+ 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,
+ };
+
+ 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");
- if (!SOSAccountTryUserPrivateKey(self, accountPrivateKey, &error)) {
- CFReleaseNull(accountPrivateKey);
- complete(false, (__bridge NSError *)error);
- secnotice("pairing", "SOSAccountTryUserPrivateKey failed: %@", error);
- CFReleaseNull(error);
- return;
+ 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);
+ }
}
-
- 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
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<NSString*> *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<NSString*> *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<NSString*> *completeIdentity = [peerInfoSPIDs mutableCopy];
+ if([peerInfoSPIDs count] > 0 && [privateKeySPIDs count] > 0) {
+ [ completeIdentity intersectSet:privateKeySPIDs];
+ } else {
+ completeIdentity = nil;
+ }
+
+ NSMutableSet<NSString*> *keyOnly = [privateKeySPIDs mutableCopy];
+ if([peerInfoSPIDs count] > 0 && [keyOnly count] > 0) {
+ [ keyOnly minusSet: peerInfoSPIDs ];
+ }
+
+ NSMutableSet<NSString*> *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 {
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
{
CFReleaseNull(error);
}
-- (void)triggerSync:(NSArray <NSString *> *)peers complete:(void(^)(bool success, NSError *))complete
+- (void)rpcTriggerSync:(NSArray <NSString *> *)peers complete:(void(^)(bool success, NSError *))complete
{
__block CFErrorRef localError = NULL;
__block bool res = false;
CFReleaseNull(localError);
}
-- (void)triggerBackup:(NSArray<NSString *>* _Nullable)backupPeers complete:(void (^)(NSError *error))complete
+- (void)rpcTriggerBackup:(NSArray<NSString *>* _Nullable)backupPeers complete:(void (^)(NSError *error))complete
{
__block CFErrorRef localError = NULL;
CFReleaseNull(localError);
}
+- (void)rpcTriggerRingUpdate:(void (^)(NSError *error))complete
+{
+#if OCTAGON
+ [self triggerRingUpdate];
+#endif
+ complete(NULL);
+}
+
- (void)getWatchdogParameters:(void (^)(NSDictionary* parameters, NSError* error))complete
{
// SecdWatchdog is only available in the secd/securityd - no other binary will contain that class
}
}
+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)
{
SOSDataSourceFactoryRef factory) {
SOSAccount* a = [[SOSAccount alloc] initWithGestalt:gestalt factory:factory];
- [a ensureFactoryCircles];
- SOSAccountEnsureUUID(a);
- secnotice("circleop", "Setting account.key_interests_need_updating to true in SOSAccountCreate");
- a.key_interests_need_updating = true;
+ dispatch_sync(a.queue, ^{
+ secnotice("circleop", "Setting account.key_interests_need_updating to true in SOSAccountCreate");
+ a.key_interests_need_updating = true;
+ });
return 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);
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);
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;
- }
+ [trust purgeIdentity];
}
-bool sosAccountLeaveCircle(SOSAccount* account, SOSCircleRef circle, NSData* parentData, CFErrorRef* error) {
+bool sosAccountLeaveCircle(SOSAccount* account, SOSCircleRef circle, CFErrorRef* error) {
SOSAccountTrustClassic *trust = account.trust;
SOSFullPeerInfoRef identity = trust.fullPeerInfo;
NSMutableSet* retirees = trust.retirees;
NSError* localError = nil;
- SFSignInAnalytics* parent = nil;
-
- if(parentData) {
- parent = [NSKeyedUnarchiver unarchivedObjectOfClass:[SFSignInAnalytics class] fromData:parentData error:&localError];
- }
-
SOSFullPeerInfoRef fpi = identity;
if(!fpi) return false;
CFErrorRef retiredError = NULL;
bool retval = false;
-
- SFSignInAnalytics *promoteToRetiredEvent = nil;
-
- if(parent) {
- promoteToRetiredEvent = [parent newSubTaskForEvent:@"promoteToRetiredEvent"];
- }
SOSPeerInfoRef retire_peer = SOSFullPeerInfoPromoteToRetiredAndCopy(fpi, &retiredError);
if(retiredError){
- if(promoteToRetiredEvent) {
- [promoteToRetiredEvent logRecoverableError:(__bridge NSError*)retiredError];
- }
secerror("SOSFullPeerInfoPromoteToRetiredAndCopy error: %@", retiredError);
if(error){
*error = retiredError;
CFReleaseNull(retiredError);
}
}
- if(promoteToRetiredEvent) {
- [promoteToRetiredEvent stopWithAttributes:nil];
- }
if (!retire_peer) {
secerror("Create ticket failed for peer %@: %@", fpi, localError);
} else if (SOSCircleHasPeer(circle, retire_peer, NULL)) {
if (SOSCircleUpdatePeerInfo(circle, retire_peer)) {
CFErrorRef cleanupError = NULL;
- SFSignInAnalytics *cleanupEvent = nil;
-
- if(parent) {
- 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);
}
- if(cleanupEvent) {
- [cleanupEvent stopWithAttributes:nil];
- }
CFReleaseSafe(cleanupError);
}
}
// Write retirement to Transport
CFErrorRef postError = NULL;
- SFSignInAnalytics *postRetirementEvent = nil;
-
- if(parent) {
- postRetirementEvent = [parent newSubTaskForEvent:@"postRestirementEvent"];
- }
-
if(![account.circle_transport postRetirement:SOSCircleGetName(circle) peer:retire_peer err:&postError]){
- if(postRetirementEvent) {
- [postRetirementEvent logRecoverableError:(__bridge NSError*)postError];
- }
+
secwarning("Couldn't post retirement (%@)", postError);
}
- if(postRetirementEvent) {
- [postRetirementEvent stopWithAttributes:nil];
- }
- SFSignInAnalytics *flushChangesEvent = nil;
- if(parent) {
- flushChangesEvent = [parent newSubTaskForEvent:@"flushChangesEvent"];
- }
+
if(![account.circle_transport flushChanges:&postError]){
- if(flushChangesEvent) {
- [flushChangesEvent logRecoverableError:(__bridge NSError*)postError];
- }
secwarning("Couldn't flush retirement data (%@)", postError);
}
- if(flushChangesEvent) {
- [flushChangesEvent stopWithAttributes:nil];
- }
+
CFReleaseNull(postError);
}
- SFSignInAnalytics *purgeIdentityEvent = nil;
- if(parent) {
- purgeIdentityEvent = [parent newSubTaskForEvent:@"purgeIdentityEvent"];
- }
+
SOSAccountPurgeIdentity(account);
- if(purgeIdentityEvent) {
- [purgeIdentityEvent stopWithAttributes:nil];
- }
+
retval = true;
CFReleaseNull(retire_peer);
//
-bool SOSAccountEnsureInBackupRings(SOSAccount* account) {
+- (bool)_onQueueEnsureInBackupRings {
__block bool result = false;
__block CFErrorRef error = NULL;
secnotice("backup", "Ensuring in rings");
- if(!account.backup_key){
+ dispatch_assert_queue(self.queue);
+
+ if(!self.backup_key){
return true;
}
- if(!SOSBSKBIsGoodBackupPublic((__bridge CFDataRef)account.backup_key, &error)){
+ if(!SOSBSKBIsGoodBackupPublic((__bridge CFDataRef)self.backup_key, &error)){
secnotice("backupkey", "account backup key isn't valid: %@", error);
- account.backup_key = nil;
+ self.backup_key = nil;
CFReleaseNull(error);
return false;
}
- NSData *peerBackupKey = (__bridge_transfer NSData*)SOSPeerInfoCopyBackupKey(account.peerInfo);
- if(![peerBackupKey isEqual:account.backup_key]) {
- result = SOSAccountUpdatePeerInfo(account, CFSTR("Backup public key"), &error, ^bool(SOSFullPeerInfoRef fpi, CFErrorRef *error) {
- return SOSFullPeerInfoUpdateBackupKey(fpi, (__bridge CFDataRef)(account.backup_key), error);
+ 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(localError);
// Setup backups the new way.
- SOSAccountForEachBackupView(account, ^(const void *value) {
+ SOSAccountForEachBackupView(self, ^(const void *value) {
CFStringRef viewName = asString(value, NULL);
- bool resetRing = SOSAccountValidateBackupRingForView(account, viewName, NULL);
+ bool resetRing = SOSAccountValidateBackupRingForView(self, viewName, NULL);
if(resetRing) {
- SOSAccountUpdateBackupRing(account, viewName, NULL, ^SOSRingRef(SOSRingRef existing, CFErrorRef *error) {
- SOSRingRef newRing = SOSAccountCreateBackupRingForView(account, viewName, error);
+ SOSAccountUpdateBackupRing(self, viewName, NULL, ^SOSRingRef(SOSRingRef existing, CFErrorRef *error) {
+ SOSRingRef newRing = SOSAccountCreateBackupRingForView(self, viewName, error);
return newRing;
});
}
// MARK: Joining
//
-static bool SOSAccountJoinCircle(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 = nil;
-
- if(parentEvent) {
- 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???")));
- if(parent) {
- 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);
- if(ensureFullPeerAvailableEvent) {
- [ensureFullPeerAvailableEvent stopWithAttributes:nil];
- }
+
+ require_quiet([account.trust ensureFullPeerAvailable: account err:error], fail);
SOSFullPeerInfoRef myCirclePeer = trust.fullPeerInfo;
if (SOSCircleCountPeers(trust.trustedCircle) == 0 || SOSAccountGhostResultsInReset(account)) {
// this also clears initial sync data
result = [account.trust resetCircleToOffering:aTxn userKey:user_key err:error];
} else {
- SFSignInAnalytics *acceptApplicantEvent = nil;
-
SOSAccountInitializeInitialSync(account);
if (use_cloud_peer) {
cloud_full_peer = SOSCircleCopyiCloudFullPeerInfoRef(trust.trustedCircle, NULL);
}
- if(parent) {
- 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);
require_quiet(SOSCircleAcceptRequest(circle, user_key, cloud_full_peer, SOSFullPeerInfoGetPeerInfo(myCirclePeer), &localError), finish);
finish:
if (localError){
- if(acceptApplicantEvent) {
- [acceptApplicantEvent logRecoverableError:(__bridge NSError *)(localError)];
- }
secerror("Failed to join with cloud identity: %@", localError);
CFReleaseNull(localError);
}
}
return result;
}];
- if(acceptApplicantEvent) {
- [acceptApplicantEvent stopWithAttributes:nil];
- }
+
if (use_cloud_peer) {
SOSAccountUpdateOutOfSyncViews(aTxn, SOSViewsGetAllCurrent());
- if(acceptApplicantEvent) {
- SFSignInAnalytics *updateOutOfDateSyncViewsEvent = [acceptApplicantEvent newSubTaskForEvent:@"updateOutOfDateSyncViewsEvent"];
- [updateOutOfDateSyncViewsEvent stopWithAttributes:nil];
- }
}
}
fail:
return result;
}
-static bool SOSAccountJoinCircles_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;
}
}
- success = SOSAccountJoinCircle(aTxn, user_key, use_cloud_identity, parentEvent, error);
+ success = SOSAccountJoinCircle(aTxn, user_key, use_cloud_identity, error);
require_quiet(success, done);
return success;
}
-bool SOSAccountJoinCircles(SOSAccountTransaction* aTxn, NSData* parentEvent, CFErrorRef* error) {
+bool SOSAccountJoinCircles(SOSAccountTransaction* aTxn, CFErrorRef* error) {
secnotice("circleOps", "Normal path circle join (SOSAccountJoinCircles)");
- return SOSAccountJoinCircles_internal(aTxn, false, parentEvent, error);
+ return SOSAccountJoinCircles_internal(aTxn, false, error);
}
-bool SOSAccountJoinCirclesAfterRestore(SOSAccountTransaction* aTxn, NSData* parentEvent, CFErrorRef* error) {
+bool SOSAccountJoinCirclesAfterRestore(SOSAccountTransaction* aTxn, CFErrorRef* error) {
secnotice("circleOps", "Joining after restore (SOSAccountJoinCirclesAfterRestore)");
- return SOSAccountJoinCircles_internal(aTxn, true, parentEvent, error);
+ return SOSAccountJoinCircles_internal(aTxn, true, error);
}
-bool SOSAccountRemovePeersFromCircle(SOSAccount* account, CFArrayRef peers, NSData* parentEvent, CFErrorRef* error)
+bool SOSAccountRemovePeersFromCircle(SOSAccount* account, CFArrayRef peers, CFErrorRef* error)
{
-
- NSError* localError = nil;
- SFSignInAnalytics* parent = nil;
-
- if(parentEvent) {
- parent = [NSKeyedUnarchiver unarchivedObjectOfClass:[SFSignInAnalytics class] fromData:parentEvent error:&localError];
- }
-
bool result = false;
CFMutableSetRef peersToRemove = NULL;
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;
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);
-
- SFSignInAnalytics *generationSignatureUpdateEvent = nil;
- if(parent) {
- generationSignatureUpdateEvent = [parent newSubTaskForEvent:@"generationSignatureUpdateEvent"];
- }
-
success = SOSAccountGenerationSignatureUpdate(account, error);
- if(error && *error){
- NSError* signatureUpdateError = (__bridge NSError*)*error;
- if(generationSignatureUpdateEvent) {
- [generationSignatureUpdateEvent logUnrecoverableError:signatureUpdateError];
- }
- }
- if(generationSignatureUpdateEvent) {
- [generationSignatureUpdateEvent stopWithAttributes:nil];
- }
- } else success = true;
+ } else {
+ success = true;
+ }
if (success && leaveCircle) {
secnotice("circleOps", "Leaving circle by client request (SOSAccountRemovePeersFromCircle)");
- success = sosAccountLeaveCircle(account, circle, parentEvent, error);
+ success = sosAccountLeaveCircle(account, circle, error);
}
done:
}];
- if(result) {
+ if (result) {
CFStringSetPerformWithDescription(peersToRemove, ^(CFStringRef description) {
secnotice("circleOps", "Removed Peers from circle %@", description);
});
}
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;
dispatch_group_async(group, queue, ^{
[trust modifyCircle:account.circle_transport err:error action:^(SOSCircleRef circle) {
secnotice("circleOps", "Leaving circle by client request (Bail)");
- return sosAccountLeaveCircle(account, circle, nil, error);
+ return sosAccountLeaveCircle(account, circle, error);
}];
});
dispatch_time_t milestone = dispatch_time(DISPATCH_TIME_NOW, limit_in_seconds * NSEC_PER_SEC);
return result;
}
-
//
// MARK: Application
//
SOSEngineInitializePeerCoder((SOSEngineRef)[account.kvs_message_transport SOSTransportMessageGetEngine], trust.fullPeerInfo, peer, &localError);
if (localError)
secnotice("updates", "can't initialize transport for peer %@ with %@ (%@)", peer, trust.fullPeerInfo, localError);
- CFReleaseSafe(localError);
+ CFReleaseNull(localError);
}
});
return (__bridge CFTypeRef)([trust.expansion objectForKey:(__bridge NSString* _Nonnull)(key)]);
}
-
-
bool SOSAccountAddEscrowToPeerInfo(SOSAccount* account, SOSFullPeerInfoRef myPeer, CFErrorRef *error){
bool success = false;
return success;
}
-void SOSAccountRecordRetiredPeersInCircle(SOSAccount* account) {
- if (![account isInCircle:NULL]) {
+- (void)_onQueueRecordRetiredPeersInCircle {
+
+ dispatch_assert_queue(self.queue);
+
+ if (![self isInCircle:NULL]) {
return;
}
__block bool updateRings = false;
- SOSAccountTrustClassic *trust = account.trust;
- [trust modifyCircle:account.circle_transport err:NULL action:^bool (SOSCircleRef circle) {
+ SOSAccountTrustClassic *trust = self.trust;
+ [trust modifyCircle:self.circle_transport err:NULL action:^bool (SOSCircleRef circle) {
__block bool updated = false;
CFSetForEach((__bridge CFMutableSetRef)trust.retirees, ^(CFTypeRef element){
SOSPeerInfoRef retiree = asSOSPeerInfo(element);
updated = true;
secnotice("retirement", "Updated retired peer %@ in %@", retiree, circle);
CFErrorRef cleanupError = NULL;
- if (![account.trust cleanupAfterPeer:account.kvs_message_transport circleTransport:account.circle_transport seconds:RETIREMENT_FINALIZATION_SECONDS circle:circle cleanupPeer:retiree err:&cleanupError])
+ if (![self.trust cleanupAfterPeer:self.kvs_message_transport circleTransport:self.circle_transport seconds:RETIREMENT_FINALIZATION_SECONDS circle:circle cleanupPeer:retiree err:&cleanupError])
secerror("Error cleanup up after peer (%@): %@", retiree, cleanupError);
CFReleaseSafe(cleanupError);
updateRings = true;
return updated;
}];
if(updateRings) {
- SOSAccountProcessBackupRings(account, NULL);
+ SOSAccountProcessBackupRings(self);
}
}
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){
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];
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;
return applicant;
}
+#if OCTAGON
+static void
+AddStrippedTLKs(NSMutableArray* results, NSArray<CKKSKeychainBackedKey*>* 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)
}
static void
-AddViewManagerResults(NSMutableArray *results, NSMutableSet *seenUUID)
+AddViewManagerResults(NSMutableArray *results, NSMutableSet *seenUUID, bool selectedTLKsOnly)
{
#if OCTAGON
- CKKSViewManager* manager = [CKKSViewManager manager];
-
- NSDictionary<NSString *,NSString *> *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);
+ NSError* localError = nil;
+ NSArray<CKKSKeychainBackedKey*>* tlks = [[CKKSViewManager manager] currentTLKsFilteredByPolicy:selectedTLKsOnly error:&localError];
+
+ if(localError) {
+ secnotice("piggy", "unable to fetch TLKs: %@", localError);
+ return;
}
+
+ AddStrippedTLKs(results, tlks, seenUUID, true);
#endif
}
+NSArray<NSDictionary *>*
+SOSAccountGetSelectedTLKs(void)
+{
+ NSMutableArray<NSDictionary *>* results = [NSMutableArray array];
+ NSMutableSet *seenUUID = [NSMutableSet set];
+
+ AddViewManagerResults(results, seenUUID, true);
+
+ return results;
+}
+
NSArray<NSDictionary *>*
SOSAccountGetAllTLKs(void)
NSMutableArray<NSDictionary *>* 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 = @{
NSMutableArray<NSData *>* encodedIdenities = [NSMutableArray array];
NSArray<NSDictionary *>* tlks = nil;
- 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];
+ 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];
+ }
+ CFRelease(identities);
}
- CFRelease(identities);
- }
- if (flags & kSOSInitialSyncFlagTLKs) {
- tlks = SOSAccountGetAllTLKs();
+
+ if (flags & kSOSInitialSyncFlagTLKs) {
+ tlks = SOSAccountGetAllTLKs();
+ }
}
return CFBridgingRetain(SOSPiggyCreateInitialSyncData(encodedIdenities, tlks));
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));
{
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) {
*/
OctagonFlag* SOSFlagTriggerBackup = (OctagonFlag*)@"trigger_backup";
+OctagonFlag* SOSFlagTriggerRingUpdate = (OctagonFlag*)@"trigger_ring_update";
OctagonState* SOSStateReady = (OctagonState*)@"ready";
OctagonState* SOSStateError = (OctagonState*)@"error";
OctagonState* SOSStatePerformBackup = (OctagonState*)@"perform_backup";
+OctagonState* SOSStatePerformRingUpdate = (OctagonState*)@"perform_ring_update";
static NSDictionary<OctagonState*, NSNumber*>* SOSStateMap(void) {
static NSDictionary<OctagonState*, NSNumber*>* map = nil;
SOSStateReady: @0U,
SOSStateError: @1U,
SOSStatePerformBackup: @2U,
+ SOSStatePerformRingUpdate: @3U,
};
});
return map;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
set = [NSSet setWithArray:@[
- SOSFlagTriggerBackup
+ SOSFlagTriggerBackup,
+ SOSFlagTriggerRingUpdate,
]];
});
return set;
+ (NSURL *)urlForSOSAccountSettings {
- return (__bridge NSURL *)SecCopyURLForFileInKeychainDirectory(CFSTR("SOSAccountSettings.pb"));
+ return (__bridge_transfer NSURL *)SecCopyURLForFileInKeychainDirectory(CFSTR("SOSAccountSettings.pb"));
}
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);
[self addBackupFlag];
}];
+ self.performRingUpdates = [[CKKSNearFutureScheduler alloc] initWithName:@"performRingUpdates"
+ initialDelay:5*NSEC_PER_SEC
+ expontialBackoff:2.0
+ maximumDelay:15*60*NSEC_PER_SEC
+ keepProcessAlive:YES
+ dependencyDescriptionCode:CKKSResultDescriptionNone
+ block:^{
+ STRONGIFY(self);
+ [self addRingUpdateFlag];
+ }];
+
SOSAccountConfiguration *conf = self.accountConfiguration.storage;
if (conf.pendingBackupPeers.count) {
[self addBackupFlag];
}
-
- [self.stateMachine startOperation];
+ if (conf.ringUpdateFlag) {
+ [self addRingUpdateFlag];
+ }
}
+/*
+ * Flag adding to state machine
+ */
+
- (void)addBackupFlag {
OctagonPendingFlag *pendingFlag = [[OctagonPendingFlag alloc] initWithFlag:SOSFlagTriggerBackup
conditions:OctagonPendingConditionsDeviceUnlocked];
[self.stateMachine handlePendingFlag:pendingFlag];
}
+- (void)addRingUpdateFlag {
+ OctagonPendingFlag *pendingFlag = [[OctagonPendingFlag alloc] initWithFlag:SOSFlagTriggerRingUpdate
+ conditions:OctagonPendingConditionsDeviceUnlocked];
+ [self.stateMachine handlePendingFlag:pendingFlag];
+}
+
+//Mark: -- Set up state for state machine
+
+
- (void)triggerBackupForPeers:(NSArray<NSString*>*)backupPeers
{
- dispatch_sync(self.stateMachineQueue, ^{
+ NSMutableSet *pending = [NSMutableSet set];
+ if (backupPeers) {
+ [pending addObjectsFromArray:backupPeers];
+ }
+
+ WEAKIFY(self);
+ dispatch_async(self.stateMachineQueue, ^{
+ STRONGIFY(self);
+
SOSAccountConfiguration *storage = self.accountConfiguration.storage;
- NSMutableSet *pending = [NSMutableSet set];
if (storage.pendingBackupPeers) {
[pending addObjectsFromArray:storage.pendingBackupPeers];
}
- if (backupPeers) {
- [pending addObjectsFromArray:backupPeers];
- }
storage.pendingBackupPeers = [[pending allObjects] mutableCopy];
[self.accountConfiguration setStorage:storage];
[self.performBackups trigger];
- secnotice("sos-sm", "trigger backup for peers: %@", backupPeers);
+ secnotice("sos-sm", "trigger backup for peers: %@ at %@",
+ backupPeers, self.performBackups.nextFireTime);
});
}
+- (void)triggerRingUpdate
+{
+ WEAKIFY(self);
+ dispatch_async(self.stateMachineQueue, ^{
+ STRONGIFY(self);
+ SOSAccountConfiguration *storage = self.accountConfiguration.storage;
+ storage.ringUpdateFlag = YES;
+ [self.accountConfiguration setStorage:storage];
+ [self.performRingUpdates trigger];
+ secnotice("sos-sm", "trigger ring update at %@",
+ self.performRingUpdates.nextFireTime);
+ });
+}
+
+//Mark: -- State machine and opertions
+
+- (OctagonStateTransitionOperation *)performBackup {
+
+ WEAKIFY(self);
+ return [OctagonStateTransitionOperation named:@"perform-backup-state"
+ intending:SOSStateReady
+ errorState:SOSStateError
+ withBlockTakingSelf:^void(OctagonStateTransitionOperation * _Nonnull op) {
+ STRONGIFY(self);
+ SOSAccountConfiguration *storage = self.accountConfiguration.storage;
+
+ secnotice("sos-sm", "performing backup for %@", storage.pendingBackupPeers);
+
+ if (storage.pendingBackupPeers.count) {
+ SOSCCRequestSyncWithBackupPeerList((__bridge CFArrayRef)storage.pendingBackupPeers);
+ [storage clearPendingBackupPeers];
+ }
+ [self.accountConfiguration setStorage:storage];
+
+ op.nextState = SOSStateReady;
+ }];
+}
+
+- (OctagonStateTransitionOperation *)performRingUpdate {
+
+ WEAKIFY(self);
+ return [OctagonStateTransitionOperation named:@"perform-ring-update"
+ intending:SOSStateReady
+ errorState:SOSStateError
+ withBlockTakingSelf:^void(OctagonStateTransitionOperation * _Nonnull op) {
+ STRONGIFY(self);
+
+ 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);
+ [self _onQueueEnsureInBackupRings];
+
+ CFErrorRef localError = NULL;
+ if(![self.circle_transport flushChanges:&localError]){
+ secerror("flush circle failed %@", localError);
+ }
+ CFReleaseNull(localError);
+
+ if(!SecCKKSTestDisableSOS()) {
+ SOSAccountNotifyEngines(self);
+ }
+ }
+ }];
+
+ op.nextState = SOSStateReady;
+ }];
+
+}
+
+
- (CKKSResultOperation<OctagonStateTransitionOperationProtocol>* _Nullable)_onqueueNextStateMachineTransition:(OctagonState*)currentState
flags:(nonnull OctagonFlags *)flags
pendingFlags:(nonnull id<OctagonStateOnqueuePendingFlagHandler>)pendingFlagHandler
{
dispatch_assert_queue(self.stateMachineQueue);
- WEAKIFY(self);
-
- secnotice("sos-sm", "currentState: %@ [flags: %@]", currentState, flags);
+ secnotice("sos-sm", "Entering state: %@ [flags: %@]", currentState, flags);
if ([currentState isEqualToString:SOSStateReady]) {
if([flags _onqueueContains:SOSFlagTriggerBackup]) {
return [OctagonStateTransitionOperation named:@"perform-backup-flag"
entering:SOSStatePerformBackup];
}
- secnotice("sos-sm", "Entering state ready");
+
+ if ([flags _onqueueContains:SOSFlagTriggerRingUpdate]) {
+ [flags _onqueueRemoveFlag:SOSFlagTriggerRingUpdate];
+ return [OctagonStateTransitionOperation named:@"perform-ring-update-flag"
+ entering:SOSStatePerformRingUpdate];
+ }
return nil;
+
} else if ([currentState isEqualToString:SOSStateError]) {
- secnotice("sos-sm", "Entering state error");
return nil;
- } else if ([currentState isEqualToString:SOSStatePerformBackup]) {
-
- return [OctagonStateTransitionOperation named:@"perform-backup-state"
- intending:SOSStateReady
- errorState:SOSStateError
- withBlockTakingSelf:^void(OctagonStateTransitionOperation * _Nonnull op) {
- STRONGIFY(self);
- SOSAccountConfiguration *storage = self.accountConfiguration.storage;
-
- secnotice("sos-sm", "performing backup for %@", storage.pendingBackupPeers);
+ } else if ([currentState isEqualToString:SOSStatePerformRingUpdate]) {
+ return [self performRingUpdate];
- if (storage.pendingBackupPeers.count) {
- SOSCCRequestSyncWithBackupPeerList((__bridge CFArrayRef)storage.pendingBackupPeers);
- [storage clearPendingBackupPeers];
- }
- [self.accountConfiguration setStorage:storage];
-
- op.nextState = SOSStateReady;
- }];
+ } else if ([currentState isEqualToString:SOSStatePerformBackup]) {
+ return [self performBackup];
}
return nil;
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);
+ }
});
}
})){
return result;
}
- SOSAccountProcessBackupRings(account, NULL);
+ SOSAccountProcessBackupRings(account);
+ account.need_backup_peers_created_after_backup_key_set = true;
+ account.circle_rings_retirements_need_attention = true;
return true;
}
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;
}
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) {
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;
message AccountConfiguration {
repeated string pendingBackupPeers = 1;
+ optional bool ringUpdateFlag = 2;
}
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);
}
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);
}
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));
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;
}
}
void SOSAccountSetParameters(SOSAccount* account, CFDataRef parameters) {
- account.accountKeyDerivationParamters = (__bridge NSData *) parameters;
+ account.accountKeyDerivationParameters = (__bridge NSData *) parameters;
}
bool SOSAccountValidateAccountCredential(SOSAccount* account, SecKeyRef accountPrivateKey, CFErrorRef *error)
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;
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;
}
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,
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;
}
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;
#include "keychain/SecureObjectSync/SOSPeerInfoPriv.h"
#include "keychain/SecureObjectSync/SOSAuthKitHelpers.h"
#import "Analytics/Clients/SOSAnalytics.h"
+#import <Security/SecBase64.h>
#include "utilities/SecTrace.h"
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:
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;
}
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 <SOSTrustedDeviceAttributes *> * _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);
SOSCircleClearMyGhosts(newCircle, account.peerInfo);
SOSCircleRemoveRetired(newCircle, NULL);
SOSCircleRemoveiCloudIdentities(newCircle);
+ SOSCircleRemoveWindowsPeers(newCircle);
+ SOSCircleRemovePeersNotInMidlist(newCircle);
int npeers = SOSCircleCountPeers(newCircle);
CFReleaseNull(newCircle);
return npeers == 0;
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;
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;
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;
-
- 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"))) {
-
- CFDictionaryRef delQuery = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
- kSecClass, kSecClassKey,
- kSecAttrKeyClass, kSecAttrKeyClassPrivate,
- kSecAttrSynchronizable, kSecAttrSynchronizableAny,
- kSecAttrApplicationLabel, candidate,
- NULL);
-
- 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);
- }
+static NSUInteger SOSGhostBustiCloudIdentityPrivateKeys(SOSAccount *account) {
+ __block NSUInteger cleaned = 0;
+
+ [ account iCloudIdentityStatus_internal:^(NSDictionary *tableSpid, NSError *error) {
+ if(!tableSpid) {
+ secnotice("ghostBust", "Couldn't work on iCloud Identities (%@)", error);
+ }
+
+ size_t keysToRemove = [tableSpid[kSOSIdentityStatusKeyOnly] count];
+
+ 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));
}];
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;
}
#include "SOSAccountLog.h"
#include <stdio.h>
#include <stdlib.h>
-#include <assert.h>
#include <AssertMacros.h>
#include "SOSAccountPriv.h"
#include "SOSViews.h"
#include <stdio.h>
#include <stdlib.h>
-#include <assert.h>
#include <AssertMacros.h>
#include "SOSViews.h"
{
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)
}
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);
{
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;
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;
}
{
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)
{
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;
}
{
{
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];
}
{
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) {
{
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;
}
}
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);
{
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) {
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);
}
}
}
CFReleaseNull(oldPI);
- SOSAccountEnsureRecoveryRing(account);
[account performTransaction:^(SOSAccountTransaction * _Nonnull txn) {
+ SOSAccountEnsureRecoveryRing(account);
+
secnotice("circleop", "Setting account.key_interests_need_updating to true in SOSAccountCreateFromDER");
account.key_interests_need_updating = true;
}];
#include <corecrypto/ccder.h>
#include <AssertMacros.h>
-#include <assert.h>
#import <notify.h>
@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;
@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;
-(id) initWithGestalt:(CFDictionaryRef)gestalt factory:(SOSDataSourceFactoryRef)factory;
-//- (void)startStateMachine;
+- (void)startStateMachine;
void SOSAccountAddSyncablePeerBlock(SOSAccount* a,
CFStringRef ds_name,
#if OCTAGON
- (void)triggerBackupForPeers:(NSArray<NSString*>*)backupPeer;
+- (void)triggerRingUpdate;
#endif
CF_RETURNS_RETAINED
CFDictionaryRef SOSAccountHandleRetirementMessages(SOSAccount* account, CFDictionaryRef circle_retirement_messages, CFErrorRef *error);
-void SOSAccountRecordRetiredPeersInCircle(SOSAccount* account);
-
bool SOSAccountHandleUpdateCircle(SOSAccount* account,
SOSCircleRef prospective_circle,
bool writeUpdate,
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);
void SOSAccountSetUserPublicTrustedForTesting(SOSAccount* account);
void SOSAccountPurgeIdentity(SOSAccount*);
-bool sosAccountLeaveCircle(SOSAccount* account, SOSCircleRef circle, NSData* parentData, CFErrorRef* error);
+bool sosAccountLeaveCircle(SOSAccount* account, SOSCircleRef circle, CFErrorRef* error);
bool SOSAccountForEachRing(SOSAccount* account, SOSRingRef (^action)(CFStringRef name, SOSRingRef ring));
bool SOSAccountUpdateBackUp(SOSAccount* account, CFStringRef viewname, CFErrorRef *error);
void SOSAccountEnsureRecoveryRing(SOSAccount* account);
-bool SOSAccountEnsureInBackupRings(SOSAccount* account);
bool SOSAccountEnsurePeerRegistration(SOSAccount* account, CFErrorRef *error);
#include "keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.h"
#include "keychain/SecureObjectSync/SOSInternal.h"
-#include "SecADWrapper.h"
#include "keychain/SecureObjectSync/SOSRecoveryKeyBag.h"
#include "keychain/SecureObjectSync/SOSRingRecovery.h"
CFReleaseNull(rkbg);
if(SOSPeerInfoHasBackupKey(account.trust.peerInfo)) {
- SOSAccountProcessBackupRings(account, error);
+ SOSAccountProcessBackupRings(account);
}
account.circle_rings_retirements_need_attention = true;
result = true;
}
void SOSAccountEnsureRecoveryRing(SOSAccount* account) {
+ dispatch_assert_queue(account.queue);
+
static SOSRecoveryKeyBagRef oldRingRKBG = NULL;
SOSRecoveryKeyBagRef acctRKBG = SOSAccountCopyRecoveryKeyBagEntry(kCFAllocatorDefault, account, NULL);
if(!CFEqualSafe(acctRKBG, oldRingRKBG)) {
}
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];
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;
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
}
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];
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) {
}
self.initialUnsyncedViews = (__bridge_transfer NSMutableSet<NSString*>*)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) {
bool isInCircle = [self.account isInCircle:NULL];
if (isInCircle && self.peersToRequestSync) {
- SOSCCRequestSyncWithPeers((__bridge CFSetRef)(self.peersToRequestSync));
+ NSMutableSet<NSString*>* worklist = self.peersToRequestSync;
+ self.peersToRequestSync = nil;
+ SOSCCRequestSyncWithPeers((__bridge CFSetRef)(worklist));
}
- self.peersToRequestSync = nil;
if (isInCircle) {
SOSAccountEnsureSyncChecking(self.account);
}
if(self.account.circle_rings_retirements_need_attention){
- SOSAccountRecordRetiredPeersInCircle(self.account);
-
- SOSAccountEnsureRecoveryRing(self.account);
- SOSAccountEnsureInBackupRings(self.account);
-
- CFErrorRef localError = NULL;
- if(![self.account.circle_transport flushChanges:&localError]){
- secerror("flush circle failed %@", localError);
- }
- CFReleaseSafe(localError);
-
+ self.account.circle_rings_retirements_need_attention = false;
+#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
SOSUpdateKeyInterest(self.account);
}
- self.account.circle_rings_retirements_need_attention = false;
self.account.engine_peer_state_needs_repair = false;
[self.account flattenToSaveBlock];
}
// 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 &&
-(id)init
{
- self = [super init];
- if(self)
- {
+ if ((self = [super init])) {
self.retirees = [NSMutableSet set];
self.fullPeerInfo = NULL;
self.trustedCircle = NULL;
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;
-(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;
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);
secnotice("account", "Key state: accountKey %@, previousAccountKey %@, old_circle_key %@",
account.accountKey, account.previousAccountKey, old_circle_key);
- if (sosAccountLeaveCircle(account, newCircle, nil, error)) {
+ if (sosAccountLeaveCircle(account, newCircle, error)) {
secnotice("circleOps", "Leaving circle by newcircle state");
circleToPush = newCircle;
} else {
&& !(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;
}
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 {
// 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;
}
}
}
--(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 sosAccountLeaveCircle(account, circle, parentEvent, error);
+ return sosAccountLeaveCircle(account, circle, error);
}];
self.departureCode = kSOSWithdrewMembership;
bool result = true;
secnotice("circleOps", "Leaving circle by client request");
result &= [self modifyCircle:account.circle_transport err:error action:^(SOSCircleRef circle) {
- return sosAccountLeaveCircle(account, circle, nil, error);
+ return sosAccountLeaveCircle(account, circle, error);
}];
account.backup_key = nil;
self.departureCode = kSOSWithdrewMembership;
-(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];
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];
__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");
-(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;
#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 {
}
-(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;
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 {
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)
+ if(!localUpdate && CFEqualSafe(peerID, SOSRingGetLastModifier(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));
// 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
}
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;
__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);
} else {
CFErrorRef signingError = NULL;
if (fpi && SOSRingConcordanceSign(newRing, fpi, &signingError)) {
+ secnotice("ring", "concordance signed");
ringToPush = newRing;
ringAction = accept;
} else {
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);
-(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;
#import "keychain/SecureObjectSync/SOSAccountTrustClassic+Expansion.h"
#import "keychain/SecureObjectSync/SOSAccountTrustClassic+Identity.h"
#import "keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h"
+#import <SecurityFoundation/SFSigningOperation.h>
+#import <SecurityFoundation/SFKey.h>
+#import <SecurityFoundation/SFKey_Private.h>
+#import <SecurityFoundation/SFDigestOperation.h>
#if __OBJC2__
#import "Analytics/Clients/SOSAnalytics.h"
#endif // __OBJC2__
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) ||
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) ||
#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);
// 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];
}
- CFReleaseNull(full_key);
+ CFReleaseNull(fullKey);
CFReleaseNull(octagonSigningFullKey);
CFReleaseNull(octagonEncryptionFullKey);
CFReleaseNull(keyName);
// 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);
//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;
-(id)init
{
- self = [super init];
- if(self)
- {
+ if ((self = [super init])) {
self.retirees = [NSMutableSet set];
self.fullPeerInfo = NULL;
self.trustedCircle = NULL;
-(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);
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;
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);
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);
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);
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,
-(SOSEngineRef) getDataSourceEngine:(SOSDataSourceFactoryRef)factory
{
+ // This is at least a piece of <rdar://problem/59045931> 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);
}
void SOSAccountNotifyEngines(SOSAccount* account)
{
+ dispatch_assert_queue(account.queue);
+
SOSAccountTrustClassic *trust = account.trust;
SOSFullPeerInfoRef identity = trust.fullPeerInfo;
SOSCircleRef circle = trust.trustedCircle;
// 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) {
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);
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];
}
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.");
} else {
SOSAccountSetUnTrustedUserPublicKey(account, newKey);
CFReleaseNull(newKey);
- SOSAccountSetParameters(account, newParameters);
+ SOSAccountSetParameters(account, pbkdfParams);
if(SOSAccountRetryUserCredentials(account)) {
secnotice("circleOps", "Successfully used cached password with new parameters");
}
CFReleaseNull(newKey);
- CFReleaseNull(newParameters);
+ CFReleaseNull(pbkdfParams);
return success;
}
}
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){
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
-(id) initWithActiveMIDS: (NSSet <SOSTrustedDeviceAttributes *> *) 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(!theMidList) return nil;
- _midList = theMidList;
+ 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;
+
+ 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;
}
#include <Security/SecRecoveryKey.h>
#include "SOSKeyedPubKeyIdentifier.h"
#include "keychain/SecureObjectSync/SOSInternal.h"
-#include "SecADWrapper.h"
#include "SecCFAllocator.h"
CFStringRef bskbRkbgPrefix = CFSTR("RK");
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);
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;
}
#include "keychain/SecureObjectSync/SOSDataSource.h"
+#include "utilities/simulatecrash_assert.h"
+
__BEGIN_DECLS
enum {
#include <corecrypto/ccsha2.h>
#include <stdlib.h>
-#include <assert.h>
+#include <utilities/simulatecrash_assert.h>
CFGiblisWithCompareFor(SOSCircle);
#include <utilities/der_plist_internal.h>
#include <corecrypto/ccder.h>
#include <stdlib.h>
-#include <assert.h>
#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);
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));
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);
}
#include <CoreFoundation/CoreFoundation.h>
#include "keychain/SecureObjectSync/SOSGenCount.h"
+#include <security_utilities/simulatecrash_assert.h>
+
enum {
kOnlyCompatibleVersion = 1, // Sometime in the future this name will be improved to reflect history.
kAlwaysIncompatibleVersion = UINT64_MAX,
#include <Security/SecureObjectSync/SOSTypes.h>
#include <Security/SecureObjectSync/SOSPeerInfo.h>
-#import <Security/SFSignInAnalytics.h>
__BEGIN_DECLS
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
};
*/
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
@return if we waited successfully
*/
bool SOSCCWaitForInitialSync(CFErrorRef* error);
-bool SOSCCWaitForInitialSyncWithAnalytics(CFDataRef parentEvent, CFErrorRef* error);
/*!
@function SOSCCCanAuthenticate
@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);
/*!
@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 SOSCCAccountSetToNew
@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
*/
bool SOSCCRemoveThisDeviceFromCircle(CFErrorRef* error);
-bool SOSCCRemoveThisDeviceFromCircleWithAnalytics(CFDataRef parentEvent, CFErrorRef* error);
/*!
@function SOSCCRemoveThisDeviceFromCircle
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);
*/
bool SOSCCViewSet(CFSetRef enabledviews, CFSetRef disabledviews);
-bool SOSCCViewSetWithAnalytics(CFSetRef enabledviews, CFSetRef disabledviews, CFDataRef parentEvent);
/*
Security Attributes for PeerInfos
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);
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;
}, 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 simple_bool_error_request(enum SecXPCOperation op, CFErrorRef* error)
{
__block bool result = false;
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;
})) {
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)
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);
}, 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);
}, 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);
}
-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);
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(^{
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(^{
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(^{
}, 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);
}, NULL)
}
-bool SOSCCRemovePeersFromCircleWithAnalytics(CFArrayRef peers, CFDataRef parentEvent, CFErrorRef* error)
+bool SOSCCRemoveThisDeviceFromCircle(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)
-}
+ IF_SOS_DISABLED {
+ secdebug("circleOps", "SOS disabled for this platform");
+ setSOSDisabledError(error);
+ return false;
+ }
-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);
+ do_if_registered(soscc_RemoveThisDeviceFromCircle, error);
+
+ return simple_bool_error_request(kSecXPCOpRemoveThisDeviceFromCircle, error);
}, NULL)
}
-bool SOSCCRemoveThisDeviceFromCircle(CFErrorRef* error)
-{
+bool SOSCCLoggedIntoAccount(CFErrorRef* error) {
sec_trace_enter_api(NULL);
sec_trace_return_bool_api(^{
- do_if_registered(soscc_RemoveThisDeviceFromCircle, error);
-
- return simple_bool_error_request(kSecXPCOpRemoveThisDeviceFromCircle, error);
+ 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);
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);
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);
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);
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);
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);
}
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);
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);
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);
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);
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);
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);
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);
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);
}
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;
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);
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);
}
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);
}
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);
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);
}
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);
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;
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);
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(^{
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(^{
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;
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;
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")));
}
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);
}
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);
}
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);
}
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);
}
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(^{
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);
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);
}
SOSViewResultCode SOSCCView(CFStringRef view, SOSViewActionCode actionCode, CFErrorRef *error) {
+ IF_SOS_DISABLED {
+ secdebug("circleOps", "SOS disabled for this platform");
+ setSOSDisabledError(error);
+ return kSOSCCGeneralViewError;
+ }
+
if(actionCode == kSOSCCViewQuery) {
uint64_t circleStat = SOSGetCachedCircleBitmask();
if(circleStat & CC_STATISVALID) {
bool SOSCCViewSet(CFSetRef enabledViews, CFSetRef disabledViews) {
+ IF_SOS_DISABLED {
+ secdebug("circleOps", "SOS disabled for this platform");
+ return false;
+ }
+
CFErrorRef *error = NULL;
__block bool result = false;
}, 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("|"));
}
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);
}
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);
}
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(^{
}
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);
}
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);
}
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(^{
}
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, ^{
}
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(^{
}
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);
static id<SOSControlProtocol>
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<SOSControlProtocol>)gSecurityd->soscc_status();
static id<SOSControlProtocol>
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<SOSControlProtocol>)gSecurityd->soscc_status();
#include <xpc/xpc.h>
#include <Security/SecKey.h>
+#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
#include <corecrypto/ccder.h>
#include <utilities/iCloudKeychainTrace.h>
-#include <utilities/SecADWrapper.h>
#include "AssertMacros.h"
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;
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;
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;
privateKey = SOSFullPeerInfoCopyDeviceKey(myPeerInfo, &localError);
require_quiet(privateKey, errOut);
- myRef = SecOTRFullIdentityCreateFromSecKeyRef(allocator, privateKey, &localError);
+ myRef = SecOTRFullIdentityCreateFromSecKeyRefSOS(allocator, privateKey, &localError);
require_quiet(myRef, errOut);
CFReleaseNull(privateKey);
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);
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) {
#import <Foundation/Foundation.h>
#import <Foundation/NSXPCConnection.h>
#import <objc/runtime.h>
+#import <Security/SecXPCHelper.h>
+#include <utilities/debugging.h>
#import "keychain/SecureObjectSync/SOSTypes.h"
#import "keychain/SecureObjectSync/SOSControlHelper.h"
void
_SOSControlSetupInterface(NSXPCInterface *interface)
{
- static NSMutableSet *errClasses;
+ NSSet<Class> *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(triggerSync: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(triggerBackup:complete:) 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];
+ }
+ @catch(NSException* e) {
+ secerror("Could not configure SOSControlHelper: %@", e);
+ @throw e;
+ }
}
[self.account importInitialSyncCredentials:items complete:complete];
}
-- (void)triggerSync:(NSArray <NSString *> *)peers complete:(void(^)(bool success, NSError *))complete
+- (void)rpcTriggerSync:(NSArray <NSString *> *)peers complete:(void(^)(bool success, NSError *))complete
{
- if (![self checkEntitlement:(__bridge NSString *)kSecEntitlementKeychainCloudCircle]) {
- complete(false, [NSError errorWithDomain:(__bridge NSString *)kSOSErrorDomain code:kSOSEntitlementMissing userInfo:NULL]);
- return;
- }
-
- [self.account triggerSync:peers complete:complete];
+ [self.account rpcTriggerSync:peers complete:complete];
}
- (void)getWatchdogParameters:(void (^)(NSDictionary* parameters, NSError* error))complete
[self.account ghostBustInfo:complete];
}
-- (void)triggerBackup:(NSArray<NSString *>* _Nullable)backupPeers complete:(void (^)(NSError *error))complete
+- (void)iCloudIdentityStatus: (void (^)(NSData *json, NSError *error))complete {
+ [self.account iCloudIdentityStatus: complete];
+}
+
+- (void)rpcTriggerBackup:(NSArray<NSString *>* _Nullable)backupPeers complete:(void (^)(NSError *error))complete
{
- [self.account triggerBackup:backupPeers complete:complete];
+ [self.account rpcTriggerBackup:backupPeers complete:complete];
+}
+
+- (void)rpcTriggerRingUpdate:(void (^)(NSError *))complete {
+ [self.account rpcTriggerRingUpdate:complete];
+}
+
+- (void)iCloudIdentityStatus_internal:(void (^)(NSDictionary *, NSError *))complete {
+ [self.account iCloudIdentityStatus_internal:complete];
}
- (instancetype)initSOSConnectionWithConnection:(NSXPCConnection *)connection account:(SOSAccount *)account
{
- self = [super initSOSClientWithAccount:account];
- if (self) {
+ if ((self = [super initSOSClientWithAccount:account])) {
self.connection = connection;
}
return self;
#include <AssertMacros.h>
-#include <CommonCrypto/CommonRandomSPI.h>
#include <utilities/SecCFWrappers.h>
#include <utilities/SecCFError.h>
#include <utilities/SecBuffer.h>
-#include <corecrypto/ccec.h>
+#import <corecrypto/ccec.h>
+#import <corecrypto/ccrng.h>
#if 0 && defined(CCEC_RFC6637_DEBUG_KEYS)
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);
#include <utilities/iCloudKeychainTrace.h>
#include <utilities/SecCoreCrypto.h>
#include <utilities/SecFileLocations.h>
-#include <utilities/SecADWrapper.h>
#include <utilities/SecTrace.h>
-
+#include "utilities/SecCoreAnalytics.h"
#include <AssertMacros.h>
#include <CoreFoundation/CoreFoundation.h>
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
//
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);
}
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;
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)) {
});
}
+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");
syncTime = now - peerModificationAbsoluteTime;
}
- SecADClientPushValueForDistributionKey(known ? kSecADSecurityKnownItemSyncTimeKey : kSecADSecurityNewItemSyncTimeKey,
- SecBucket2Significant(syncTime));
+ SecCoreAnalyticsSendValue(known ? kSecADSecurityKnownItemSyncTimeKey : kSecADSecurityNewItemSyncTimeKey,
+ SecBucket2Significant(syncTime));
}
CFReleaseNull(itemModDate);
}
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);
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);
_SOSCCIsSafariSyncing
_SOSCCIsWiFiSyncing
_SOSCCJoinWithCircleJoiningBlob
+_SOSCCLoggedIntoAccount
_SOSCCLoggedOutOfAccount
_SOSCCMessageFromPeerIsPending
_SOSCCPeersHaveViewsEnabled
_SOSCCRegisterUserCredentials
_SOSCCRejectApplicants
_SOSCCRemovePeersFromCircle
-_SOSCCRemovePeersFromCircleWithAnalytics
_SOSCCRemoveThisDeviceFromCircle
-_SOSCCRemoveThisDeviceFromCircleWithAnalytics
_SOSCCRequestToJoinCircle
-_SOSCCRequestToJoinCircleWithAnalytics
_SOSCCRequestToJoinCircleAfterRestore
-_SOSCCRequestToJoinCircleAfterRestoreWithAnalytics
_SOSCCResetToEmpty
-_SOSCCResetToEmptyWithAnalytics
_SOSCCResetToOffering
_SOSCCSendToPeerIsPending
_SOSCCSetLastDepartureReason
_SOSCCSetUserCredentials
_SOSCCSetUserCredentialsAndDSID
-_SOSCCSetUserCredentialsAndDSIDWithAnalytics
_SOSCCThisDeviceIsInCircle
_SOSCCThisDeviceIsInCircleNonCached
_SOSCCTryUserCredentials
_SOSCCValidateUserPublic
_SOSCCView
_SOSCCViewSet
-_SOSCCViewSetWithAnalytics
_SOSCCWaitForInitialSync
-_SOSCCWaitForInitialSyncWithAnalytics
_SOSCCCopyInitialSyncData
_kSOSCCEngineStateCoderKey
_SOSPeerInfoGetDEREncodedSize
_SOSPeerInfoGetPeerDeviceType
_SOSPeerInfoGetPeerID
+_SOSPeerInfoGetSPID
_SOSPeerInfoGetPeerName
_SOSPeerInfoGetPeerProtocolVersion
_SOSPeerInfoGetPermittedViews
_SOSFullPeerInfoEncodeToDER
_SOSFullPeerInfoGetDEREncodedSize
_SOSFullPeerInfoPing
+_SOSFullPeerInfoSetCKKS4AllSupport
_SOSFullPeerInfoPrivKeyExists
_SOSFullPeerInfoPromoteToRetiredAndCopy
_SOSFullPeerInfoPurgePersistentKey
_SOSRingKeyCreateWithRingName
_kSOSKVSKeyParametersKey
_sCirclePrefix
+_sRingPrefix
_sDebugInfoPrefix
_sRetirementPrefix
_SOSCreateErrorWithFormatAndArguments
_SOSDateCreate
_SOSErrorCreate
+_SOSCCCredentialQueue
_SOSGenerateDeviceBackupFullKey
_SOSGetBackupKeyCurveParameters
_SOSItemsChangedCopyDescription
_SOSTransportMessageTypeKVS
_kSOSDSIDKey
_kSOSNoCachedValue
-
+_kSOSCountKey
_SOSPeerGestaltGetAnswer
_SOSPeerGestaltGetName
_sEscrowRecord
_sTransportType
_SOSGenerationCountCopyDescription
+_sCKKSForAll
_kSOSHsaCrKeyDictionary
_SOSPeerInfoCopySerialNumber
_SOSPeerInfoSerialNumberIsSet
_SOSPeerInfoSetSerialNumber
_SOSPeerInfoSetTestSerialNumber
+_SOSPeerInfoSetSupportsCKKSForAll
+_SOSPeerInfoSupportsCKKSForAll
_SOSPeerInfoSign
_SOSPeerInfoUpdateToV2
_SOSPeerInfoV2DictionaryCopyDictionary
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);
#include <Security/SecFramework.h>
#include <stdlib.h>
-#include <assert.h>
#include <utilities/SecCFWrappers.h>
#include <utilities/SecCFRelease.h>
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);
});
}
+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)
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;
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;
}
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;
__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)
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);
// Returns false unless errorCode is 0.
bool SOSErrorCreate(CFIndex errorCode, CFErrorRef *error, CFDictionaryRef formatOptions, CFStringRef descriptionString, ...);
#include <utilities/der_date.h>
#include <corecrypto/ccrng.h>
-#include <corecrypto/ccrng_pbkdf2_prng.h>
-
-#include <CommonCrypto/CommonRandomSPI.h>
+#include <corecrypto/ccdigest.h>
+#include <corecrypto/ccsha2.h>
+#include <corecrypto/ccpbkdf2.h>
#include <os/lock.h>
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);
{
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));
- 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));
+#define drbg_output_size 1024
+
+ 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)
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;
+}
}
-(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;
}
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);
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);
}
-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);
// 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++;
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) {
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);
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);
// 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);
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);
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);
#include <dispatch/dispatch.h>
#include <stdlib.h>
-#include <assert.h>
#include <utilities/SecCFWrappers.h>
#include <utilities/SecCFRelease.h>
CFStringRef sTransportType = CFSTR("TransportType");
CFStringRef sDeviceID = CFSTR("DeviceID");
+CFStringRef sCKKSForAll = CFSTR("CKKS4A");
+
const CFStringRef peerIDLengthKey = CFSTR("idLength");
SOSPeerInfoRef SOSPeerInfoAllocate(CFAllocatorRef allocator) {
#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);
SecKeyRef signingKey,
SecKeyRef octagonPeerSigningKey,
SecKeyRef octagonPeerEncryptionKey,
+ bool supportsCKKS4All,
CFErrorRef* error,
void (^ description_modifier)(CFMutableDictionaryRef description)) {
SOSPeerInfoRef pi = CFTypeAllocate(SOSPeerInfo, struct __OpaqueSOSPeerInfo, allocator);
goto exit;
}
+
if (octagonPeerSigningKey) {
SecKeyRef octagonPeerSigningPublicKey = SecKeyCreatePublicFromPrivate(octagonPeerSigningKey);
if (octagonPeerSigningPublicKey == NULL) {
description_modifier(pi->description);
pi->peerID = SOSCopyIDOfKey(publicKey, error);
+ pi->spid = CFStringCreateTruncatedCopy(pi->peerID, 8);
pi->verifiedAppKeyID = NULL;
pi->verifiedResult = false;
if (backup_key != NULL) SOSPeerInfoV2DictionarySetValue(pi, sBackupKeyKey, backup_key);
SOSPeerInfoV2DictionarySetValue(pi, sViewsKey, enabledViews);
+ SOSPeerInfoSetSupportsCKKSForAll(pi, supportsCKKS4All);
+
// ================ V2 Additions End
if (!SOSPeerInfoSign(signingKey, pi, error)) {
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,
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);
});
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;
}
-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);
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:
CFReleaseNull(pi->signature);
CFReleaseNull(pi->gestalt);
CFReleaseNull(pi->peerID);
- CFReleaseNull(pi->v2Dictionary);
+ CFReleaseNull(pi->spid);
CFReleaseNull(pi->verifiedAppKeyID);
+ CFReleaseNull(pi->v2Dictionary);
pi->verifiedResult = false;
}
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)),
'-',
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);
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);
}
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));
}
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;
}
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;
CFDictionarySetValue(peer->description, sOctagonPeerSigningPublicKeyKey, signingPublicKeyBytes);
CFDictionarySetValue(peer->description, sOctagonPeerEncryptionPublicKeyKey, encryptionPublicKeyBytes);
+ ret = true;
+
fail:
CFReleaseNull(signingPublicKeyBytes);
CFReleaseNull(encryptionPublicKeyBytes);
+
+ return ret;
}
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);
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)) {
// Cached data
CFDictionaryRef gestalt;
CFStringRef peerID;
+ CFStringRef spid;
CFIndex version;
CFStringRef verifiedAppKeyID;
bool verifiedResult;
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
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);
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);
#include "keychain/SecureObjectSync/SOSPeerOTRTimer.h"
#include "keychain/SecureObjectSync/CKBridge/SOSCloudKeychainClient.h"
-#include <utilities/SecADWrapper.h>
#include <utilities/debugging.h>
#include <utilities/SecCFWrappers.h>
#include <AssertMacros.h>
#include "keychain/SecureObjectSync/SOSInternal.h"
-//AGGD
-NSString* const SecSOSAggdMaxRenegotiation = @"com.apple.security.sos.otrrenegotiationmaxretries";
-
static int maxRetryCount = 7; //max number of times to attempt restarting OTR negotiation
bool SOSPeerOTRTimerHaveReachedMaxRetryAllowance(SOSAccount* account, NSString* peerid){
if(attempt && [attempt intValue] >= maxRetryCount)
{
reachedMax = true;
- SecADAddValueForScalarKey((__bridge CFStringRef) SecSOSAggdMaxRenegotiation,1);
}
return reachedMax;
}
-(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];
-(instancetype)initWithAccessGroup:(NSString *)accessGroup
{
- self = [super init];
- if(self){
+ if ((self = [super init])) {
_accessGroup = accessGroup;
}
return self;
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");
*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);
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);
#include <utilities/SecCFWrappers.h>
#include <stdlib.h>
-#include <assert.h>
#include "SOSRingUtils.h"
#include "SOSRingTypes.h"
#include <utilities/SecCFWrappers.h>
#include <stdlib.h>
-#include <assert.h>
#include "SOSRingUtils.h"
#include "SOSRingTypes.h"
#include <utilities/der_date.h>
#include <stdlib.h>
-#include <assert.h>
#include "SOSRing.h"
#include "SOSRingUtils.h"
#include <utilities/der_date.h>
#include <stdlib.h>
-#include <assert.h>
#include "SOSRingUtils.h"
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"));
#include <utilities/der_date.h>
#include <stdlib.h>
-#include <assert.h>
#include "SOSRing.h"
#include "SOSRingUtils.h"
#include <utilities/SecCFWrappers.h>
#include <stdlib.h>
-#include <assert.h>
#include "SOSRingUtils.h"
#include "SOSRingTypes.h"
#include <utilities/der_date.h>
#include <stdlib.h>
-#include <assert.h>
+#include <utilities/simulatecrash_assert.h>
#include "SOSRing.h"
#include "SOSRingUtils.h"
__block bool addSeparator = false;
- CFSetForEachPeerID(peers, ^(CFStringRef peerID) {
- if (addSeparator) {
- CFStringAppendCString(result, ", ", kCFStringEncodingUTF8);
- }
- CFStringRef spid = CFStringCreateTruncatedCopy(peerID, 8);
- CFStringAppend(result, spid);
- CFReleaseNull(spid);
-
- addSeparator = true;
- });
+ if(peers) {
+ CFSetForEachPeerID(peers, ^(CFStringRef peerID) {
+ if (addSeparator) {
+ CFStringAppendCString(result, ", ", kCFStringEncodingUTF8);
+ }
+ CFStringRef spid = CFStringCreateTruncatedCopy(peerID, 8);
+ CFStringAppend(result, spid);
+ CFReleaseNull(spid);
+
+ addSeparator = true;
+ });
+ }
return result;
}
#include <utilities/SecCFWrappers.h>
#include <stdlib.h>
-#include <assert.h>
#include "SOSRingUtils.h"
#include "SOSRingTypes.h"
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;
}
-(SOSCircleStorageTransport*) initWithAccount:(SOSAccount*)acct
{
- self = [super init];
- if(self){
+ if ((self = [super init])) {
self.account = acct;
}
return self;
-(id) init
{
- self = [super init];
- if(self){
+ if ((self = [super init])) {
SOSRegisterTransportCircle(self);
}
return self;
-(id) initWithAccount:(SOSAccount*)acct
{
- self = [super init];
- if(self)
- {
+ if ((self = [super init])) {
self.account = acct;
}
return self;
-(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;
}
};
- 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;
}
-(id) initWithAccount:(SOSAccount*) acct
{
- self = [super init];
- if(self){
+ if ((self = [super init])) {
self.account = acct;
SOSRegisterTransportKeyParameter(self);
}
}
};
- 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;
}
#include "keychain/SecureObjectSync/SOSEngine.h"
#import "keychain/SecureObjectSync/SOSPeerRateLimiter.h"
#import "keychain/SecureObjectSync/SOSPeerOTRTimer.h"
-#include <utilities/SecADWrapper.h>
+#import "utilities/SecCoreAnalytics.h"
#include <utilities/SecCFWrappers.h>
#include <utilities/SecPLWrappers.h>
#include "keychain/SecureObjectSync/SOSInternal.h"
-(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;
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);
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);
}
#import "keychain/SecureObjectSync/SOSTransportMessageKVS.h"
#include "keychain/SecureObjectSync/SOSKVSKeys.h"
#include <utilities/SecCFWrappers.h>
-#include <utilities/SecADWrapper.h>
#include "keychain/SecureObjectSync/SOSInternal.h"
#include <AssertMacros.h>
#include "keychain/SecureObjectSync/CKBridge/SOSCloudKeychainClient.h"
-(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);
}
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;
}
- (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;
- (void)initialSyncCredentials:(uint32_t)flags complete:(void (^)(NSArray *, NSError *))complete;
- (void)importInitialSyncCredentials:(NSArray *)items complete:(void (^)(bool success, NSError *))complete;
-- (void)triggerSync:(NSArray <NSString *> *)peers complete:(void(^)(bool success, NSError *))complete;
+- (void)rpcTriggerSync:(NSArray <NSString *> *)peers complete:(void(^)(bool success, NSError *))complete;
- (void)getWatchdogParameters:(void (^)(NSDictionary* parameters, NSError* error))complete;
- (void)setWatchdogParmeters:(NSDictionary*)parameters complete:(void (^)(NSError* error))complete;
-- (void)triggerBackup:(NSArray<NSString *>*)backupPeers complete:(void (^)(NSError *error))complete;
+- (void)rpcTriggerBackup:(NSArray<NSString *>*)backupPeers complete:(void (^)(NSError *error))complete;
+- (void)rpcTriggerRingUpdate:(void (^)(NSError *error))complete;
+
@end
#endif
#include <corecrypto/ccec.h>
#include <corecrypto/ccdigest.h>
#include <corecrypto/ccsha2.h>
-#include <CommonCrypto/CommonRandomSPI.h>
#include <Security/SecKey.h>
#include <Security/SecKeyPriv.h>
#include <Security/SecFramework.h>
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;
}
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;
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];
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("<Params: iter: %zd, size: %zd, salt: %@> <keyid: %@>"), iterations, keysize, saltHex, userPubKeyID);
- });
+ description = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("<Params: iter: %zd, size: %zd, salt: %@>"), iterations, keysize, saltHex);
});
-
- CFReleaseNull(newParameters);
- CFReleaseNull(newKey);
- CFReleaseNull(userPubKeyID);
-
+
return description;
}
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";
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);
CFMutableArrayRef peers2remove = NULL;
SOSLogSetOutputTo(NULL, NULL);
- while ((ch = getopt_long(argc, argv, "ab:deikmorv:NCDLOP:RT:UWV05", longopts, NULL)) != -1)
+ while ((ch = getopt_long(argc, argv, "ab:deikmorv:NCDLOP:RT:UWV05", longopts, NULL)) != -1) {
switch (ch) {
case 'a':
{
}
break;
}
+ 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;
+ }
+ break;
+ }
case '?':
default:
return SHOW_USAGE_MESSAGE;
}
+ }
if (peers2remove != NULL) {
hadError = !doRemovePeers(peers2remove, &error);
@interface SOSAccountConfiguration : PBCodable <NSCopying>
{
NSMutableArray<NSString *> *_pendingBackupPeers;
- BOOL _sbdBackup;
+ BOOL _ringUpdateFlag;
struct {
- int sbdBackup:1;
+ int ringUpdateFlag:1;
} _has;
}
- (NSString *)pendingBackupPeersAtIndex:(NSUInteger)idx;
+ (Class)pendingBackupPeersType;
-@property (nonatomic) BOOL hasSbdBackup;
-@property (nonatomic) BOOL sbdBackup;
+@property (nonatomic) BOOL hasRingUpdateFlag;
+@property (nonatomic) BOOL ringUpdateFlag;
// Performs a shallow copy into other
- (void)copyTo:(SOSAccountConfiguration *)other;
{
return [NSString class];
}
+@synthesize ringUpdateFlag = _ringUpdateFlag;
+- (void)setRingUpdateFlag:(BOOL)v
+{
+ _has.ringUpdateFlag = YES;
+ _ringUpdateFlag = v;
+}
+- (void)setHasRingUpdateFlag:(BOOL)f
+{
+ _has.ringUpdateFlag = f;
+}
+- (BOOL)hasRingUpdateFlag
+{
+ return _has.ringUpdateFlag != 0;
+}
- (NSString *)description
{
{
[dict setObject:self->_pendingBackupPeers forKey:@"pendingBackupPeers"];
}
+ if (self->_has.ringUpdateFlag)
+ {
+ [dict setObject:[NSNumber numberWithBool:self->_ringUpdateFlag] forKey:@"ringUpdateFlag"];
+ }
return dict;
}
}
}
break;
+ case 2 /* ringUpdateFlag */:
+ {
+ self->_has.ringUpdateFlag = YES;
+ self->_ringUpdateFlag = PBReaderReadBOOL(reader);
+ }
+ break;
default:
if (!PBReaderSkipValueWithTag(reader, tag, aType))
return NO;
PBDataWriterWriteStringField(writer, s_pendingBackupPeers, 1);
}
}
+ /* ringUpdateFlag */
+ {
+ if (self->_has.ringUpdateFlag)
+ {
+ PBDataWriterWriteBOOLField(writer, self->_ringUpdateFlag, 2);
+ }
+ }
}
- (void)copyTo:(SOSAccountConfiguration *)other
[other addPendingBackupPeers:[self pendingBackupPeersAtIndex:i]];
}
}
+ if (self->_has.ringUpdateFlag)
+ {
+ other->_ringUpdateFlag = _ringUpdateFlag;
+ other->_has.ringUpdateFlag = YES;
+ }
}
- (id)copyWithZone:(NSZone *)zone
NSString *vCopy = [v copyWithZone:zone];
[copy addPendingBackupPeers:vCopy];
}
+ if (self->_has.ringUpdateFlag)
+ {
+ copy->_ringUpdateFlag = _ringUpdateFlag;
+ copy->_has.ringUpdateFlag = YES;
+ }
return copy;
}
return [other isMemberOfClass:[self class]]
&&
((!self->_pendingBackupPeers && !other->_pendingBackupPeers) || [self->_pendingBackupPeers isEqual:other->_pendingBackupPeers])
+ &&
+ ((self->_has.ringUpdateFlag && other->_has.ringUpdateFlag && ((self->_ringUpdateFlag && other->_ringUpdateFlag) || (!self->_ringUpdateFlag && !other->_ringUpdateFlag))) || (!self->_has.ringUpdateFlag && !other->_has.ringUpdateFlag))
;
}
return 0
^
[self->_pendingBackupPeers hash]
+ ^
+ (self->_has.ringUpdateFlag ? PBHashInt((NSUInteger)self->_ringUpdateFlag) : 0)
;
}
{
[self addPendingBackupPeers:iter_pendingBackupPeers];
}
+ if (other->_has.ringUpdateFlag)
+ {
+ self->_ringUpdateFlag = other->_ringUpdateFlag;
+ self->_has.ringUpdateFlag = YES;
+ }
}
@end
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");
}
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"],
@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");
+}
+
@end
} 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"
#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"
+++ /dev/null
-/*
- * 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 SFSignInAnalytics_Internal_h
-#define SFSignInAnalytics_Internal_h
-
-#import "SFSignInAnalytics.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;
-@end
-
-@interface SFSIALoggerObject : SFAnalytics
-+ (instancetype)logger;
-- (instancetype)init NS_UNAVAILABLE;
-@end
-
-#endif /* SFSignInAnalytics+Internal_h */
-#endif
+++ /dev/null
-/*
- * 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 <Foundation/Foundation.h>
-#import <Security/SFAnalytics.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface SFSignInAnalytics : NSObject <NSSecureCoding>
-
-@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<NSString*, id>* _Nullable)attributes;
-
-/*
- abstract: call to signal iCloud sign in has finished.
- */
-- (void)signInCompleted;
-
-@end
-NS_ASSUME_NONNULL_END
-#endif /* SignInAnalytics_h */
-#endif
+++ /dev/null
-/*
- * 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 <Analytics/SFAnalytics+Signin.h>
-#import "Analytics/SFAnalyticsDefines.h"
-#import "Analytics/SFAnalyticsSQLiteStore.h"
-#import "Analytics/SFAnalytics.h"
-
-#import <os/log_private.h>
-#import <mach/mach_time.h>
-#import <utilities/SecFileLocations.h>
-#import "utilities/debugging.h"
-#import <utilities/SecCFWrappers.h>
-
-//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<NSString*, id>*)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
-
+++ /dev/null
-/*
- * 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 <XCTest/XCTest.h>
-#import "keychain/SigninMetrics/SFSignInAnalytics.h"
-#import "keychain/SigninMetrics/SFSignInAnalytics+Internal.h"
-#import "keychain/ot/OTDefines.h"
-#import "SFAnalytics+Signin.h"
-#import <Security/SecureObjectSync/SOSCloudCircle.h>
-
-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
- (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;
- (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);
- (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);
}
final class OctagonTests: CDTTestCase {
-
let username: String? = nil
let password: String? = nil
var signedIn: Bool = false
}
func compareCKKSZone(name zone: String, status1: NSDictionary, status2: NSDictionary) -> Bool {
-
let zone1 = status1[zone] as! NSDictionary
let zone2 = status2[zone] as! NSDictionary
}
func compareCKKSStatus(c1: NSDictionary, c2: NSDictionary) -> Bool {
-
let status1 = c1["status"] as! NSDictionary
let status2 = c2["status"] as! NSDictionary
func sosApplication(_ device: CDAIOSDevice, verbose: Bool = false) throws {
if self.password != nil {
-
print("submitting application\n")
let password = try device.executeFile(atPath: securityTool, withArguments: ["sync", "-P", self.password!])
func sosApprove(_ device: CDAIOSDevice, verbose: Bool = false) throws {
if self.password != nil {
-
print("approving applications\n")
let password = try device.executeFile(atPath: securityTool, withArguments: ["sync", "-P", self.password!])
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)
}
// 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
// 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)
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 {
}
extension BottledPeer.Error: LocalizedError {
- public var errorDescription: String? {
+ var errorDescription: String? {
switch self {
case .OTErrorDeserializationFailure:
return "Failed to deserialize bottle peer"
}
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 infoString = Array("Escrow Signing Private Key".utf8)
info = Data(bytes: infoString, count: infoString.count)
-
}
guard let cp = ccec_cp_384() else {
} 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)
}
class func storeEscrowedEncryptionKeyPair(keyData: Data, label: String) throws -> (Bool) {
-
let query: [CFString: Any] = [
kSecClass: kSecClassKey,
kSecAttrAccessible: kSecAttrAccessibleWhenUnlocked,
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)
}
extension EscrowKeysError: LocalizedError {
- public var errorDescription: String? {
+ var errorDescription: String? {
switch self {
case .keyGeneration:
return "Key generation failed"
}
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
}
}
- public var errorUserInfo: [String: Any] {
+ var errorUserInfo: [String: Any] {
var userInfo: [String: Any] = [:]
if let desc = self.errorDescription {
userInfo[NSLocalizedDescriptionKey] = desc
import Foundation
+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 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 (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(nil, CKXPCSuitableError(error))
+ reply(nil, error.sanitizeForClientXPC())
}
}
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 (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(nil, nil, nil, nil, CKXPCSuitableError(error))
+ reply(nil, nil, nil, nil, error.sanitizeForClientXPC())
}
}
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 (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
reply(TrustedPeersHelperEgoPeerStatus(egoPeerID: nil,
peerCountsByMachineID: [:],
isExcluded: false,
isLocked: false),
- CKXPCSuitableError(error))
+ error.sanitizeForClientXPC())
}
}
let containerName = ContainerName(container: container, context: context)
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 (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(nil, nil, CKXPCSuitableError(error))
+ reply(nil, nil, error.sanitizeForClientXPC())
}
}
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 (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(CKXPCSuitableError(error))
+ reply(error.sanitizeForClientXPC())
}
}
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 (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(CKXPCSuitableError(error))
+ reply(error.sanitizeForClientXPC())
}
}
let container = try self.containerMap.findOrCreate(name: containerName)
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 (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(false, CKXPCSuitableError(error))
+ reply(false, error.sanitizeForClientXPC())
}
}
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 (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(CKXPCSuitableError(error))
+ reply(error.sanitizeForClientXPC())
}
}
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 (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(CKXPCSuitableError(error))
+ reply(error.sanitizeForClientXPC())
}
}
let container = try self.containerMap.findOrCreate(name: containerName)
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 (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(nil, CKXPCSuitableError(error))
+ reply(nil, error.sanitizeForClientXPC())
}
}
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 (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(0, CKXPCSuitableError(error))
+ reply(0, error.sanitizeForClientXPC())
}
}
bottleID: String,
modelID: String,
deviceName: String?,
- serialNumber: String,
+ serialNumber: String?,
osVersion: String,
policyVersion: TPPolicyVersion?,
policySecrets: [String: Data]?,
+ syncUserControllableViews: TPPBPeerStableInfo_UserControllableViewStatus,
signingPrivKeyPersistentRef: Data?,
encPrivKeyPersistentRef: Data?,
- reply: @escaping (String?, Data?, Data?, Data?, Data?, Set<String>?, TPPolicy?, 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 %{public}@", log: tplogDebug, type: .default, containerName.description)
osVersion: osVersion,
policyVersion: policyVersion,
policySecrets: policySecrets,
+ syncUserControllableViews: syncUserControllableViews,
signingPrivateKeyPersistentRef: signingPrivKeyPersistentRef,
- encryptionPrivateKeyPersistentRef: encPrivKeyPersistentRef) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, views, policy, 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, views, policy, CKXPCSuitableError(error))
+ reply(peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, policy, error?.sanitizeForClientXPC())
}
} catch {
os_log("Prepare failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(nil, nil, nil, nil, nil, nil, nil, CKXPCSuitableError(error))
+ reply(nil, nil, nil, nil, nil, nil, error.sanitizeForClientXPC())
}
}
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 %{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 (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(nil, nil, CKXPCSuitableError(error))
+ reply(nil, nil, nil, error.sanitizeForClientXPC())
}
}
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 (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(nil, nil, CKXPCSuitableError(error))
+ reply(nil, nil, error.sanitizeForClientXPC())
}
}
func preflightVouchWithBottle(withContainer container: String,
context: String,
bottleID: String,
- reply: @escaping (String?, Set<String>?, TPPolicy?, Error?) -> Void) {
+ reply: @escaping (String?, TPSyncingPolicy?, Bool, Error?) -> Void) {
do {
let containerName = ContainerName(container: container, context: context)
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, viewSet, policy, 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, viewSet, policy, CKXPCSuitableError(error)) }
+ reply(peerID, policy, refetched, error?.sanitizeForClientXPC()) }
} catch {
os_log("Preflighting Vouch With Bottle failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(nil, nil, nil, CKXPCSuitableError(error))
+ reply(nil, nil, false, error.sanitizeForClientXPC())
}
}
let container = try self.containerMap.findOrCreate(name: containerName)
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, uniqueTLKsRecovered, totalTLKSharesRecovered, CKXPCSuitableError(error)) }
+ reply(voucher, voucherSig, uniqueTLKsRecovered, totalTLKSharesRecovered, error?.sanitizeForClientXPC()) }
} catch {
os_log("Vouching with Bottle failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(nil, nil, 0, 0, CKXPCSuitableError(error))
+ reply(nil, nil, 0, 0, error.sanitizeForClientXPC())
}
}
func preflightVouchWithRecoveryKey(withContainer container: String,
- context: String,
- recoveryKey: String,
- salt: String,
- reply: @escaping (String?, Set<String>?, TPPolicy?, Error?) -> Void) {
+ 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, viewSet, policy, error in
+ container.preflightVouchWithRecoveryKey(recoveryKey: recoveryKey, salt: salt) { rkID, policy, error in
self.logComplete(function: "Preflight Vouch With RecoveryKey", container: container.name, error: error)
- reply(rkID, viewSet, policy, CKXPCSuitableError(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, nil, CKXPCSuitableError(error))
+ reply(nil, nil, error.sanitizeForClientXPC())
}
}
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 (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(nil, nil, CKXPCSuitableError(error))
+ reply(nil, nil, error.sanitizeForClientXPC())
}
}
voucherSig: Data,
ckksKeys: [CKKSKeychainBackedKeySet],
tlkShares: [CKKSTLKShare],
- preapprovedKeys: [Data],
- reply: @escaping (String?, [CKRecord]?, Set<String>?, TPPolicy?, Error?) -> Void) {
+ preapprovedKeys: [Data]?,
+ reply: @escaping (String?, [CKRecord]?, TPSyncingPolicy?, Error?) -> Void) {
do {
let containerName = ContainerName(container: container, context: context)
os_log("Joining %{public}@", log: tplogDebug, type: .default, containerName.description)
voucherSig: voucherSig,
ckksKeys: ckksKeys,
tlkShares: tlkShares,
- preapprovedKeys: preapprovedKeys) { peerID, keyHierarchyRecords, views, policy, error in
- reply(peerID, keyHierarchyRecords, views, policy, CKXPCSuitableError(error))
-
+ preapprovedKeys: preapprovedKeys) { peerID, keyHierarchyRecords, policy, error in
+ reply(peerID, keyHierarchyRecords, policy, error?.sanitizeForClientXPC())
}
} catch {
os_log("Joining failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(nil, nil, nil, nil, CKXPCSuitableError(error))
+ 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 %{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 {
os_log("preflightPreapprovedJoin failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(false, CKXPCSuitableError(error))
+ reply(false, error.sanitizeForClientXPC())
}
}
context: String,
ckksKeys: [CKKSKeychainBackedKeySet],
tlkShares: [CKKSTLKShare],
- preapprovedKeys: [Data],
- reply: @escaping (String?, [CKRecord]?, Set<String>?, TPPolicy?, 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 %{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, viewSet, policy, error in
- reply(peerID, keyHierarchyRecords, viewSet, policy, CKXPCSuitableError(error)) }
+ preapprovedKeys: preapprovedKeys) { peerID, keyHierarchyRecords, policy, error in
+ reply(peerID, keyHierarchyRecords, policy, error?.sanitizeForClientXPC()) }
} catch {
os_log("attemptPreapprovedJoin failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(nil, nil, nil, nil, CKXPCSuitableError(error))
+ reply(nil, nil, nil, error.sanitizeForClientXPC())
}
}
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 %{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 {
os_log("update failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(nil, CKXPCSuitableError(error))
+ reply(nil, nil, error.sanitizeForClientXPC())
}
}
let containerName = ContainerName(container: container, context: context)
os_log("setPreapprovedKeysWithContainer %{public}@", log: tplogDebug, type: .default, containerName.description)
let container = try self.containerMap.findOrCreate(name: containerName)
- container.set(preapprovedKeys: preapprovedKeys) { state, error in reply(state, CKXPCSuitableError(error)) }
+ container.set(preapprovedKeys: preapprovedKeys) { state, error in reply(state, error?.sanitizeForClientXPC()) }
} catch {
os_log("setPreapprovedKeysWithContainer failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(nil, CKXPCSuitableError(error))
+ reply(nil, error.sanitizeForClientXPC())
}
}
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 {
os_log("updateTLKs failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(nil, CKXPCSuitableError(error))
+ reply(nil, error.sanitizeForClientXPC())
}
}
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 {
os_log("departByDistrustingSelf failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(CKXPCSuitableError(error))
+ reply(error.sanitizeForClientXPC())
}
}
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 {
os_log("distrustPeerIDs failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(CKXPCSuitableError(error))
+ reply(error.sanitizeForClientXPC())
}
}
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 {
os_log("fetchViableBottles failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(nil, nil, CKXPCSuitableError(error))
+ 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())
}
}
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 {
os_log("fetchEscrowContents failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(nil, nil, nil, CKXPCSuitableError(error))
+ reply(nil, nil, nil, error.sanitizeForClientXPC())
}
}
func fetchCurrentPolicy(withContainer container: String,
context: String,
- reply: @escaping (Set<String>?, TPPolicy?, Error?) -> Void) {
+ modelIDOverride: String?,
+ reply: @escaping (TPSyncingPolicy?, TPPBPeerStableInfo_UserControllableViewStatus, Error?) -> Void) {
do {
let containerName = ContainerName(container: container, context: context)
os_log("Fetching policy+views for %{public}@", log: tplogDebug, type: .default, containerName.description)
let container = try self.containerMap.findOrCreate(name: containerName)
- container.fetchCurrentPolicy { viewList, policy, error in
- reply(viewList, policy, CKXPCSuitableError(error))
+ container.fetchCurrentPolicy(modelIDOverride: modelIDOverride) { policy, peersOpinion, error in
+ reply(policy, peersOpinion, error?.sanitizeForClientXPC())
}
} catch {
os_log("fetchCurrentPolicy failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(nil, nil, CKXPCSuitableError(error))
+ reply(nil, .UNKNOWN, error.sanitizeForClientXPC())
}
}
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(versions: versions) { entries, error in
- reply(entries, CKXPCSuitableError(error))
+ reply(entries, error?.sanitizeForClientXPC())
}
} catch {
os_log("fetchPolicyDocuments failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(nil, CKXPCSuitableError(error))
+ reply(nil, error.sanitizeForClientXPC())
}
}
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 (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(nil, CKXPCSuitableError(error))
+ 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 %{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 (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(CKXPCSuitableError(error))
+ reply(nil, error.sanitizeForClientXPC())
}
}
}
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 (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(CKXPCSuitableError(error))
+ reply(error.sanitizeForClientXPC())
}
}
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 (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(CKXPCSuitableError(error))
+ reply(error.sanitizeForClientXPC())
}
}
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.requestHealthCheck(requiresEscrowCheck: requiresEscrowCheck) { postRepair, postEscrow, postReset, leaveTrust, error in
- reply(postRepair, postEscrow, postReset, leaveTrust, CKXPCSuitableError(error))
+ reply(postRepair, postEscrow, postReset, leaveTrust, error?.sanitizeForClientXPC())
}
} catch {
os_log("Health Check! failed for (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(false, false, false, false, CKXPCSuitableError(error))
+ 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 %{public}@", 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 (%{public}@, %{public}@): %{public}@", log: tplogDebug, type: .default, container, context, error as CVarArg)
- reply(nil, CKXPCSuitableError(error))
+ 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())
}
-
}
}
*/
import CloudKitCode
+import CloudKitCodeProtobuf
import CoreData
import Foundation
import os
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 {
case .testGenerated:
return ResetReason.testGenerated
@unknown default:
- fatalError()
+ fatalError("unknown reset reason: \(cuttlefishResetReason)")
}
}
}
case unknownSecurityFoundationError
case failedToSerializeData
case unknownInternalError
+ case unknownSyncUserControllableViewsValue(value: Int32)
+ case noPeersPreapprovedBySelf
+ case peerRegisteredButNotStored(String)
}
extension ContainerError: LocalizedError {
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"
}
return 44
case .unknownInternalError:
return 45
+ case .unknownSyncUserControllableViewsValue:
+ return 46
+ case .noPeersPreapprovedBySelf:
+ return 47
+ case .peerRegisteredButNotStored:
+ return 48
}
}
}
func saveSecret(_ secret: Data, label: String) throws {
-
let query: [CFString: Any] = [
kSecClass: kSecClassInternetPassword,
kSecAttrAccessible: kSecAttrAccessibleWhenUnlocked,
throw error
}
}
- }.compactMap { $0 }
+ }
+ .compactMap { $0 }
}
@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<String> = Set()
var sharesRecovered: Int64 = 0
do {
var trustedPeers: [AnyHashable] = [peer]
- if let egoPeer = model.peer(withID: peer.peerID) {
+ 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,
var peers: [String: TPPeer] = [:]
var vouchers: [TPVoucher] = []
var bottles = Set<BottleMO>()
+ var escrowRecords = Set<EscrowRecordMO>()
var recoverySigningKey: Data?
var recoveryEncryptionKey: Data?
}
let osVersion: String?
let policyVersion: UInt64?
let policySecrets: [String: 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] {
func egoStableInfo() -> TPPeerStableInfo? {
guard let egoStableData = self.egoPeerStableInfo,
let egoStableSig = self.egoPeerStableInfoSig else {
- return nil
+ return nil
}
return TPPeerStableInfo(data: egoStableData, sig: egoStableSig)
// 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.
// 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 {
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()
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
}
}
- if let recoveryKeySigningSPKI = containerMO.recoveryKeySigningSPKI,
- let recoveryKeyEncyryptionSPKI = containerMO.recoveryKeyEncryptionSPKI {
- model.setRecoveryKeys(TPRecoveryKeyPair(signingSPKI: recoveryKeySigningSPKI, encryptionSPKI: recoveryKeyEncyryptionSPKI))
+ 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
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(signingSPKI: egoStableInfo.recoverySigningPublicKey, encryptionSPKI: egoStableInfo.recoveryEncryptionPublicKey))
+ model.setRecoveryKeys(TPRecoveryKeyPair(signingKeyData: egoStableInfo.recoverySigningPublicKey, encryptionKeyData: egoStableInfo.recoveryEncryptionPublicKey))
}
}
containerMO.egoPeerStableInfo = modelStableInfo.data
containerMO.egoPeerStableInfoSig = modelStableInfo.sig
}
-
}
static func dictionaryRepresentation(bottle: BottleMO) -> [String: Any] {
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 {
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: %{public}@", log: tplogDebug, type: .default, error as CVarArg)
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)
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("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 {
}
func dumpEgoPeer(reply: @escaping (String?, TPPeerPermanentInfo?, TPPeerStableInfo?, TPPeerDynamicInfo?, Error?) -> Void) {
- 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 {
+ 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
}
self.cuttlefish.validatePeers(request) { response, error in
- os_log("ValidatePeers(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))")
guard let response = response, error == nil else {
os_log("validatePeers failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error")
reply(nil, error ?? ContainerError.cloudkitResponseMissing)
$0.resetReason = resetReason
}
self.cuttlefish.reset(request) { response, error in
- os_log("Reset(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))")
guard let response = response, error == nil else {
os_log("reset failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error")
reply(error ?? ContainerError.cloudkitResponseMissing)
bottleID: String,
modelID: String,
deviceName: String?,
- serialNumber: String,
+ serialNumber: String?,
osVersion: String,
policyVersion: TPPolicyVersion?,
policySecrets: [String: Data]?,
+ syncUserControllableViews: TPPBPeerStableInfo_UserControllableViewStatus,
signingPrivateKeyPersistentRef: Data?,
encryptionPrivateKeyPersistentRef: Data?,
- reply: @escaping (String?, Data?, Data?, Data?, Data?, Set<String>?, TPPolicy?, Error?) -> Void) {
+ reply: @escaping (String?, Data?, Data?, Data?, Data?, TPSyncingPolicy?, Error?) -> Void) {
self.semaphore.wait()
- let reply: (String?, Data?, Data?, Data?, Data?, Set<String>?, TPPolicy?, Error?) -> Void = {
+ 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($7))
+ log: tplogTrace, type: .info, ($0 ?? "NULL") as CVarArg, traceError($6))
self.semaphore.signal()
- reply($0, $1, $2, $3, $4, $5, $6, $7)
+ reply($0, $1, $2, $3, $4, $5, $6)
}
// Create a new peer identity with random keys, and store the keys in keychain
signing: signingKeyPair,
encryptionKeyPair: encryptionKeyPair,
peerIDHashAlgo: TPHashAlgo.SHA256)
-
} catch {
- reply(nil, nil, nil, nil, nil, nil, nil, error)
+ reply(nil, nil, nil, nil, nil, nil, error)
return
}
_ = try saveSecret(bottle.secret, label: peerID)
} catch {
os_log("bottle creation failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg)
- reply(nil, nil, nil, nil, nil, nil, nil, error)
+ 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: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing")
- reply(nil, nil, nil, nil, nil, nil, nil, error ?? ContainerError.failedToStoreIdentity)
+ 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: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing")
- reply(nil, nil, nil, nil, nil, nil, nil, error ?? ContainerError.failedToStoreIdentity)
+ reply(nil, nil, nil, nil, nil, nil, error ?? ContainerError.failedToStoreIdentity)
return
}
- let policyVersion = policyVersion ?? prevailingPolicyVersion
- self.fetchPolicyDocumentWithSemaphore(version: policyVersion) { policyDoc, policyFetchError in
+ 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, nil, error ?? ContainerError.unknownInternalError)
+ reply(nil, nil, nil, nil, nil, nil, error ?? ContainerError.unknownInternalError)
return
}
+ if policyVersion != nil {
+ self.policyVersionOverride = policyDoc.version
+ }
+
// Save the prepared identity as containerMO.egoPeer* and its bottle
self.moc.performAndWait {
do {
-
- let stableInfo = TPPeerStableInfo(clock: 1,
- frozenPolicyVersion: frozenPolicyVersion,
- flexiblePolicyVersion: policyDoc.version,
- policySecrets: policySecrets,
- deviceName: deviceName,
- serialNumber: serialNumber,
- osVersion: osVersion,
- signing: signingKeyPair,
- recoverySigningPubKey: nil,
- recoveryEncryptionPubKey: nil,
- error: nil)
-
+ // 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 useFrozenPolicyVersion = policyDoc.version.versionNumber >= frozenPolicyVersion.versionNumber
+
+ 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.addToBottles(bottleMO)
- let (syncingViews, policy) = try self.policyAndViewsFor(permanentInfo: permanentInfo, stableInfo: stableInfo)
+ 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, syncingViews, policy, nil)
+ 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, nil, error)
+ reply(nil, nil, nil, nil, nil, nil, error)
}
}
}
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 = {
+ let reply: (String?, [CKRecord], TPSyncingPolicy?, Error?) -> Void = {
os_log("establish complete peer: %{public}@ %{public}@",
- log: tplogTrace, type: .default, ($0 ?? "NULL") as CVarArg, traceError($2))
+ 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: { peerID, ckrecords, _, _, error in
- reply(peerID, ckrecords, error)
- })
+ preapprovedKeys: preapprovedKeys) { peerID, ckrecords, syncingPolicy, error in
+ reply(peerID, ckrecords, syncingPolicy, error)
+ }
}
}
func fetchAfterEstablish(ckksKeys: [CKKSKeychainBackedKeySet],
tlkShares: [CKKSTLKShare],
- reply: @escaping (String?, [CKRecord], Set<String>?, TPPolicy?, Error?) -> Void) {
+ 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, nil, error)
+ 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, nil, error)
+ 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, nil, ContainerError.noPreparedIdentity)
- return
+ 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, nil, ContainerError.invalidPeerID)
+ 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, 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, [], nil, nil, ContainerError.invalidStableInfoOrSig)
+ 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, nil, error)
+ reply(nil, [], nil, error)
return
}
do {
- let (syncingViews, policy) = try self.policyAndViewsFor(permanentInfo: selfPermanentInfo,
- stableInfo: selfStableInfo)
+ let syncingPolicy = try self.syncingPolicyFor(modelID: selfPermanentInfo.modelID,
+ stableInfo: selfStableInfo)
os_log("fetchAfterEstablish succeeded", log: tplogDebug, type: .default)
- reply(egoPeerID, ckrecords ?? [], syncingViews, policy, nil)
+ reply(egoPeerID, ckrecords ?? [], syncingPolicy, nil)
} catch {
os_log("fetchAfterEstablish failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg))
- reply(nil, [], nil, nil, error)
+ reply(nil, [], nil, error)
}
}
}
func onqueueEstablish(ckksKeys: [CKKSKeychainBackedKeySet],
tlkShares: [CKKSTLKShare],
preapprovedKeys: [Data]?,
- reply: @escaping (String?, [CKRecord], Set<String>?, TPPolicy?, 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,
let egoStableData = self.containerMO.egoPeerStableInfo,
let egoStableSig = self.containerMO.egoPeerStableInfoSig
else {
- reply(nil, [], nil, 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, [], nil, 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, [], nil, nil, ContainerError.invalidStableInfoOrSig)
+ reply(nil, [], nil, ContainerError.invalidStableInfoOrSig)
return
}
guard self.onqueueMachineIDAllowedByIDMS(machineID: selfPermanentInfo.machineID) else {
os_log("establish: self machineID %{public}@ not on list", log: tplogDebug, type: .debug, selfPermanentInfo.machineID)
self.onqueueTTRUntrusted()
- reply(nil, [], nil, nil, ContainerError.preparedIdentityNotOnAllowedList(selfPermanentInfo.machineID))
+ reply(nil, [], nil, ContainerError.preparedIdentityNotOnAllowedList(selfPermanentInfo.machineID))
return
}
loadEgoKeys(peerID: egoPeerID) { egoPeerKeys, error in
- guard let egoPeerKeys = egoPeerKeys else {
+ 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, nil, error)
+ reply(nil, [], nil, error)
return
}
self.moc.performAndWait {
allTLKShares = octagonShares + sosShares
} catch {
os_log("Unable to make TLKShares for self: %{public}@", log: tplogDebug, type: .default, error as CVarArg)
- reply(nil, [], nil, nil, error)
+ 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())
-
- os_log("dynamic info: %{public}@", log: tplogDebug, type: .default, dynamicInfo)
+ (peer, newDynamicInfo) = try self.onqueuePreparePeerForJoining(egoPeerID: egoPeerID,
+ peerPermanentInfo: selfPermanentInfo,
+ stableInfo: selfStableInfo,
+ sponsorID: nil,
+ preapprovedKeys: preapprovedKeys,
+ vouchers: [],
+ egoPeerKeys: egoPeerKeys)
+
+ os_log("dynamic info: %{public}@", log: tplogDebug, type: .default, newDynamicInfo)
} catch {
- reply(nil, [], nil, 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, [], nil, nil, error)
+ reply(nil, [], nil, error)
return
}
os_log("Beginning establish for peer %{public}@", log: tplogDebug, type: .default, egoPeerID)
$0.tlkShares = allTLKShares
}
self.cuttlefish.establish(request) { response, error in
- os_log("Establish(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))")
os_log("Establish: viewKeys: %{public}@", String(describing: viewKeys))
guard let response = response, error == nil else {
switch error {
return
default:
os_log("establish failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error")
- reply(nil, [], nil, nil, error ?? ContainerError.cloudkitResponseMissing)
+ reply(nil, [], nil, error ?? ContainerError.cloudkitResponseMissing)
return
}
}
let keyHierarchyRecords = response.zoneKeyHierarchyRecords.compactMap { CKRecord($0) }
do {
- let (syncingViews, policy) = try self.policyAndViewsFor(permanentInfo: selfPermanentInfo,
- stableInfo: selfStableInfo)
+ let syncingPolicy = try self.syncingPolicyFor(modelID: selfPermanentInfo.modelID,
+ stableInfo: newPeerStableInfo)
try self.persist(changes: response.changes)
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: %{public}@", log: tplogDebug, type: .default, (fetchError as CVarArg?) ?? "no error")
- reply(nil, keyHierarchyRecords, nil, nil, fetchError)
+ reply(nil, keyHierarchyRecords, nil, fetchError)
return
}
os_log("fetch-after-establish succeeded", log: tplogDebug, type: .default)
- reply(egoPeerID, keyHierarchyRecords, nil, nil, nil)
+ reply(egoPeerID, keyHierarchyRecords, syncingPolicy, nil)
}
return
}
os_log("establish succeeded", log: tplogDebug, type: .default)
- reply(egoPeerID, keyHierarchyRecords, syncingViews, policy, nil)
+ reply(egoPeerID, keyHierarchyRecords, syncingPolicy, nil)
} catch {
os_log("establish handling failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg))
- reply(nil, keyHierarchyRecords, nil, nil, error)
+ 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: %{public}@", 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)
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
}
recoveryKeys = try RecoveryKey(recoveryKeyString: recoveryKey, recoverySalt: salt)
} catch {
os_log("failed to create recovery keys: %{public}@", log: tplogDebug, type: .default, error as CVarArg)
- reply(ContainerError.failedToCreateRecoveryKey)
+ reply(nil, ContainerError.failedToCreateRecoveryKey)
return
}
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: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error")
- reply(error)
+ reply(nil, error)
return
}
self.moc.performAndWait {
let policyVersion = stableInfo.bestPolicyVersion()
let policyDoc = try self.getPolicyDoc(policyVersion.versionNumber)
- let updatedStableInfo = TPPeerStableInfo(clock: stableInfo.clock + 1,
- frozenPolicyVersion: frozenPolicyVersion,
- flexiblePolicyVersion: policyDoc.version,
- 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 {
}
self.cuttlefish.setRecoveryKey(request) { response, error in
- os_log("SetRecoveryKey(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))")
guard let response = response, error == nil else {
os_log("setRecoveryKey failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error")
- reply(error ?? ContainerError.cloudkitResponseMissing)
+ reply(nil, error ?? ContainerError.cloudkitResponseMissing)
return
}
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: %{public}@", log: tplogDebug, type: .default, (error as CVarArg))
- reply(error)
+ reply(nil, error)
}
}
}
} catch {
- reply(error)
+ reply(nil, error)
}
}
}
}
}
- func currentSetContainerBottleID(bottleMOs: Set<BottleMO>, 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<BottleMO> = []
- var shouldPerformFetch = false
-
- if let containerBottles = self.containerMO.bottles as? Set<BottleMO> {
- 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: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error")
- reply(nil, error)
- return
- }
-
- guard let newBottles = self.containerMO.bottles as? Set<BottleMO> else {
- os_log("no bottles on container: %{public}@", 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: %{public}@", 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: %{public}@", 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: %{public}@", log: tplogDebug, type: .default, error as CVarArg)
- throw ContainerError.failedToCreateBottledPeer
- }
- }
- }
-
func vouchWithBottle(bottleID: String,
entropy: Data,
bottleSalt: String,
reply($0, $1, $2, $3, $4)
}
- self.fetchAndPersistChangesIfNeeded { error in
- guard error == nil else {
- os_log("vouchWithBottle unable to fetch changes: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "")
+ // 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: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "")
- reply(nil, nil, 0, 0, error)
- return
- }
-
- guard let bmo: BottleMO = returnedBMO else {
- os_log("vouchWithBottle bottle is nil: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "")
- reply(nil, nil, 0, 0, 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 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, 0, 0, ContainerError.bottleDoesNotContainContents)
+ return
+ }
+ guard let signatureUsingEscrowKey = bmo.signatureUsingEscrowKey else {
+ reply(nil, nil, 0, 0, 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, 0, 0, ContainerError.bottleDoesNotContainerPeerKeySignature)
+ return
+ }
+ guard let sponsorPeerID = bmo.peerID else {
+ reply(nil, nil, 0, 0, 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, 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
+ }
- //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: %{public}@", log: tplogDebug, type: .default, error as CVarArg)
+ reply(nil, nil, 0, 0, ContainerError.failedToCreateBottledPeer)
+ return
+ }
- do {
- bottledPeer = try BottledPeer(contents: bottledContents,
- secret: entropy,
- bottleSalt: "",
- signatureUsingEscrow: signatureUsingEscrowKey,
- signatureUsingPeerKey: signatureUsingPeerKey)
- } catch {
+ //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("Creation of Bottled Peer failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg)
- reply(nil, nil, 0, 0, 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
+ }
+ }
- os_log("Have a bottle for peer %{public}@", log: tplogDebug, type: .default, bottledPeer.peerID)
+ os_log("Have a bottle for peer %{public}@", log: tplogDebug, type: .default, bottledPeer.peerID)
- // Extract any TLKs we have been given
- let (uniqueTLKsRecovered, totalSharesRecovered) = extract(tlkShares: tlkShares, peer: bottledPeer.peerKeys, model: self.model)
+ // Extract any TLKs we have been given
+ let (uniqueTLKsRecovered, totalSharesRecovered) = extract(tlkShares: tlkShares, peer: bottledPeer.peerKeys, model: self.model)
- 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
- }
+ 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
+ }
- 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
- }
- }
+ 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
}
}
}
return
}
- extract(tlkShares: tlkShares, peer: recoveryKeys.peerKeys, model: self.model)
-
let signingPublicKey: Data = recoveryKeys.peerKeys.signingKey.publicKey.keyData
let encryptionPublicKey: Data = recoveryKeys.peerKeys.encryptionKey.publicKey.keyData
}
//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,
func onqueueDistrust(peerIDs: Set<String>,
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)
preapprovedKeys: nil,
signing: signingKeyPair,
currentMachineIDs: self.onqueueCurrentMIDList())
-
} catch {
os_log("Error preparing dynamic info: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "nil")
reply(error)
$0.dynamicInfoAndSig = signedDynamicInfo
}
self.cuttlefish.updateTrust(request) { response, error in
- os_log("UpdateTrust(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))")
guard let response = response, error == nil else {
os_log("updateTrust failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error")
reply(error ?? ContainerError.cloudkitResponseMissing)
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
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
+ }
+
+ 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)
}
- guard let bottles: Set<BottleMO> = self.containerMO.bottles as? Set<BottleMO> else {
- os_log("bottleForEgoPeer: No Bottles.", log: tplogDebug, type: .default)
- return false
+
+ 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<EscrowRecordMO> {
+ let matchingRecords: Set<EscrowRecordMO> = 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)
+ }
+ }
+ // Save this bottle only if we don't already have it
+ if let existingBottles = self.containerMO.bottles as? Set<BottleMO> {
+ let matchingBottles: Set<BottleMO> = 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)
}
- var matchesCached: Bool = false
- for bottle in bottles {
- guard let bottleID: String = bottle.bottleID else {
- continue
+
+ 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<EscrowRecordMO> {
+ let matchingRecords: Set<EscrowRecordMO> = 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)
+ }
}
- 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<BottleMO> {
+ let matchingBottles: Set<BottleMO> = 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<EscrowRecordMO> {
+ let matchingRecords: Set<EscrowRecordMO> = 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.isEmpty || !cachedBottles.partialBottles.isEmpty) {
+ 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.moc.performAndWait {
-
guard let escrowPairs = response?.viableBottles else {
os_log("fetchViableBottles returned no viable bottles", log: tplogDebug, type: .default)
reply([], [], nil)
let partialBottleIDs = partialPairs.compactMap { $0.bottle.bottleID }
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<BottleMO> {
- let matchingBottles: Set<BottleMO> = 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
-
- // Save this bottle only if we don't already have it
- if let existingBottles = self.containerMO.bottles as? Set<BottleMO> {
- let matchingBottles: Set<BottleMO> = 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)
- }
+ 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: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error")
reply(nil, nil, error)
}
+ }
+ }
+ }
+ }
+
+ func removeEscrowCache(reply: @escaping (Error?) -> Void) {
+ os_log("beginning a removeEscrowCache", log: tplogDebug, type: .default)
+
+ self.semaphore.wait()
+ let reply: (Error?) -> Void = {
+ os_log("removeEscrowCache complete %{public}@", log: tplogTrace, type: .info, traceError($0))
+ self.semaphore.signal()
+ reply($0)
+ }
+
+ self.moc.performAndWait {
+ self.onQueueRemoveEscrowCache()
+ reply(nil)
+ }
+ }
+
+ 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
+ }
+
+ func fetchEscrowRecordsWithSemaphore(forceFetch: Bool, reply: @escaping ([Data]?, Error?) -> Void) {
+ os_log("beginning a fetchEscrowRecords", log: tplogDebug, type: .default)
+
+ 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()
+ }
+
+ 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
+ }
+
+ self.cuttlefish.fetchViableBottles { 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
+ }
+
+ 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 {
+ 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<EscrowRecordMO> {
+ 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<EscrowRecordMO> {
+ 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<EscrowRecordMO> {
+ for record in legacyRecords {
+ if let r = self.escrowRecordMOToEscrowRecords(record: record, viability: .none) {
+ allEscrowRecordData.append(r.data)
+ }
+ }
+ }
+ reply(allEscrowRecordData, nil)
+ } catch {
+ os_log("fetchViableBottles unable to save bottles and records: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error")
+ reply(nil, error)
}
}
}
}
- func fetchCurrentPolicy(reply: @escaping (Set<String>?, TPPolicy?, Error?) -> Void) {
+ func fetchCurrentPolicy(modelIDOverride: String?, reply: @escaping (TPSyncingPolicy?, TPPBPeerStableInfo_UserControllableViewStatus, Error?) -> Void) {
self.semaphore.wait()
- let reply: (Set<String>?, TPPolicy?, Error?) -> Void = {
+ 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)
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)
- reply(nil, nil, ContainerError.noPreparedIdentity)
+ 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, nil, ContainerError.invalidPermanentInfoOrSig)
+ 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, nil, ContainerError.invalidStableInfoOrSig)
+ reply(nil, .UNKNOWN, ContainerError.invalidStableInfoOrSig)
return
}
do {
- let (views, policy) = try self.policyAndViewsFor(permanentInfo: permanentInfo, stableInfo: stableInfo)
- reply(views, policy, nil)
+ 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("TPPolicyDocument failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg)
- reply(nil, nil, error)
+ os_log("Fetching the syncing policy failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg)
+ reply(nil, .UNKNOWN, error)
return
}
}
}
- func policyAndViewsFor(permanentInfo: TPPeerPermanentInfo, stableInfo: TPPeerStableInfo) throws -> (Set<String>, TPPolicy) {
- let policyVersion = stableInfo.bestPolicyVersion()
- guard let policyDocument = self.model.policy(withVersion: policyVersion.versionNumber) else {
- os_log("current policy is missing?", log: tplogDebug, type: .default)
- throw ContainerError.unknownPolicyVersion(policyVersion.versionNumber)
+ 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
}
- let policy = try policyDocument.policy(withSecrets: stableInfo.policySecrets, decrypter: Decrypter())
- let views = try policy.views(forModel: permanentInfo.modelID)
+ guard let policyDocument = self.model.policy(withVersion: bestPolicyVersion.versionNumber) else {
+ os_log("best policy is missing?", log: tplogDebug, type: .default)
+ throw ContainerError.unknownPolicyVersion(prevailingPolicyVersion.versionNumber)
+ }
- return (views, policy)
+ 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.
}
self.cuttlefish.fetchPolicyDocuments(request) { response, error in
- os_log("FetchPolicyDocuments(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))")
guard let response = response, error == nil else {
os_log("FetchPolicyDocuments failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error")
reply(nil, error ?? ContainerError.cloudkitResponseMissing)
return
}
- guard let expectedVersion = (remaining.filter { $0.versionNumber == doc.version.versionNumber }.first) else {
+ 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
}
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<TPVoucher> ?? 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
}
}
peerShares += viewPeerShares
-
} catch {
os_log("Unable to create TLKShares for keyset %@: %{public}@", log: tplogDebug, type: .default, String(describing: keyset), error as CVarArg)
}
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)
ckksKeys: [CKKSKeychainBackedKeySet],
tlkShares: [CKKSTLKShare],
preapprovedKeys: [Data]?,
- reply: @escaping (String?, [CKRecord], Set<String>?, TPPolicy?, Error?) -> Void) {
+ reply: @escaping (String?, [CKRecord], TPSyncingPolicy?, Error?) -> Void) {
self.semaphore.wait()
- let reply: (String?, [CKRecord], Set<String>?, TPPolicy?, Error?) -> Void = {
- os_log("join complete: %{public}@", log: tplogTrace, type: .info, traceError($4))
+ 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, $3, $4)
+ reply($0, $1, $2, $3)
}
self.fetchAndPersistChanges { error in
guard error == nil else {
- reply(nil, [], nil, nil, error)
+ reply(nil, [], nil, error)
return
}
self.moc.performAndWait {
guard let voucher = TPVoucher(infoWith: voucherData, sig: voucherSig) else {
- reply(nil, [], nil, nil, ContainerError.invalidVoucherOrSig)
+ reply(nil, [], nil, ContainerError.invalidVoucherOrSig)
return
}
guard let sponsor = self.model.peer(withID: voucher.sponsorID) else {
- reply(nil, [], nil, nil, ContainerError.sponsorNotRegistered(voucher.sponsorID))
+ reply(nil, [], nil, ContainerError.sponsorNotRegistered(voucher.sponsorID))
return
}
let egoStableData = self.containerMO.egoPeerStableInfo,
let egoStableSig = self.containerMO.egoPeerStableInfoSig
else {
- reply(nil, [], nil, 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, [], nil, nil, ContainerError.invalidPermanentInfoOrSig)
+ reply(nil, [], nil, ContainerError.invalidPermanentInfoOrSig)
return
}
guard let selfStableInfo = TPPeerStableInfo(data: egoStableData, sig: egoStableSig) else {
- reply(nil, [], nil, nil, ContainerError.invalidStableInfoOrSig)
+ 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, 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 join: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing")
- reply(nil, [], nil, nil, error)
+ reply(nil, [], nil, error)
return
}
self.moc.performAndWait {
egoPeerKeys: egoPeerKeys)
} catch {
os_log("Unable to create peer for joining: %{public}@", log: tplogDebug, type: .default, error as CVarArg)
- reply(nil, [], nil, nil, error)
+ reply(nil, [], nil, error)
return
}
guard let peerStableInfo = peer.stableInfoAndSig.toStableInfo() else {
- os_log("Unable to create new peer stable new for joining", log: tplogDebug, type: .default)
- reply(nil, [], nil, nil, ContainerError.invalidStableInfoOrSig)
+ os_log("Unable to create new peer stable info for joining", log: tplogDebug, type: .default)
+ reply(nil, [], nil, ContainerError.invalidStableInfoOrSig)
return
}
epoch: Int(selfPermanentInfo.epoch))
} catch {
os_log("Unable to process keys before joining: %{public}@", log: tplogDebug, type: .default, error as CVarArg)
- reply(nil, [], nil, nil, error)
+ reply(nil, [], nil, error)
return
}
withSponsorID: sponsor.peerID)
} catch {
os_log("Error checking introduction: %{public}@", log: tplogDebug, type: .default, error as CVarArg)
- reply(nil, [], nil, nil, error)
+ reply(nil, [], nil, error)
return
}
do {
bottle = try self.assembleBottle(egoPeerID: egoPeerID)
} catch {
- reply(nil, [], nil, nil, error)
+ reply(nil, [], nil, error)
return
}
$0.viewKeys = viewKeys
}
self.cuttlefish.joinWithVoucher(request) { response, error in
- os_log("JoinWithVoucher(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))")
guard let response = response, error == nil else {
os_log("joinWithVoucher failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error")
- reply(nil, [], nil, nil, error ?? ContainerError.cloudkitResponseMissing)
+ reply(nil, [], nil, error ?? ContainerError.cloudkitResponseMissing)
return
}
self.containerMO.egoPeerStableInfo = peer.stableInfoAndSig.peerStableInfo
self.containerMO.egoPeerStableInfoSig = peer.stableInfoAndSig.sig
- let (syncingViews, policy) = try self.policyAndViewsFor(permanentInfo: selfPermanentInfo,
- stableInfo: peerStableInfo)
+ 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, syncingViews, policy, nil)
+ reply(egoPeerID, keyHierarchyRecords, syncingPolicy, nil)
} catch {
os_log("JoinWithVoucher failed: %{public}@", log: tplogDebug, String(describing: error))
- reply(nil, [], nil, nil, error)
+ reply(nil, [], nil, error)
}
}
}
}
self.cuttlefish.getSupportAppInfo { response, error in
- os_log("getSupportAppInfo(): %{public}@, error: %{public}@", log: tplogDebug,
- "(\(String(describing: response))", "\(String(describing: error))")
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)
reply(data, nil)
}
-
}
- func preflightPreapprovedJoin(reply: @escaping (Bool, Error?) -> Void) {
+ 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))
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], Set<String>?, TPPolicy?, Error?) -> Void) {
+ reply: @escaping (String?, [CKRecord], TPSyncingPolicy?, Error?) -> Void) {
self.semaphore.wait()
- let reply: (String?, [CKRecord], Set<String>?, TPPolicy?, Error?) -> Void = {
- os_log("preapprovedJoin complete: %{public}@", log: tplogTrace, type: .info, traceError($4))
+ 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, $4)
+ 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, nil, error)
+ reply(nil, [], nil, error)
return
}
self.moc.performAndWait {
// 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)
+ tlkShares: tlkShares,
+ preapprovedKeys: preapprovedKeys,
+ reply: reply)
return
}
let egoStableSig = self.containerMO.egoPeerStableInfoSig
else {
os_log("preapprovedJoin: no prepared identity", log: tplogDebug, type: .debug)
- reply(nil, [], nil, 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, [], nil, nil, ContainerError.invalidPermanentInfoOrSig)
+ reply(nil, [], nil, ContainerError.invalidPermanentInfoOrSig)
return
}
guard let selfStableInfo = TPPeerStableInfo(data: egoStableData, sig: egoStableSig) else {
- reply(nil, [], nil, nil, ContainerError.invalidStableInfoOrSig)
+ 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, 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("preapprovedJoin: Don't have my own keys: can't join", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error")
- reply(nil, [], nil, nil, 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, nil, ContainerError.noPeersPreapprovePreparedIdentity)
+ reply(nil, [], nil, ContainerError.noPeersPreapprovePreparedIdentity)
return
}
self.moc.performAndWait {
-
let peer: Peer
let newDynamicInfo: TPPeerDynamicInfo
do {
egoPeerKeys: egoPeerKeys)
} catch {
os_log("Unable to create peer for joining: %{public}@", log: tplogDebug, type: .default, error as CVarArg)
- reply(nil, [], nil, nil, error)
+ reply(nil, [], nil, error)
return
}
guard let peerStableInfo = peer.stableInfoAndSig.toStableInfo() else {
- os_log("Unable to create new peer stable new for joining", log: tplogDebug, type: .default)
- reply(nil, [], nil, nil, ContainerError.invalidStableInfoOrSig)
+ os_log("Unable to create new peer stable info for joining", log: tplogDebug, type: .default)
+ reply(nil, [], nil, ContainerError.invalidStableInfoOrSig)
return
}
let viewKeys: [ViewKeys]
do {
(viewKeys, allTLKShares) = try self.makeSharesForNewKeySets(ckksKeys: ckksKeys,
- tlkShares: tlkShares,
- egoPeerKeys: egoPeerKeys,
- egoPeerDynamicInfo: newDynamicInfo,
- epoch: Int(selfPermanentInfo.epoch))
+ 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, nil, error)
+ reply(nil, [], nil, error)
return
}
do {
bottle = try self.assembleBottle(egoPeerID: egoPeerID)
} catch {
- reply(nil, [], nil, nil, error)
+ reply(nil, [], nil, error)
return
}
$0.viewKeys = viewKeys
}
self.cuttlefish.joinWithVoucher(request) { response, error in
- os_log("preapprovedJoin(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))")
guard let response = response, error == nil else {
os_log("preapprovedJoin failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error")
- reply(nil, [], nil, nil, error ?? ContainerError.cloudkitResponseMissing)
+ reply(nil, [], nil, error ?? ContainerError.cloudkitResponseMissing)
return
}
self.containerMO.egoPeerStableInfo = peer.stableInfoAndSig.peerStableInfo
self.containerMO.egoPeerStableInfoSig = peer.stableInfoAndSig.sig
- let (syncingViews, policy) = try self.policyAndViewsFor(permanentInfo: selfPermanentInfo,
- stableInfo: peerStableInfo)
+ 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, syncingViews, policy, nil)
+ reply(egoPeerID, keyHierarchyRecords, syncingPolicy, nil)
} catch {
os_log("preapprovedJoin failed: %{public}@", log: tplogDebug, String(describing: error))
- reply(nil, [], nil, nil, error)
+ reply(nil, [], nil, error)
}
}
}
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: %{public}@", 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
serialNumber: serialNumber,
osVersion: osVersion,
policyVersion: policyVersion,
- policySecrets: policySecrets)
+ policySecrets: policySecrets,
+ setSyncUserControllableViews: syncUserControllableViews)
self.fetchChangesAndUpdateTrustIfNeeded(stableChanges: stableChanges, reply: reply)
}
os_log("setPreapprovedKeys: no change; nothing to do.", log: tplogDebug, type: .default)
// Calling this will fill in the peer status
- self.updateTrustIfNeeded(reply: reply)
+ self.updateTrustIfNeeded { status, _, error in
+ reply(status, error)
+ }
return
}
$0.dynamicInfoAndSig = SignedPeerDynamicInfo(dynamicInfo)
}
- self.perform(updateTrust: request) { state, error in
+ 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)
self.moc.performAndWait {
self.onqueueUpdateTLKs(ckksKeys: ckksKeys, tlkShares: tlkShares, reply: reply)
}
- }
+ }
- func onqueueUpdateTLKs(ckksKeys: [CKKSKeychainBackedKeySet],
- tlkShares: [CKKSTLKShare],
- reply: @escaping ([CKRecord]?, Error?) -> Void) {
+ 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
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: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "error missing")
+ 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.cuttlefish.updateTrust(request) { response, error in
- os_log("UpdateTrust(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))")
-
guard error == nil else {
reply(nil, error)
return
}
}
+ 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
}
}
}
- private func fetchAndPersistChanges(reply: @escaping (Error?) -> Void) {
+ func fetchAndPersistChanges(reply: @escaping (Error?) -> Void) {
self.moc.performAndWait {
self.onqueueFetchAndPersistChanges(reply: reply)
}
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(%{public}@): %{public}@, error: %{public}@", 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):
// (i.e. after reply is invoked).
internal func fetchChangesAndUpdateTrustIfNeeded(stableChanges: StableChanges? = nil,
peerChanges: Bool = false,
- reply: @escaping (TrustedPeersHelperPeerState?, Error?) -> Void) {
+ reply: @escaping (TrustedPeersHelperPeerState?, TPSyncingPolicy?, Error?) -> Void) {
self.fetchAndPersistChanges { error in
if let error = error {
os_log("fetchChangesAndUpdateTrustIfNeeded: fetching failed: %{public}@", log: tplogDebug, type: .default, error as CVarArg)
- reply(nil, error)
+ reply(nil, nil, error)
return
}
// (i.e. after reply is invoked).
private func updateTrustIfNeeded(stableChanges: StableChanges? = nil,
peerChanges: Bool = false,
- reply: @escaping (TrustedPeersHelperPeerState?, Error?) -> Void) {
+ 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: peerChanges, 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: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error")
- reply(TrustedPeersHelperPeerState(peerID: nil, isPreapproved: false, status: .unknown, memberChanges: peerChanges, unknownMachineIDs: false, osVersion: nil), error)
+ reply(TrustedPeersHelperPeerState(peerID: nil, isPreapproved: false, status: .unknown, memberChanges: peerChanges, unknownMachineIDs: false, osVersion: nil),
+ nil,
+ error)
return
}
guard let currentSelfInModel = self.model.peer(withID: egoPeerID) else {
memberChanges: peerChanges,
unknownMachineIDs: false,
osVersion: nil),
+ nil,
nil)
return
}
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.
currentMachineIDs: self.onqueueCurrentMIDList())
stableInfo = try self.createNewStableInfoIfNeeded(stableChanges: stableChanges,
- egoPeerID: egoPeerID,
+ permanentInfo: currentSelfInModel.permanentInfo,
existingStableInfo: currentSelfInModel.stableInfo,
dynamicInfo: dynamicInfo,
signingKeyPair: signingKeyPair)
memberChanges: peerChanges,
unknownMachineIDs: false,
osVersion: nil),
+ nil,
error)
return
}
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
}
let havePeerChanges = peerChanges || self.haveTrustMemberChanges(newDynamicInfo: dynamicInfo, oldDynamicInfo: peer?.dynamicInfo)
let signedDynamicInfo = SignedPeerDynamicInfo(dynamicInfo)
- os_log("updateTrustIfNeeded: attempting updateTrust for %{public}@ with: %{public}@", log: tplogDebug, type: .default, egoPeerID, 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
private func perform(updateTrust request: UpdateTrustRequest,
stableChanges: StableChanges? = nil,
peerChanges: Bool = false,
- reply: @escaping (TrustedPeersHelperPeerState?, Error?) -> Void) {
-
+ reply: @escaping (TrustedPeersHelperPeerState?, TPSyncingPolicy?, Error?) -> Void) {
self.cuttlefish.updateTrust(request) { response, error in
- os_log("UpdateTrust(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))")
guard let response = response, error == nil else {
os_log("UpdateTrust failed: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "no error")
- reply(nil, error ?? ContainerError.cloudkitResponseMissing)
+ reply(nil, nil, error ?? ContainerError.cloudkitResponseMissing)
return
}
try self.persist(changes: response.changes)
} catch {
os_log("UpdateTrust failed: %{public}@", log: tplogDebug, String(describing: error))
- reply(nil, error)
+ reply(nil, nil, error)
return
}
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 {
peerRequest.predicate = NSPredicate(format: "container == %@", self.containerMO)
try self.moc.execute(NSBatchDeleteRequest(fetchRequest: peerRequest))
- let bottleRequest = NSFetchRequest<NSFetchRequestResult>(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<NSFetchRequestResult>(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
// 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
} 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)
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)
+ }
}
}
}
// 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? {
}
let policyOfPeers = try? self.model.policy(forPeerIDs: dynamicInfo.includedPeerIDs,
- candidatePeerID: egoPeerID,
+ candidatePeerID: permanentInfo.peerID,
candidateStableInfo: existingStableInfo)
// Pick the best version of:
// 1. The policy version asked for by the client
- // 2. The max of our existing policyVersion, the highest policy used by our trusted peers, and the compile-time prevailing policy version
+ // 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 ??
- max(existingStableInfo?.bestPolicyVersion().versionNumber ?? prevailingPolicyVersion.versionNumber,
- policyOfPeers?.version.versionNumber ?? prevailingPolicyVersion.versionNumber,
- prevailingPolicyVersion.versionNumber)
+ 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(optimalPolicyVersionNumber, existingStableInfo?.bestPolicyVersion().versionNumber) &&
noChange(stableChanges?.policySecrets, existingStableInfo?.policySecrets) &&
- noChange(optimalRecoveryKey?.signingSPKI, existingStableInfo?.recoverySigningPublicKey) &&
- noChange(optimalRecoveryKey?.encryptionSPKI, existingStableInfo?.recoveryEncryptionPublicKey) {
+ noChange(optimalRecoveryKey?.signingKeyData, existingStableInfo?.recoverySigningPublicKey) &&
+ noChange(optimalRecoveryKey?.encryptionKeyData, existingStableInfo?.recoveryEncryptionPublicKey) &&
+ noChange(intendedSyncUserControllableViews, existingStableInfo?.syncUserControllableViews) {
return 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))
+ }
- return try self.model.createStableInfo(withFrozenPolicyVersion: frozenPolicyVersion,
- flexiblePolicyVersion: optimalPolicyVersion,
+ 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: optimalRecoveryKey?.signingSPKI,
- recoveryEncryptionPubKey: optimalRecoveryKey?.encryptionSPKI)
+ recoverySigningPubKey: optimalRecoveryKey?.signingKeyData,
+ recoveryEncryptionPubKey: optimalRecoveryKey?.encryptionKeyData)
}
private func assembleBottle(egoPeerID: String) throws -> Bottle {
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 {
}
self.moc.performAndWait {
- self.cuttlefish.reportHealth(updatedRequest) { response, error in
- os_log("reportHealth(%{public}@): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: request))", "\(String(describing: response))", "\(String(describing: error))")
+ self.cuttlefish.reportHealth(updatedRequest) { _, error in
guard error == nil else {
reply(error)
return
}
self.moc.performAndWait {
- self.cuttlefish.pushHealthInquiry(PushHealthInquiryRequest()) { response, error in
- os_log("pushHealthInquiry(): %{public}@, error: %{public}@", log: tplogDebug, "\(String(describing: response))", "\(String(describing: error))")
+ self.cuttlefish.pushHealthInquiry(PushHealthInquiryRequest()) { _, error in
guard error == nil else {
reply(error)
return
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 {
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
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()
-
- // 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)
+ 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)
+
+ 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)
}
}
}
public func invoke<RequestType: Message, ResponseType: Message>(
function: String, request: RequestType,
completion: @escaping (ResponseType?, Error?) -> Void) {
-
// Hack to fool CloudKit, real solution is tracked in <rdar://problem/49086080>
self.queue.async {
-
let operation = CodeOperation<RequestType, ResponseType>(
service: self.serviceName,
functionName: function,
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)
// 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,
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)
self.containers.removeAll()
}
}
+
+ func deleteAllPersistentStores() throws {
+ try queue.sync {
+ try self.containers.forEach {
+ try $0.value.deletePersistentStore()
+ }
+ }
+ }
}
import Foundation
extension Container {
+ func onMOCQueueFindBottle(bottleID: String) throws -> (BottleMO) {
+ guard let containerBottles = self.containerMO.bottles as? Set<BottleMO> 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?, Set<String>?, TPPolicy?, Error?) -> Void) {
+ reply: @escaping (String?, TPSyncingPolicy?, Bool, Error?) -> Void) {
self.semaphore.wait()
- let reply: (String?, Set<String>?, TPPolicy?, Error?) -> Void = {
+ 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.fetchAndPersistChangesIfNeeded { 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, nil, fetchError)
- return
- }
+ 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?) ?? "")
- // 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, 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("fetchCurrentPolicy failed to find ego peer information", log: tplogDebug, type: .error)
- reply(nil, nil, nil, ContainerError.noPreparedIdentity)
- return
- }
-
- 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)
- reply(nil, nil, nil, ContainerError.invalidPermanentInfoOrSig)
+ 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
}
- self.onqueueFindBottle(bottleID: bottleID) { bottleMO, error in
- guard let bottleMO = bottleMO else {
- os_log("preflightVouchWithBottle found no bottle: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "")
- reply(nil, nil, nil, error)
- return
- }
-
- guard let sponsorPeer = self.model.peer(withID: bottleMO.peerID ?? "") else {
- os_log("preflightVouchWithBottle found no peer to match bottle", log: tplogDebug, type: .default)
- reply(nil, nil, nil, ContainerError.sponsorNotRegistered(bottleMO.peerID ?? "no peer ID given"))
- return
- }
-
- guard let sponsorPeerStableInfo = sponsorPeer.stableInfo else {
- os_log("preflightVouchWithBottle sponsor peer has no stable info", log: tplogDebug, type: .default)
- reply(nil, nil, nil, ContainerError.sponsorNotRegistered(bottleMO.peerID ?? "no peer ID given"))
+ // 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
}
- do {
- // We need to extract the syncing policy that the remote peer would have used (if they were the type of device that we are)
- // So, figure out their policy version...
- let (views, policy) = try self.policyAndViewsFor(permanentInfo: egoPermanentInfo, stableInfo: sponsorPeerStableInfo)
+ 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
+ }
- reply(bottleMO.peerID, views, policy, nil)
- } catch {
- os_log("preflightVouchWithBottle failed to fetch policy: %{public}@", log: tplogDebug, type: .default, (error as CVarArg?) ?? "")
- reply(nil, nil, nil, error)
+ // 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)
+ }
}
--- /dev/null
+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<BottleMO> = self.containerMO.bottles as? Set<BottleMO> 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
+
+ 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)
+
+ 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<EscrowRecordMO> {
+ viableRecords = fullyViableEscrowRecords.compactMap { $0.escrowMetadata?.bottleID }
+ }
+ if let partiallyViableEscrowRecords = self.containerMO.partiallyViableEscrowRecords as? Set<EscrowRecordMO> {
+ 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<EscrowRecordMO> {
+ 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<EscrowRecordMO> {
+ 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<EscrowRecordMO> {
+ 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)
+ }
+}
// 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 }.isEmpty
+ let runUpgrade = knownMachineMOs.contains { $0.allowed }
if runUpgrade {
knownMachineMOs.forEach { mo in
if mo.allowed {
machine.modified = Date()
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 %{public}@, ignoring: %{public}@", log: tplogDebug, type: .default, machine.modifiedDate(), String(describing: machine.machineID))
differences = true
}
}
-
} else if machine.status == TPMachineIDStatus.unknown.rawValue {
if machine.modifiedInPast(hours: cutoffHours) {
os_log("Unknown machine ID last modified %{public}@; leaving unknown: %{public}@", log: tplogDebug, type: .default, machine.modifiedDate(), 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
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
--- /dev/null
+import CloudKitCode
+import CloudKitCodeProtobuf
+import CoreData
+import Foundation
+import os
+import Security
+import SecurityFoundation
+
+extension Container {
+ internal static func removingDuplicates(vouchers: Set<VoucherMO>) -> Set<VoucherMO> {
+ var unique: Set<VoucherMO> = 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<PeerMO> = Set()
+ let peers = container.peers as? Set<PeerMO> ?? Set()
+ for peer in peers {
+ let vouchers = peer.vouchers as? Set<VoucherMO> ?? 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)
+ }
+ }
+}
extension Container {
func preflightVouchWithRecoveryKey(recoveryKey: String,
salt: String,
- reply: @escaping (String?, Set<String>?, TPPolicy?, Error?) -> Void) {
+ reply: @escaping (String?, TPSyncingPolicy?, Error?) -> Void) {
self.semaphore.wait()
- let reply: (String?, Set<String>?, TPPolicy?, Error?) -> Void = {
+ let reply: (String?, TPSyncingPolicy?, Error?) -> Void = {
os_log("preflightRecoveryKey complete: %{public}@",
- log: tplogTrace, type: .info, traceError($3))
+ log: tplogTrace, type: .info, traceError($2))
self.semaphore.signal()
- reply($0, $1, $2, $3)
+ 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, nil, fetchError)
+ reply(nil, nil, fetchError)
return
}
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, nil, fetchPolicyDocumentsError)
+ reply(nil, nil, fetchPolicyDocumentsError)
return
}
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, nil, ContainerError.noPreparedIdentity)
- return
+ 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, nil, ContainerError.invalidPermanentInfoOrSig)
+ reply(nil, nil, ContainerError.invalidPermanentInfoOrSig)
return
}
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, nil, ContainerError.failedToCreateRecoveryKey)
+ 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, nil, ContainerError.recoveryKeysNotEnrolled)
+ reply(nil, nil, ContainerError.recoveryKeysNotEnrolled)
return
}
- guard let sponsorPeerID = self.model.peerIDThatTrustsRecoveryKeys(TPRecoveryKeyPair(signingSPKI: recoveryKeys.peerKeys.signingKey.publicKey.keyData,
- encryptionSPKI: recoveryKeys.peerKeys.encryptionKey.publicKey.keyData)) else {
+ 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, nil, ContainerError.untrustedRecoveryKeys)
+ 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, nil, ContainerError.sponsorNotRegistered(sponsorPeerID))
+ reply(nil, nil, ContainerError.sponsorNotRegistered(sponsorPeerID))
return
}
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)
- let views = try bestPolicy.views(forModel: selfPermanentInfo.modelID)
- reply(recoveryKeys.peerKeys.peerID, views, bestPolicy, nil)
+ reply(recoveryKeys.peerKeys.peerID, syncingPolicy, nil)
} catch {
os_log("preflightRecoveryKey: error fetching policy: %{public}@", log: tplogDebug, type: .default, error as CVarArg)
- reply(nil, nil, nil, error)
+ reply(nil, nil, error)
return
}
}
--- /dev/null
+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)
+ }
+}
self.publicSigningKey = signingKey.publicKey as? _SFECPublicKey
guard let encryptionVerificationKey = self.publicEncryptionKey,
- let signingVerificationKey = self.publicSigningKey else {
+ let signingVerificationKey = self.publicSigningKey else {
throw OctagonSelfPeerKeysError.noPublicKeys
}
let plaintextPolicy: TPPolicyDocument
}
-let prevailingPolicyVersion = TPPolicyVersion(version: 6, hash: "SHA256:L2Px1aYyR1tgChe8dIyTBSmCHCWEFJirZ3ELMFXz2PY=")
+let prevailingPolicyVersion = TPPolicyVersion(version: 7, hash: "SHA256:dL8Qujqzprhp6FdH5GzNMtPlnZtLWMwfiiF7aykr8WU=")
// 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 = [
],
redactions: [:],
keyViewMapping: [],
+ userControllableViewList: [],
+ piggybackViews: [],
hashAlgo: .SHA256)
),
],
redactions: [:],
keyViewMapping: [],
+ userControllableViewList: [],
+ piggybackViews: [],
hashAlgo: .SHA256)
),
TPPBPolicyKeyViewMapping(view: "Backstop",
matchingRule: TPDictionaryMatchingRule.fieldMatch("agrp", fieldRegex: "^com.apple.cfnetwork$")),
],
+ userControllableViewList: [],
+ piggybackViews: [],
hashAlgo: .SHA256)
),
RawPolicy(version: TPPolicyVersion(version: 4, hash: "SHA256:Tjdu5QrWGvKWMx7k3VWFrEWSsBDPZAwCql9ybDkvFs8="),
TPDictionaryMatchingRule.fieldMatch("vwht", fieldRegex: "^WatchMigration$"),
])),
],
+ userControllableViewList: [],
+ piggybackViews: [],
hashAlgo: .SHA256)
),
TPPBPolicyKeyViewMapping(view: "Backstop", matchingRule:
TPDictionaryMatchingRule.trueMatch()),
],
+ userControllableViewList: [],
+ piggybackViews: [],
hashAlgo: .SHA256)
),
TPPBPolicyKeyViewMapping(view: "Backstop", matchingRule:
TPDictionaryMatchingRule.trueMatch()),
],
+ userControllableViewList: [],
+ piggybackViews: [],
+ 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: [],
hashAlgo: .SHA256)
),
+
+ // Note to you, the next person to add a policy:
+ // We added user_controllable_views to the policy proto after creating v7. Pushing a new policy just to fill
+ // in that section seemed unnecessary. When you create v8, please fill it in. See the hacky v7 patch in TPPolicy.m.
+ // We added views_to_piggyback to the policy proto after creating v7 as well.
+
]
// swiftlint:enable force_try
let data = Data(base64Encoded: raw.policyData)!
let doc = TPPolicyDocument.policyDoc(withHash: raw.version.policyHash, data: data)!
- if(!doc.isEqual(to: raw.plaintextPolicy)) {
+ if !doc.isEqual(to: raw.plaintextPolicy) {
let bodyData = raw.plaintextPolicy.protobuf
let bodyBase64 = bodyData.base64EncodedString()
let hash = TPHashBuilder.hash(with: .SHA256, of: bodyData)
}
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 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)
}
let infoString = Array("Recovery Signing Private Key".utf8)
info = Data(bytes: infoString, count: infoString.count)
-
}
guard let cp = ccec_cp_384() else {
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)
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())
}
class func storeRecoveryedEncryptionKeyPair(keyData: Data, label: String) throws -> (Bool) {
-
let query: [CFString: Any] = [
kSecClass: kSecClassKey,
kSecAttrAccessible: kSecAttrAccessibleWhenUnlocked,
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)
}
extension RecoveryKeySetError: CustomNSError {
-
public static var errorDomain: String {
return "com.apple.security.trustedpeers.RecoveryKeySetError"
}
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<String>) 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 {
#import <SecurityFoundation/SFKey.h>
#import <SecurityFoundation/SFKey_Private.h>
#import <corecrypto/ccsha2.h>
-#import <CommonCrypto/CommonRandomSPI.h>
+#import <corecrypto/ccrng.h>
@implementation TPHObjectiveC : NSObject
#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"
#import <corecrypto/cchkdf.h>
#import <corecrypto/ccsha2.h>
#import <corecrypto/ccec.h>
+#import <corecrypto/ccrng.h>
-#import <CommonCrypto/CommonRandomSPI.h>
#import <Security/SecCFAllocator.h>
#include <Security/SecRecoveryKey.h>
+
+#if TARGET_OS_OSX
+#include <sandbox.h>
+#endif
<true/>
<key>com.apple.private.cloudkit.systemService</key>
<true/>
+ <key>com.apple.private.cloudkit.spi</key>
+ <true/>
<key>com.apple.private.cloudkit.supportservice</key>
<true/>
<key>com.apple.private.cloudkit.prefix</key>
</array>
<key>com.apple.symptom_diagnostics.report</key>
<true/>
+ <key>seatbelt-profiles</key>
+ <array>
+ <string>temporary-sandbox</string>
+ </array>
+ <key>com.apple.security.ts.cloudkit-client</key>
+ <true/>
+ <key>com.apple.security.exception.files.absolute-path.read-write</key>
+ <array>
+ <string>/private/var/Keychains/</string>
+ </array>
+ <key>com.apple.security.exception.mach-lookup.global-name</key>
+ <array>
+ <string>com.apple.securityd</string>
+ <string>com.apple.security.sfkeychainserver</string>
+ </array>
+ <key>com.apple.security.exception.shared-preference.read-write</key>
+ <array>
+ <string>com.apple.TrustedPeersHelper</string>
+ </array>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="17026" systemVersion="19E219" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
+<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="17162" systemVersion="20A2347" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="Bottle" representedClassName="BottleMO" syncable="YES" codeGenerationType="class">
<attribute name="bottleID" optional="YES" attributeType="String"/>
<attribute name="contents" optional="YES" attributeType="Binary"/>
<attribute name="egoPeerPermanentInfoSig" optional="YES" attributeType="Binary"/>
<attribute name="egoPeerStableInfo" optional="YES" attributeType="Binary"/>
<attribute name="egoPeerStableInfoSig" optional="YES" attributeType="Binary"/>
+ <attribute name="escrowFetchDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="honorIDMSListChanges" optional="YES" attributeType="String" defaultValueString="UNKNOWN"/>
<attribute name="moreChanges" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="name" optional="YES" attributeType="String"/>
<attribute name="recoveryKeyEncryptionSPKI" optional="YES" attributeType="Binary"/>
<attribute name="recoveryKeySigningSPKI" optional="YES" attributeType="Binary"/>
<relationship name="bottles" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Bottle" inverseName="container" inverseEntity="Bottle"/>
+ <relationship name="fullyViableEscrowRecords" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="EscrowRecord" inverseName="fullyViableEscrowRecords" inverseEntity="EscrowRecord"/>
+ <relationship name="legacyEscrowRecords" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="EscrowRecord" inverseName="legacyEscrowRecords" inverseEntity="EscrowRecord"/>
<relationship name="machines" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Machine" inverseName="container" inverseEntity="Machine"/>
+ <relationship name="partiallyViableEscrowRecords" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="EscrowRecord" inverseName="partiallyViableEscrowRecords" inverseEntity="EscrowRecord"/>
<relationship name="peers" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="Peer" inverseName="container" inverseEntity="Peer"/>
<relationship name="policies" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="Policy" inverseName="container" inverseEntity="Policy"/>
</entity>
+ <entity name="EscrowClientMetadata" representedClassName="EscrowClientMetadataMO" syncable="YES" codeGenerationType="class">
+ <attribute name="deviceColor" optional="YES" attributeType="String"/>
+ <attribute name="deviceEnclosureColor" optional="YES" attributeType="String"/>
+ <attribute name="deviceMid" optional="YES" attributeType="String"/>
+ <attribute name="deviceModel" optional="YES" attributeType="String"/>
+ <attribute name="deviceModelClass" optional="YES" attributeType="String"/>
+ <attribute name="deviceModelVersion" optional="YES" attributeType="String"/>
+ <attribute name="deviceName" optional="YES" attributeType="String"/>
+ <attribute name="devicePlatform" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
+ <attribute name="secureBackupMetadataTimestamp" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
+ <attribute name="secureBackupNumericPassphraseLength" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
+ <attribute name="secureBackupUsesComplexPassphrase" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
+ <attribute name="secureBackupUsesNumericPassphrase" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
+ <relationship name="escrowMetadata" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="EscrowMetadata" inverseName="clientMetadata" inverseEntity="EscrowMetadata"/>
+ </entity>
+ <entity name="EscrowMetadata" representedClassName="EscrowMetadataMO" syncable="YES" codeGenerationType="class">
+ <attribute name="backupKeybagDigest" optional="YES" attributeType="Binary"/>
+ <attribute name="bottleID" optional="YES" attributeType="String"/>
+ <attribute name="escrowedSPKI" optional="YES" attributeType="Binary"/>
+ <attribute name="peerInfo" optional="YES" attributeType="Binary"/>
+ <attribute name="secureBackupTimestamp" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
+ <attribute name="secureBackupUsesMultipleiCSCS" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
+ <attribute name="serial" optional="YES" attributeType="String"/>
+ <relationship name="clientMetadata" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="EscrowClientMetadata" inverseName="escrowMetadata" inverseEntity="EscrowClientMetadata"/>
+ <relationship name="escrowRecord" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="EscrowRecord" inverseName="escrowMetadata" inverseEntity="EscrowRecord"/>
+ </entity>
+ <entity name="EscrowRecord" representedClassName="EscrowRecordMO" syncable="YES" codeGenerationType="class">
+ <attribute name="creationDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
+ <attribute name="label" optional="YES" attributeType="String"/>
+ <attribute name="recordStatus" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
+ <attribute name="remainingAttempts" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
+ <attribute name="silentAttemptAllowed" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
+ <attribute name="sosViability" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
+ <relationship name="escrowMetadata" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="EscrowMetadata" inverseName="escrowRecord" inverseEntity="EscrowMetadata"/>
+ <relationship name="fullyViableEscrowRecords" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Container" inverseName="fullyViableEscrowRecords" inverseEntity="Container"/>
+ <relationship name="legacyEscrowRecords" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Container" inverseName="legacyEscrowRecords" inverseEntity="Container"/>
+ <relationship name="partiallyViableEscrowRecords" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Container" inverseName="partiallyViableEscrowRecords" inverseEntity="Container"/>
+ </entity>
<entity name="Machine" representedClassName="MachineMO" syncable="YES" codeGenerationType="class">
<attribute name="allowed" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="machineID" optional="YES" attributeType="String"/>
</entity>
<elements>
<element name="Bottle" positionX="-549" positionY="-234" width="128" height="150"/>
- <element name="Container" positionX="-758" positionY="-261" width="128" height="268"/>
+ <element name="Container" positionX="-758" positionY="-261" width="128" height="343"/>
+ <element name="EscrowClientMetadata" positionX="-513" positionY="-198" width="128" height="238"/>
+ <element name="EscrowMetadata" positionX="-522" positionY="-207" width="128" height="178"/>
+ <element name="EscrowRecord" positionX="-549" positionY="-234" width="128" height="179"/>
<element name="Machine" positionX="-549" positionY="-234" width="128" height="133"/>
<element name="Peer" positionX="-414" positionY="-387" width="128" height="210"/>
<element name="Policy" positionX="-414" positionY="54" width="128" height="105"/>
<element name="RecoveryVoucher" positionX="-65" positionY="-297" width="128" height="105"/>
<element name="Voucher" positionX="-65" positionY="-171" width="128" height="90"/>
</elements>
-</model>
+</model>
\ No newline at end of file
#import <Foundation/Foundation.h>
#import <TrustedPeers/TrustedPeers.h>
+#import <objc/runtime.h>
#import "keychain/ckks/CKKSKeychainBackedKey.h"
#import "keychain/ckks/CKKSTLKShare.h"
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 TPPolicyVersion *)policyVersion
policySecrets:(nullable NSDictionary<NSString*,NSData*> *)policySecrets
+ syncUserControllableViews:(TPPBPeerStableInfo_UserControllableViewStatus)syncUserControllableViews
signingPrivKeyPersistentRef:(nullable NSData *)spkPr
encPrivKeyPersistentRef:(nullable NSData*)epkPr
reply:(void (^)(NSString * _Nullable peerID,
NSData * _Nullable permanentInfoSig,
NSData * _Nullable stableInfo,
NSData * _Nullable stableInfoSig,
- NSSet<NSString*>* _Nullable syncingViewList,
- TPPolicy* _Nullable syncingPolicy,
+ TPSyncingPolicy* _Nullable syncingPolicy,
NSError * _Nullable error))reply;
// If there already are existing CKKSViews, please pass in their key sets anyway.
preapprovedKeys:(nullable NSArray<NSData*> *)preapprovedKeys
reply:(void (^)(NSString * _Nullable peerID,
NSArray<CKRecord*>* _Nullable keyHierarchyRecords,
+ TPSyncingPolicy* _Nullable syncingPolicy,
NSError * _Nullable error))reply;
// Returns a voucher for the given peer ID using our own identity
// 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,
- NSSet<NSString*>* _Nullable peerSyncingViewList,
- TPPolicy * _Nullable peerSyncingPolicy,
+ TPSyncingPolicy* _Nullable syncingPolicy,
+ BOOL refetchWasNeeded,
NSError * _Nullable error))reply;
// Returns a voucher for our own identity, created by the identity inside this bottle
recoveryKey:(NSString*)recoveryKey
salt:(NSString*)salt
reply:(void (^)(NSString* _Nullable recoveryKeyID,
- NSSet<NSString*>* _Nullable peerSyncingViewList,
- TPPolicy * _Nullable peerSyncingPolicy,
+ TPSyncingPolicy* _Nullable syncingPolicy,
NSError * _Nullable error))reply;
// Returns a voucher for our own identity, using recovery key
voucherSig:(NSData *)voucherSig
ckksKeys:(NSArray<CKKSKeychainBackedKeySet*> *)viewKeySets
tlkShares:(NSArray<CKKSTLKShare*> *)tlkShares
- preapprovedKeys:(NSArray<NSData*> *)preapprovedKeys
+ preapprovedKeys:(nullable NSArray<NSData*> *)preapprovedKeys
reply:(void (^)(NSString * _Nullable peerID,
NSArray<CKRecord*>* _Nullable keyHierarchyRecords,
- NSSet<NSString*>* _Nullable syncingViewList,
- TPPolicy* _Nullable syncingPolicy,
+ 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<NSData*> *)preapprovedKeys
reply:(void (^)(BOOL launchOkay,
NSError * _Nullable error))reply;
context:(NSString *)context
ckksKeys:(NSArray<CKKSKeychainBackedKeySet*> *)ckksKeys
tlkShares:(NSArray<CKKSTLKShare*> *)tlkShares
- preapprovedKeys:(NSArray<NSData*> *)preapprovedKeys
+ preapprovedKeys:(nullable NSArray<NSData*> *)preapprovedKeys
reply:(void (^)(NSString * _Nullable peerID,
NSArray<CKRecord*>* _Nullable keyHierarchyRecords,
- NSSet<NSString*>* _Nullable syncingViewList,
- TPPolicy* _Nullable syncingPolicy,
+ 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
osVersion:(nullable NSString *)osVersion
policyVersion:(nullable NSNumber *)policyVersion
policySecrets:(nullable NSDictionary<NSString*,NSData*> *)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
context:(NSString *)context
reply:(void (^)(NSArray<NSString*>* _Nullable sortedBottleIDs, NSArray<NSString*>* _Nullable sortedPartialBottleIDs, NSError* _Nullable error))reply;
+- (void)fetchViableEscrowRecordsWithContainer:(NSString *)container
+ context:(NSString *)context
+ forceFetch:(BOOL)forceFetch
+ reply:(void (^)(NSArray<NSData*>* _Nullable records, NSError* _Nullable error))reply;
+
- (void)fetchEscrowContentsWithContainer:(NSString *)container
context:(NSString *)context
reply:(void (^)(NSData* _Nullable entropy,
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
- reply:(void (^)(NSSet<NSString*>* _Nullable syncingViewList,
- TPPolicy * _Nullable syncingPolicy,
+ modelIDOverride:(NSString* _Nullable)modelID
+ reply:(void (^)(TPSyncingPolicy* _Nullable syncingPolicy,
+ TPPBPeerStableInfo_UserControllableViewStatus userControllableViewStatusOfPeers,
NSError * _Nullable error))reply;
- (void)validatePeersWithContainer:(NSString *)container
recoveryKey:(NSString *)recoveryKey
salt:(NSString *)salt
ckksKeys:(NSArray<CKKSKeychainBackedKeySet*> *)ckksKeys
- reply:(void (^)(NSError* _Nullable error))reply;
+ reply:(void (^)(NSArray<CKRecord*>* _Nullable keyHierarchyRecords,
+ NSError* _Nullable error))reply;
- (void)reportHealthWithContainer:(NSString *)container
context:(NSString *)context
context:(NSString *)context
reply:(void (^)(NSData * _Nullable, NSError * _Nullable))reply;
+- (void)removeEscrowCacheWithContainer:(NSString *)container
+ context:(NSString *)context
+ reply:(void (^)(NSError * _Nullable))reply;
+
@end
/*
#import "utilities/debugging.h"
#import <CloudKit/CloudKit.h>
#import <CloudKit/CloudKit_Private.h>
+#import <Security/SecXPCHelper.h>
#endif
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 {
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];
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:
tlkShares:
reply:) argumentIndex:4 ofReply:NO];
- [interface setClasses:[NSSet setWithObject:[TPPolicy class]] forSelector:@selector(fetchCurrentPolicyWithContainer:
- context:
- reply:) argumentIndex:1 ofReply:YES];
-
[interface setClasses:trustedPeersHelperPeerState forSelector:@selector(updateWithContainer:
context:
deviceName:
osVersion:
policyVersion:
policySecrets:
+ syncUserControllableViews:
reply:) argumentIndex:0 ofReply:YES];
[interface setClasses:trustedPeersHelperPeerState forSelector:@selector(fetchTrustStateWithContainer:
}
@catch(NSException* e) {
secerror("TrustedPeersHelperSetupProtocol failed, continuing, but you might crash later: %@", e);
-#if DEBUG
@throw e;
-#endif
}
#endif
- (NSString*)description
{
- return [NSString stringWithFormat:@"<TPHPeerState: %@ preapproved:%d status:%lld memberChanges: %@ unk. mIDs: %@ osVersion: %@>",
+ return [NSString stringWithFormat:@"<TPHPeerState: %@ preapproved:%d status:%@ memberChanges: %@ unk. mIDs: %@ osVersion: %@>",
self.peerID,
self.identityIsPreapproved,
- (int64_t)self.peerStatus,
+ TPPeerStatusToString(self.peerStatus),
self.memberChanges ? @"YES" : @"NO",
self.unknownMachineIDsPresent ? @"YES" : @"NO",
self.osVersion?:@"unknown"];
--- /dev/null
+(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/")
+)
}
}
+#if os(macOS)
+public func withArrayOfCStrings<R>(
+ _ args: [String],
+ _ body: ([UnsafePointer<CChar>?]) -> 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<CChar>?
+
+ 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()
#import <Foundation/Foundation.h>
#import <ProtocolBuffer/PBCodable.h>
-@class OTPrivateKey;
@class OTPrivateKey;
#ifdef __cplusplus
disabled_rules:
- force_cast
- force_try
+ - implicitly_unwrapped_optional
import XCTest
extension Container {
-
func dumpSync(test: XCTestCase) -> ([AnyHashable: Any]?, Error?) {
let expectation = XCTestExpectation(description: "dump replied")
var reta: [AnyHashable: Any]?, reterr: Error?
osVersion: String = "123",
policyVersion: TPPolicyVersion? = nil,
policySecrets: [String: Data]? = nil,
+ syncUserControllableViews: TPPBPeerStableInfo_UserControllableViewStatus = .UNKNOWN,
signingPrivateKeyPersistentRef: Data? = nil,
encryptionPrivateKeyPersistentRef: Data? = nil
- ) -> (String?, Data?, Data?, Data?, Data?, Set<String>?, TPPolicy?, 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 retviews: Set<String>?
- var retpolicy: TPPolicy?
+ var retpolicy: TPSyncingPolicy?
self.prepare(epoch: epoch,
machineID: machineID,
bottleSalt: bottleSalt,
osVersion: osVersion,
policyVersion: policyVersion,
policySecrets: policySecrets,
+ syncUserControllableViews: syncUserControllableViews,
signingPrivateKeyPersistentRef: signingPrivateKeyPersistentRef,
encryptionPrivateKeyPersistentRef: encryptionPrivateKeyPersistentRef
- ) { a, b, c, d, e, f, g, err in
+ ) { a, b, c, d, e, f, err in
reta = a
retb = b
retc = c
retd = d
rete = e
- retviews = f
- retpolicy = g
+ retpolicy = f
reterr = err
expectation.fulfill()
}
test.wait(for: [expectation], timeout: 10.0)
- return (reta, retb, retc, retd, rete, retviews, retpolicy, 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,
return (reta, retb, reterr)
}
- func preflightVouchWithBottleSync(test: XCTestCase, bottleID: String) -> (String?, Set<String>?, TPPolicy?, Error?) {
+ func preflightVouchWithBottleSync(test: XCTestCase, bottleID: String) -> (String?, TPSyncingPolicy?, Bool, Error?) {
let expectation = XCTestExpectation(description: "preflightVouchWithBottle replied")
var reta: String?, reterr: Error?
- var retviews: Set<String>?, retpolicy: TPPolicy?
- self.preflightVouchWithBottle(bottleID: bottleID) { a, views, policy, err in
+ var retrefetched: Bool = false
+ var retpolicy: TPSyncingPolicy?
+ self.preflightVouchWithBottle(bottleID: bottleID) { a, policy, refetched, err in
reta = a
- retviews = views
retpolicy = policy
+ retrefetched = refetched
reterr = err
expectation.fulfill()
}
test.wait(for: [expectation], timeout: 10.0)
- return (reta, retviews, retpolicy, reterr)
+ return (reta, retpolicy, retrefetched, reterr)
}
func vouchWithBottleSync(test: XCTestCase, b: String, entropy: Data, bottleSalt: String, tlkShares: [CKKSTLKShare]) -> (Data?, Data?, Int64, Int64, Error?) {
voucherSig: Data,
ckksKeys: [CKKSKeychainBackedKeySet],
tlkShares: [CKKSTLKShare],
- preapprovedKeys: [Data]? = nil) -> (String?, [CKRecord]?, Set<String>?, TPPolicy?, Error?) {
+ preapprovedKeys: [Data]? = nil) -> (String?, [CKRecord]?, TPSyncingPolicy?, Error?) {
let expectation = XCTestExpectation(description: "join replied")
var reta: String?, retkhr: [CKRecord]?, reterr: Error?
- var retviews: Set<String>?, retpolicy: TPPolicy?
+ var retpolicy: TPSyncingPolicy?
self.join(voucherData: voucherData,
voucherSig: voucherSig,
ckksKeys: ckksKeys,
tlkShares: tlkShares,
- preapprovedKeys: preapprovedKeys) { a, khr, views, policy, err in
+ preapprovedKeys: preapprovedKeys) { a, khr, policy, err in
reta = a
retkhr = khr
- retviews = views
retpolicy = policy
reterr = err
expectation.fulfill()
}
test.wait(for: [expectation], timeout: 10.0)
- return (reta, retkhr, retviews, retpolicy, reterr)
+ return (reta, retkhr, retpolicy, reterr)
}
func preapprovedJoinSync(test: XCTestCase,
ckksKeys: [CKKSKeychainBackedKeySet],
tlkShares: [CKKSTLKShare],
- preapprovedKeys: [Data]? = nil) -> (String?, [CKRecord]?, Set<String>?, TPPolicy?, Error?) {
+ preapprovedKeys: [Data]? = nil) -> (String?, [CKRecord]?, TPSyncingPolicy?, Error?) {
let expectation = XCTestExpectation(description: "preapprovedjoin replied")
var reta: String?
var retkhr: [CKRecord]?
- var retviews: Set<String>?
- var retpolicy: TPPolicy?
+ var retpolicy: TPSyncingPolicy?
var reterr: Error?
self.preapprovedJoin(ckksKeys: ckksKeys,
tlkShares: tlkShares,
- preapprovedKeys: preapprovedKeys) { a, khr, views, policy, err in
+ preapprovedKeys: preapprovedKeys) { a, khr, policy, err in
reta = a
retkhr = khr
- retviews = views
retpolicy = policy
reterr = err
expectation.fulfill()
}
test.wait(for: [expectation], timeout: 10.0)
- return (reta, retkhr, retviews, retpolicy, 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<String>, accountIsDemo: Bool, listDifference: Bool = true) -> (Error?) {
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?) {
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?
//
import CloudKitCode
+import CloudKitCodeProtobuf
import Foundation
-enum FakeCuttlefishError: Error {
- case notEmpty
- case unknownChangeToken
- case unknownPeerID
-}
-
enum FakeCuttlefishOpinion {
case trusts
case trustsByPreapproval
class FakeCuttlefishNotify: NSObject {
let pushes: (Data) -> Void
let containerName: String
+
@objc
init(_ containerName: String, pushes: @escaping (Data) -> Void) {
self.containerName = containerName
}
@objc
- public func notify(_ function: String) throws {
+ func notify(_ function: String) throws {
let notification: [String: [String: Any]] = [
"aps": ["content-available": 1],
"cf": [
}
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]] = [:]
// @property (nullable) NSMutableDictionary<CKRecordZoneID*, ZoneKeys*>* keys;
var ckksZoneKeys: NSMutableDictionary
+ var injectLegacyEscrowRecords: Bool = false
+ var includeEscrowRecords: Bool = true
+
var nextFetchErrors: [Error] = []
var fetchViableBottlesError: [Error] = []
var nextJoinErrors: [Error] = []
var returnLeaveTrustResponse: Bool = false
var returnRepairErrorResponse: Error?
var fetchChangesCalledCount: Int = 0
+ var fetchChangesReturnEmptyResponse: Bool = false
+
+ var fetchViableBottlesEscrowRecordCacheTimeout: TimeInterval = 2.0
var nextEstablishReturnsMoreChanges: Bool = false
}
}
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
if self.state.recoveryEncryptionPubKey != snapshot.recoveryEncryptionPubKey {
changes.recoveryEncryptionPubKey = self.state.recoveryEncryptionPubKey ?? Data()
}
-
}
}
let record = share.fakeRecord(zoneID: rzid)
fakeZone.add(toZone: record)
allRecords.append(record)
-
} else {
print("Received an unexpected zone id: \(rzid)")
}
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
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))
}
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))
}
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)
+ completion(nil, FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .updateTrustPeerNotFound))
return
}
if request.hasStableInfoAndSig {
}
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")
}
completion(nil, possibleError)
return
}
+ if fetchChangesReturnEmptyResponse == true {
+ completion(FetchChangesResponse(), nil)
+ return
+ }
}
if let injectedError = self.nextFetchErrors.first {
}
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
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)
}
func getSupportAppInfo(_: GetSupportAppInfoRequest, completion: @escaping (GetSupportAppInfoResponse?, Error?) -> Void) {
completion(GetSupportAppInfoResponse(), nil)
}
+
+ func fetchSosiCloudIdentity(_: FetchSOSiCloudIdentityRequest, completion: @escaping (FetchSOSiCloudIdentityResponse?, Error?) -> Void) {
+ completion(FetchSOSiCloudIdentityResponse(), nil)
+ }
}
extension FakeCuttlefishServer: CloudKitCode.Invocable {
}
class MockCuttlefishAPIAsyncClient: CuttlefishAPIAsync {
-
var handlers: [Handler] = []
var index: Int = 0
}
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)
+ }
}
#import <SecurityFoundation/SFKey_Private.h>
#import "keychain/TrustedPeersHelper/TrustedPeersHelper-Bridging-Header.h"
+#import "keychain/securityd/SecItemDataSource.h"
#import "keychain/ckks/tests/MockCloudKit.h"
// Created by Ben Williamson on 5/1/18.
//
+import CloudKitCodeProtobuf
import CoreData
import XCTest
let recovery_encryptionKey_384 = Data(base64Encoded: "BKkZpYHTbMi2yrWFo+ErM3HbcYJCngPuWDYoVUD7egKkmiHFvv1Bsk0j/Dcj3xTR12vj5QOpZQV3GzE5estf75BV+EZz1cjUUSi/MysfpKsqEbwYrhIEkmeyMGr7CVWQWRLR2LnoihnQajvWi1LmO0AoDl3+LzVgTJBjjDQ5ANyw0Yv1EgOgBvZsLA9UTN4oAg==")
class TrustedPeersHelperUnitTests: XCTestCase {
-
var tmpPath: String!
var tmpURL: URL!
var cuttlefish: FakeCuttlefishServer!
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)
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()
}
contextID: String,
allowedMachineIDs: Set<String> = 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, 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: "iPhone1,1")
+ let (peerID, permanentInfo, permanentInfoSig, _, _, _, error) = container.prepareSync(test: self,
+ epoch: 1,
+ machineID: "aaa",
+ bottleSalt: "123456789",
+ bottleID: UUID().uuidString,
+ modelID: modelID,
+ syncUserControllableViews: syncUserControllableViews)
+
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")
}
}
- 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)
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")
// Now set up a machine ID list that positively does not have our peer
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")
}
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)
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!)
}
XCTAssertNil(containerC.setAllowedMachineIDsSync(test: self, allowedMachineIDs: machineIDs, accountIsDemo: false))
print("preparing A")
- let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, aViewList, aPolicy, error) =
+ let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, aPolicy, error) =
containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1")
- XCTAssertNotNil(aViewList, "Should have a view list coming back from a successful prepare")
- XCTAssertNotNil(aPolicy, "Should have a policy coming back from a successful prepare")
+ 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")
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")
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)
_ = 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")
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"))
print("A updates")
do {
- let (_, error) = containerA.updateSync(test: self)
+ let (_, _, error) = containerA.updateSync(test: self)
XCTAssertNil(error)
}
_ = 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")
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")
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")
}
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")
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"))
let machineIDs = Set(["aaa"])
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")
do {
let error = containerA.localResetSync(test: self)
XCTAssertNil(error, "local-reset shouldn't error")
+ let peers = containerA.containerMO.peers as! Set<PeerMO>
+ XCTAssertEqual(peers.count, 0, "peers should be empty ")
}
do {
let (dict, error) = containerA.dumpSync(test: self)
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")
}
// 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 missingTuple = TPPolicyVersion(version: 900, hash: "not a hash")
}
func testEscrowKeys() throws {
-
XCTAssertThrowsError(try EscrowKeys.retrieveEscrowKeysFromKeychain(label: "hash"), "retrieveEscrowKeysFromKeychain should throw error")
XCTAssertThrowsError(try EscrowKeys.findEscrowKeysForLabel(label: "hash"), "findEscrowKeysForLabel should throw error")
}
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)
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()
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")
_ = 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")
do {
print("B prepares to join via bottle")
- let (bottlePeerID, views, policy, 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(views, "Should have a set of views to restore")
XCTAssertNotNil(policy, "Should have a policy")
let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: entropy, bottleSalt: "123456789", tlkShares: [])
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!)
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()
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")
_ = 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")
do {
print("B prepares to join via bottle")
- let (bottlePeerID, views, policy, 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(views, "Should have a set of views to restore")
XCTAssertNotNil(policy, "Should have a policy")
let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: entropy, bottleSalt: "123456789", tlkShares: [])
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!)
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")
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")
_ = 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")
do {
print("B joins via bottle")
- let (bottlePeerID, views, policy, 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(views, "Should not have a set of views to restore")
XCTAssertNil(policy, "Should not have a policy")
let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: "wrong escrow record", entropy: entropy, bottleSalt: "123456789", tlkShares: [])
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")
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")
}
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")
do {
print("B joins via bottle")
- let (bottlePeerID, views, policy, errorPreflight) = containerB.preflightVouchWithBottleSync(test: self, bottleID: bottleB.bottleID!)
+ 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(views, "Should not have a set of views to restore")
XCTAssertNil(policy, "Should not have a policy")
let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: bottleB.bottleID!, entropy: entropy, bottleSalt: "123456789", tlkShares: [])
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")
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")
_ = 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")
do {
print("B joins via bottle")
- let (bottlePeerID, views, policy, 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(views, "Should have a set of views to restore")
XCTAssertNotNil(policy, "Should have a policy")
let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: entropy, bottleSalt: "987654321", tlkShares: [])
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")
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")
_ = 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")
do {
print("B joins via bottle")
- let (bottlePeerID, views, policy, 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(views, "Should have a set of views to restore")
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: [])
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()
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")
self.cuttlefish.fetchViableBottlesError.append(FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .changeTokenExpired))
- let (bottlePeerID, views, policy, 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(views, "Should not have a set of views to restore")
XCTAssertNil(policy, "Should not have a policy")
self.cuttlefish.fetchViableBottlesError.append(FakeCuttlefishServer.makeCloudKitCuttlefishError(code: .changeTokenExpired))
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"])
+ 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, _, _, aViewList, aPolicy, 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(aViewList, "Should have a view list coming back from a successful prepare")
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")
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, _, views, policy, 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(views, "should have a list of views to use")
- XCTAssertNotNil(policy, "Should have a policy back from preapprovedjoin")
+ 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 {
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])
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])
}
// 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
XCTAssertNotNil(deserializedBottle, "deserializedBottle should not be nil")
XCTAssertEqual(deserializedBottle.contents, bottle.contents, "bottle data should be equal")
-
} catch {
XCTFail("error testing bottles \(error)")
}
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)
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")
}
}
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, 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")
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")
}
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")
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, leaveTrust, healthError) = c.requestHealthCheckSync(requiresEscrowCheck: true, test: self)
- XCTAssertEqual(repairAccount, false, "")
- XCTAssertEqual(repairEscrow, false, "")
- XCTAssertEqual(resetOctagon, false, "")
- XCTAssertEqual(leaveTrust, false, "")
+ XCTAssertFalse(repairAccount, "")
+ XCTAssertFalse(repairEscrow, "")
+ XCTAssertFalse(resetOctagon, "")
+ XCTAssertFalse(leaveTrust, "")
XCTAssertNil(healthError)
}
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()
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")
_ = 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")
do {
print("B prepares to join via bottle")
- let (bottlePeerID, views, policy, 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(views, "Should have a set of views to restore")
XCTAssertNotNil(policy, "Should have a policy")
let (voucherData, voucherSig, _, _, error3) = containerB.vouchWithBottleSync(test: self, b: bottleA.bottleID!, entropy: entropy, bottleSalt: "123456789", tlkShares: [])
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")
}
}
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")
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")
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)
}
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)
}
let recoveryEncryptionPublicKey: Data? = stableInfo!["recovery_encryption_public_key"] as! Data?
XCTAssertNil(recoveryEncryptionPublicKey, "recoveryEncryptionPublicKey should be nil")
-
}
}
unknownMachineIDs: Set<String> = 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")
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)
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")
// 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)
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<PeerMO>
+ 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<PeerMO> {
+ 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")
var (container, peerID1) = try establish(reload: false, contextID: OTDefaultContext, allowedMachineIDs: Set(["aaa"]), accountIsDemo: false, store: description)
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, peerID3])
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)")
}
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])
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])
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)")
}
}
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)
let containerEgoStableInfo = TPPeerStableInfo(data: stableInfo!, sig: stableInfoSig!)
do {
let peerKeys: OctagonSelfPeerKeys = try loadEgoKeysSync(peerID: containerMO.egoPeerID!)
- let info3 = TPPeerStableInfo(clock: containerEgoStableInfo!.clock + 2,
- frozenPolicyVersion: containerEgoStableInfo!.frozenPolicyVersion,
- flexiblePolicyVersion: containerEgoStableInfo!.flexiblePolicyVersion!,
- 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
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")
+ 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")
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)
XCTAssertEqual(containerC.containerMO.honorIDMSListChanges, "UNKNOWN", "honorIDMSListChanges should be unknown")
print("preparing A")
- let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, aViewList, aPolicy, error) =
+ let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, aPolicy, error) =
containerA.prepareSync(test: self, epoch: 1, machineID: "aaa", bottleSalt: "123456789", bottleID: UUID().uuidString, modelID: "iPhone1,1")
- XCTAssertNotNil(aViewList, "Should have a view list coming back from a successful prepare")
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("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)
}
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)
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!)
}
_ = 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)
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, _, _, error2) = containerC.joinSync(test: self,
+ voucherData: voucherData!,
+ voucherSig: voucherSig!,
+ ckksKeys: [self.manateeKeySet, provisionalEngramKeySet],
+ tlkShares: [])
XCTAssertNil(error2)
XCTAssertEqual(peerID, cPeerID!)
print("A updates")
do {
- let (_, error) = containerA.updateSync(test: self)
+ let (_, _, error) = containerA.updateSync(test: self)
XCTAssertNil(error)
}
XCTAssertEqual(containerB.containerMO.honorIDMSListChanges, "UNKNOWN", "honorIDMSListChanges should be unknown")
print("preparing A")
- let (aPeerID, aPermanentInfo, aPermanentInfoSig, _, _, aViewList, aPolicy, 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(aViewList, "Should have a view list coming back from a successful prepare")
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) =
+ 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)
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()])
XCTAssertNil(error)
XCTAssertNotNil(peerID)
}
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, _, views, policy, bJoinedError) = containerB.preapprovedJoinSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [])
+ 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(views, "should have a list of views to use")
XCTAssertNotNil(policy, "Should have a policy back from preapprovedjoin")
assertTLKShareFor(peerID: bPeerID!, keyUUID: self.manateeKeySet.tlk.uuid, zoneID: CKRecordZone.ID(zoneName: "Manatee"))
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")
+ 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")
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: [])
+ let (peerID2, _, _, error2) = container.establishSync(test: self, ckksKeys: [self.manateeKeySet], tlkShares: [], preapprovedKeys: [])
XCTAssertNil(error2)
XCTAssertNotNil(peerID2)
}
- (instancetype)initWithCoder:(NSCoder *)coder {
- self = [super init];
- if (self) {
+ if ((self = [super init])) {
NSMutableSet *attributeClasses = [[[self class] supportedAttributeClasses] mutableCopy];
[attributeClasses addObject:[NSDictionary class]];
#import <os/transaction_private.h>
#import <Foundation/Foundation.h>
-#import <CFNetwork/CFURLConnection.h>
+#import <CFNetwork/CFNetworkPriv.h>
#import <Accounts/Accounts.h>
#import <Accounts/Accounts_Private.h>
#import <AppleAccount/ACAccount+AppleAccount.h>
#import "keychain/analytics/C2Metric/SECC2MPDeviceInfo.h"
#import <utilities/SecCoreAnalytics.h>
+#import <utilities/simulatecrash_assert.h>
+
@interface SecMetrics () <NSURLSessionDelegate>
+++ /dev/null
-/*
- * 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 <Foundation/Foundation.h>
-
-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
+++ /dev/null
-/*
- * 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 <dispatch/dispatch.h>
-
-#if __OBJC2__
-
-@interface SFBehavior ()
-@property NSString *family;
-@property NSXPCConnection *connection;
-- (instancetype)initBehaviorFamily:(NSString *)family connection:(NSXPCConnection *)connection;
-@end
-
-@protocol SFBehaviorProtocol <NSObject>
-- (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<NSString *, SFBehavior *> *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__ */
-
#ifdef __OBJC__
#import <Foundation/Foundation.h>
-NS_ASSUME_NONNULL_BEGIN
-#else
+#import "keychain/ot/OctagonStateMachine.h"
+#endif /* __OBJC__ */
+
CF_ASSUME_NONNULL_BEGIN
-#endif
#ifdef __OBJC__
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 <NSObject>
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 <NSObject>
@end
typedef NSString<SecCKKSZoneKeyState> CKKSZoneKeyState;
+#endif
+
+extern CKKSZoneKeyState* const SecCKKSZoneKeyStateWaitForCloudKitAccountStatus;
// CKKS is currently logged out
extern CKKSZoneKeyState* const SecCKKSZoneKeyStateLoggedOut;
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;
// 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.
// 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<CKKSZoneKeyState*, NSNumber*>* CKKSZoneKeyStateMap(void);
// 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<CKKSZoneKeyState*>* CKKSKeyStateNonTransientStates(void);
/* Hide Item Length */
extern const NSUInteger SecCKKSItemPaddingBlockSize;
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,
CKKSKeysMissing = 53,
CKKSCircularKeyReference = 54,
+
+ CKKSErrorViewIsPaused = 55,
+ CKKSErrorPolicyNotLoaded = 56,
+
+ CKKSErrorUnexpectedNil = 57,
};
typedef CF_ENUM(CFIndex, CKKSResultDescriptionErrorCode) {
//CKKSServerInvalidCurrentItem = 17,
};
+#if __OBJC__
+
#define SecTranslateError(nserrorptr, cferror) \
if(nserrorptr) { \
*nserrorptr = (__bridge_transfer NSError*)cferror; \
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 */
#import <CloudKit/CloudKit.h>
#endif
-#include <utilities/debugging.h>
#include "keychain/securityd/SecItemServer.h"
#include <Security/SecItemPriv.h>
#import "keychain/ckks/CKKSKey.h"
#import "keychain/ot/OTManager.h"
+#import "keychain/ot/OctagonStateMachineHelpers.h"
NSDictionary<CKKSZoneKeyState*, NSNumber*>* CKKSZoneKeyStateMap(void) {
static NSDictionary<CKKSZoneKeyState*, NSNumber*>* map = nil;
map = @{
SecCKKSZoneKeyStateReady: @0U,
SecCKKSZoneKeyStateError: @1U,
- SecCKKSZoneKeyStateCancelled: @2U,
+ //SecCKKSZoneKeyStateCancelled: @2U,
SecCKKSZoneKeyStateInitializing: @3U,
SecCKKSZoneKeyStateInitialized: @4U,
SecCKKSZoneKeyStateWaitForTLKUpload: @22U,
SecCKKSZoneKeyStateWaitForTLKCreation: @23U,
SecCKKSZoneKeyStateProcess: @24U,
+ SecCKKSZoneKeyStateBecomeReady: @25U,
+ SecCKKSZoneKeyStateLoseTrust: @26U,
+ SecCKKSZoneKeyStateTLKMissing: @27U,
+ SecCKKSZoneKeyStateWaitForCloudKitAccountStatus:@28U,
+ SecCKKSZoneKeyStateBeginFetch: @29U,
};
});
return map;
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<CKKSZoneKeyState*>* CKKSKeyStateNonTransientStates()
+{
+ static NSSet<CKKSZoneKeyState*>* 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
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;
}
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;
}
[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;
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;
}
[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;
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;
}
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];
});
}
}
// Ignore our own changes, otherwise we'd infinite-loop.
if(source == kSecDbCKKSTransaction) {
- secinfo("ckks", "Ignoring kSecDbCKKSTransaction notification");
+ ckksinfo_global("ckks", "Ignoring kSecDbCKKSTransaction notification");
return;
}
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;
}
void SecCKKSPerformLocalResync() {
#if OCTAGON
if(SecCKKSIsEnabled()) {
- secnotice("ckks", "Local keychain was reset; performing local resync");
+ ckksnotice_global("reset", "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);
+ ckksnotice_global("reset", "Local keychain reset resync finished with an error: %@", result);
} else {
- secnotice("ckks", "Local keychain reset resync finished successfully");
+ ckksnotice_global("reset", "Local keychain reset resync finished successfully");
}
}];
}
@end
@protocol CKKSCloudKitAccountStateTrackingProvider <NSObject>
- (dispatch_semaphore_t)registerForNotificationsOfCloudKitAccountStatusChange:(id<CKKSCloudKitAccountStateListener>)listener;
+- (BOOL)notifyCKAccountStatusChangeAndWait:(dispatch_time_t)timeout;
@end
#pragma mark -- Tracker
#if OCTAGON
#include <dispatch/dispatch.h>
-#include <utilities/debugging.h>
#include <Security/SecureObjectSync/SOSCloudCircle.h>
#include <Security/SecureObjectSync/SOSCloudCircleInternal.h>
#include "keychain/SecureObjectSync/SOSInternal.h"
_hsa2iCloudAccountInitialized = [[CKKSCondition alloc] init];
id<CKKSNSNotificationCenter> 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);
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;
}
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];
});
}];
[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;
}
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;
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) {
[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;
}
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;
}];
} 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];
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;
}
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];
}
}
+- (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 {
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;
}
while ((dq = [enumerator nextObject])) {
id<CKKSCloudKitAccountStateListener> 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);
});
}
});
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)];
}
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];
}
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;
extern NSString* const OctagonAnalyticsBottledUniqueTLKsWithSharesCount;
extern NSString* const OctagonAnalyticsBottledTLKUniqueViewCount;
-@class CKKSKeychainView;
-
@protocol CKKSAnalyticsFailableEvent <NSObject>
@end
typedef NSString<CKKSAnalyticsFailableEvent> CKKSAnalyticsFailableEvent;
+ (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;
- (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
NSString* const OctagonAnalyticsTrustState = @"OATrust";
NSString* const OctagonAnalyticsAttemptedJoin = @"OAAttemptedJoin";
+NSString* const OctagonAnalyticsUserControllableViewsSyncing = @"OAUserViewsSyncing";
NSString* const OctagonAnalyticsLastHealthCheck = @"OAHealthCheck";
NSString* const OctagonAnalyticsSOSStatus = @"OASOSStatus";
NSString* const OctagonAnalyticsDateOfLastPreflightPreapprovedJoin = @"OALastPPJ";
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
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;
[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;
[eventAttributes setValuesForKeysWithDictionary:@{
CKKSAnalyticsAttributeRecoverableError : @(NO),
- CKKSAnalyticsAttributeZoneName : view.zoneName,
+ CKKSAnalyticsAttributeZoneName : zoneName,
CKKSAnalyticsAttributeErrorDomain : error.domain,
CKKSAnalyticsAttributeErrorCode : @(error.code)
}];
[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;
{
[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
--- /dev/null
+
+#import <Foundation/Foundation.h>
+
+#if OCTAGON
+
+#import "keychain/ckks/CKKSKeychainView.h"
+#import "keychain/ckks/CKKSOperationDependencies.h"
+#import "keychain/ot/OctagonStateMachineHelpers.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface CKKSCheckKeyHierarchyOperation : CKKSResultOperation <OctagonStateTransitionOperationProtocol>
+@property CKKSOperationDependencies* deps;
+
+- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies
+ intendedState:(OctagonState*)intendedState
+ errorState:(OctagonState*)errorState;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // OCTAGON
--- /dev/null
+
+#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<CKKSPeerProviderState*>* 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<id<CKKSPeer>>* 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
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";
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";
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";
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
reply:(void (^)(NSArray<NSDictionary*>* _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;
#import "keychain/ckks/CKKSControl.h"
#import "keychain/ckks/CKKSControlProtocol.h"
#import "keychain/ckks/CKKSControlServer.h"
-
-#include <security_utilities/debugging.h>
+#import "utilities/debugging.h"
@interface CKKSControl ()
@property (readwrite,assign) BOOL synchronous;
return self;
}
+- (void)dealloc {
+ [self.connection invalidate];
+}
+
- (id<CKKSControlProtocol>)objectProxyWithErrorHandler:(void(^)(NSError * _Nonnull error))failureHandler
{
if (self.synchronous) {
- (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){
}
- (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){
}];
}
-
+- (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){
+ 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){
}];
}
- (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){
}];
}
- (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){
}];
}
- (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){
bool tlkMissing = false;
bool waitForUnlock = false;
bool waitForOctagon = false;
+ bool noAccount = false;
CKKSKnownBadState response = CKKSKnownStatePossiblyGood;
}
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);
}];
@protocol CKKSControlProtocol <NSObject>
- (void)performanceCounters:(void(^)(NSDictionary <NSString *, NSNumber *> *))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
#if OCTAGON
#import <CloudKit/CloudKit.h>
#import <CloudKit/CloudKit_Private.h>
-#import <utilities/debugging.h>
+#import <objc/runtime.h>
+#import "utilities/debugging.h"
#include <dlfcn.h>
+#import <Security/SecXPCHelper.h>
// Weak-link CloudKit, until we can get ckksctl out of base system
static void *cloudKit = NULL;
__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
#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;
}
--- /dev/null
+
+#import <Foundation/Foundation.h>
+
+#if OCTAGON
+
+#import "keychain/ckks/CKKSKeychainView.h"
+#import "keychain/ckks/CKKSOperationDependencies.h"
+#import "keychain/ot/OctagonStateMachineHelpers.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface CKKSCreateCKZoneOperation : CKKSGroupOperation <OctagonStateTransitionOperationProtocol>
+@property CKKSOperationDependencies* deps;
+
+- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies
+ intendedState:(OctagonState*)intendedState
+ errorState:(OctagonState*)errorState;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // OCTAGON
--- /dev/null
+#if OCTAGON
+
+#import <CloudKit/CloudKit.h>
+#import <CloudKit/CloudKit_Private.h>
+
+#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
_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;
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);
}
}
--- /dev/null
+#import <Foundation/Foundation.h>
+
+#if OCTAGON
+
+#import "keychain/ckks/CKKSKeychainView.h"
+#import "keychain/ckks/CKKSOperationDependencies.h"
+#import "keychain/ot/OctagonStateMachineHelpers.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface CKKSDeleteCKZoneOperation : CKKSGroupOperation <OctagonStateTransitionOperationProtocol>
+@property CKKSOperationDependencies* deps;
+
+- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies
+ intendedState:(OctagonState*)intendedState
+ errorState:(OctagonState*)errorState;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // OCTAGON
--- /dev/null
+
+
+#if OCTAGON
+
+#import <CloudKit/CloudKit.h>
+#import <CloudKit/CloudKit_Private.h>
+
+#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
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;
}
}
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];;
}
}
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;
}
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;
}
// 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];
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;
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];
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];
};
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;
}
// 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;
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];
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"];
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];
{
id<CKKSChangeFetcherClient> 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;
}
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
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
@interface CKKSFixupLocalReloadOperation : CKKSGroupOperation
@property (weak) CKKSKeychainView* ckks;
- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)keychainView
+ fixupNumber:(CKKSFixup)fixupNumber
ckoperationGroup:(CKOperationGroup*)ckoperationGroup;
@end
#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;
if(lastfixup < CKKSFixupLocalReload) {
CKKSResultOperation* localSync = [[CKKSFixupLocalReloadOperation alloc] initWithCKKSKeychainView:keychainView
+ fixupNumber:CKKSFixupLocalReload
ckoperationGroup:fixupCKGroup];
[localSync addNullableSuccessDependency:previousOp];
[fixups runBeforeGroupFinished:localSync];
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;
}
return;
}
- [ckks dispatchSyncWithAccountKeys:^bool {
+ [ckks dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{
NSError* error = nil;
NSArray<CKKSCurrentItemPointer*>* cips = [CKKSCurrentItemPointer allInZone: ckks.zoneID error:&error];
if(error) {
ckkserror("ckksfixup", ckks, "Couldn't fetch current item pointers: %@", error);
- return false;
+ return CKKSDatabaseTransactionRollback;
}
NSMutableSet<CKRecordID*>* recordIDs = [NSMutableSet set];
WEAKIFY(self);
NSBlockOperation* doneOp = [NSBlockOperation named:@"fetch-records-operation-complete" withBlock:^{}];
- id<CKKSFetchRecordsOperation> fetch = [[ckks.cloudKitClassDependencies.fetchRecordsOperationClass alloc] initWithRecordIDs: [recordIDs allObjects]];
+ CKDatabaseOperation<CKKSFetchRecordsOperation>* fetch = [[ckks.cloudKitClassDependencies.fetchRecordsOperationClass alloc] initWithRecordIDs: [recordIDs allObjects]];
fetch.fetchRecordsCompletionBlock = ^(NSDictionary<CKRecordID *,CKRecord *> * _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);
}
[self runBeforeGroupFinished:doneOp];
- return true;
+ return CKKSDatabaseTransactionCommit;
}];
};
[ckks.database addOperation: fetch];
[self dependOnBeforeGroupFinished:fetch];
[self dependOnBeforeGroupFinished:doneOp];
- return true;
+ return CKKSDatabaseTransactionCommit;
}];
}
@end
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<CKKSQueryOperation> fetch = [[ckks.cloudKitClassDependencies.queryOperationClass alloc] initWithQuery:query];
+ CKDatabaseOperation<CKKSQueryOperation>* 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;
}];
};
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);
} else {
ckksnotice("ckksfixup", strongCKKS, "Updated zone fixup state to CKKSFixupFetchTLKShares");
}
- return true;
+ return CKKSDatabaseTransactionCommit;
}];
[self runBeforeGroupFinished:doneOp];
};
[self dependOnBeforeGroupFinished:fetch];
[self dependOnBeforeGroupFinished:doneOp];
- return true;
+ return CKKSDatabaseTransactionCommit;
}];
}
@end
@interface CKKSFixupLocalReloadOperation ()
@property CKOperationGroup* group;
+@property CKKSFixup fixupNumber;
@end
// In <rdar://problem/35540228> 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 <rdar://problem/60650208> 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:@"<CKKSFixup:LocalReload (%@)>", self.ckks];
+ return [NSString stringWithFormat:@"<CKKSFixup:LocalReload (%d)(%@)>", (int)self.fixupNumber, self.ckks];
}
- (void)groupStart {
CKKSKeychainView* ckks = self.ckks;
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];
}
// This operation simply loads all CDSEs, remakes them from their CKRecord, and resaves them
- [ckks dispatchSync:^bool {
+ [ckks dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{
NSError* error = nil;
NSArray<CKKSDeviceStateEntry*>* cdses = [CKKSDeviceStateEntry allInZone:ckks.zoneID
error:&error];
if(error) {
ckkserror("ckksfixup", ckks, "Unable to fetch all CDSEs: %@", error);
self.error = error;
- return false;
+ return CKKSDatabaseTransactionRollback;
}
for(CKKSDeviceStateEntry* cdse in cdses) {
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);
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;
}];
}
#import "CKKSGroupOperation.h"
#import "keychain/ot/ObjCImprovements.h"
-#include <utilities/debugging.h>
+#import "keychain/ckks/CKKS.h"
@interface CKKSGroupOperation()
@property bool fillInError;
_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;
}
_finishOperation = [NSBlockOperation blockOperationWithBlock:^{
STRONGIFY(self);
if(!self) {
- secerror("ckks: received callback for released object");
+ ckkserror_global("ckks", "received callback for released object");
return;
}
}
- (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];
+
+ [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:@", "];
+ }
+ }
- // 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];
+ 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 {
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;
}
#import <Foundation/Foundation.h>
#import "keychain/ckks/CKKSGroupOperation.h"
+#import "keychain/ckks/CKKSOperationDependencies.h"
+#import "keychain/ot/OctagonStateMachineHelpers.h"
#if OCTAGON
@class CKKSKeychainView;
-@interface CKKSHealKeyHierarchyOperation : CKKSGroupOperation
+@interface CKKSHealKeyHierarchyOperation : CKKSGroupOperation <OctagonStateTransitionOperationProtocol>
+@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
#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"
@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;
}
return;
}
+ NSArray<CKKSPeerProviderState*>* 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;
// 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;
}
}
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.
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;
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;
}
// We've selected a new TLK. Compute any TLKShares that should go along with it.
- NSSet<CKKSTLKShareRecord*>* tlkShares = [ckks _onqueueCreateMissingKeyShares:keyset.tlk
- error:&error];
+ NSSet<CKKSTLKShareRecord*>* 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) {
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);
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
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
}
// 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;
}];
}
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;
}
}
#import <Foundation/Foundation.h>
#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 <OctagonStateTransitionOperationProtocol>
+@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<CKKSTLKShareRecord*>* _Nullable)createMissingKeyShares:(CKKSCurrentKeySet*)keyset
+ trustStates:(NSArray<CKKSPeerProviderState*>*)trustStates
+ error:(NSError* __autoreleasing*)errore;
@end
NS_ASSUME_NONNULL_END
@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;
}
WEAKIFY(self);
- CKKSKeychainView* ckks = self.ckks;
- if(!ckks) {
- ckkserror("ckksshare", ckks, "no CKKS object");
+ if(self.cancelled) {
+ ckksnotice("ckksshare", self.deps.zoneID, "CKKSHealTLKSharesOperation cancelled, quitting");
return;
}
- if(self.cancelled) {
- ckksnotice("ckksshare", ckks, "CKKSHealTLKSharesOperation cancelled, quitting");
+ NSArray<CKKSPeerProviderState*>* trustStates = [self.deps currentTrustStates];
+
+ NSError* error = nil;
+ __block CKKSCurrentKeySet* keyset = nil;
+
+ [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);
}
- [ckks dispatchSyncWithAccountKeys: ^bool{
- if(self.cancelled) {
- ckksnotice("ckksshare", ckks, "CKKSHealTLKSharesOperation cancelled, quitting");
- return false;
+ [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<CKKSTLKShareRecord*>* 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];
- NSError* error = nil;
+ // 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<CKRecord *>* recordsToSave = [[NSMutableArray alloc] init];
+ NSMutableArray<CKRecordID *>* recordIDsToDelete = [[NSMutableArray alloc] init];
+ NSMutableDictionary<CKRecordID*, CKRecord*>* 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;
- CKKSCurrentKeySet* keyset = [CKKSCurrentKeySet loadForZone:ckks.zoneID];
+ modifyRecordsOp.group = self.deps.ckoperationGroup;
+ ckksnotice("ckksshare", self.deps.zoneID, "Operation group is %@", self.deps.ckoperationGroup);
- 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;
+ 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 {
- ckksnotice("ckksshare", ckks, "Key set is %@", keyset);
+ ckkserror("ckksshare", self.deps.zoneID, "error on row: %@ %@", record.recordID, error);
}
+ };
+
+ modifyRecordsOp.modifyRecordsCompletionBlock = ^(NSArray<CKRecord *> *savedRecords, NSArray<CKRecordID *> *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);
+ }
+ }
- [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];
+ // Successfully sharing TLKs means we're now in ready!
+ self.nextState = SecCKKSZoneKeyStateBecomeReady;
} else {
- // TODO go to waitfortlk
- ckkserror("ckksshare", ckks, "couldn't load current tlk from keychain: %@", error);
- [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateUnhealthy withError:nil];
+ 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 true;
- }
+ return CKKSDatabaseTransactionCommit;
+ }];
- NSSet<CKKSTLKShareRecord*>* newShares = [ckks _onqueueCreateMissingKeyShares:keyset.tlk
- error:&error];
- if(error) {
- ckkserror("ckksshare", ckks, "Unable to create shares: %@", error);
- [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateUnhealthy withError:nil];
- return false;
- }
+ // Notify that we're done
+ [self.operationQueue addOperation: self.cloudkitModifyOperationFinished];
+ };
+
+ [self.ckks.database addOperation:modifyRecordsOp];
+}
- if(newShares.count == 0u) {
- ckksnotice("ckksshare", ckks, "Don't believe we need to change any TLKShares, stopping");
- [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateReady withError:nil];
- return true;
+- (void)cancel {
+ [self.cloudkitModifyOperationFinished cancel];
+ [super cancel];
+}
+
++ (BOOL)areNewSharesSufficient:(CKKSCurrentKeySet*)keyset
+ trustStates:(NSArray<CKKSPeerProviderState*>*)trustStates
+ error:(NSError* __autoreleasing*)error
+{
+ for(CKKSPeerProviderState* trustState in trustStates) {
+ NSError* localError = nil;
+ NSSet<id<CKKSPeer>>* 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.
+ }
}
- // 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;
+ if(peersMissingShares.count > 0) {
+ ckksnotice("ckksshare", keyset.tlk, "New share set is missing shares for peers: %@", peersMissingShares);
+ return NO;
}
+ }
- // Fire up our CloudKit operation!
+ return YES;
+}
- NSMutableArray<CKRecord *>* recordsToSave = [[NSMutableArray alloc] init];
- NSMutableArray<CKRecordID *>* recordIDsToDelete = [[NSMutableArray alloc] init];
- NSMutableDictionary<CKRecordID*, CKRecord*>* attemptedRecords = [[NSMutableDictionary alloc] init];
- for(CKKSTLKShareRecord* share in newShares) {
- CKRecord* record = [share CKRecordWithZoneID:ckks.zoneID];
- [recordsToSave addObject: record];
- attemptedRecords[record.recordID] = record;
- }
++ (NSSet<CKKSTLKShareRecord*>* _Nullable)createMissingKeyShares:(CKKSCurrentKeySet*)keyset
+ trustStates:(NSArray<CKKSPeerProviderState*>*)trustStates
+ error:(NSError* __autoreleasing*)error
+{
+ NSError* localerror = nil;
+ NSSet<CKKSTLKShareRecord*>* newShares = nil;
- // 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];
+ // If any one of our trust states succeed, this function doesn't have an error
+ for(CKKSPeerProviderState* trustState in trustStates) {
+ NSError* stateError = nil;
+ NSSet<CKKSTLKShareRecord*>* newTrustShares = [self createMissingKeyShares:keyset
+ peers:trustState
+ error:&stateError];
- // 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;
+ 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;
+ }
+ }
+ }
- modifyRecordsOp.group = self.ckoperationGroup;
- ckksnotice("ckksshare", ckks, "Operation group is %@", self.ckoperationGroup);
+ // 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;
+ }
+}
- modifyRecordsOp.perRecordCompletionBlock = ^(CKRecord *record, NSError * _Nullable error) {
- STRONGIFY(self);
- CKKSKeychainView* blockCKKS = self.ckks;
++ (NSSet<CKKSTLKShareRecord*>*)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;
+ }
- // 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<CKRecord *> *savedRecords, NSArray<CKRecordID *> *deletedRecordIDs, NSError *error) {
- STRONGIFY(self);
- CKKSKeychainView* strongCKKS = self.ckks;
- if(!self) {
- secerror("ckks: received callback for released object");
- return;
- }
+ NSSet<id<CKKSPeer>>* 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;
+ }
- [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);
- }
- }
+ NSMutableSet<CKKSTLKShareRecord*>* newShares = [NSMutableSet set];
- // 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;
- }];
+ for(id<CKKSPeer> 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;
+ }
- // Notify that we're done
- [self.operationQueue addOperation: self.cloudkitModifyOperationFinished];
- };
+ // 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;
+ }
- [ckks.database addOperation: modifyRecordsOp];
- return true;
- }];
-}
+ [newShares addObject: newShare];
+ }
-- (void)cancel {
- [self.cloudkitModifyOperationFinished cancel];
- [super cancel];
+ return newShares;
}
@end;
+ (instancetype _Nullable)tryFromDatabase:(NSString*)uuid zoneID:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error;
+ (NSArray<CKKSIncomingQueueEntry*>* _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;
+ (NSArray<CKKSIncomingQueueEntry*>*)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"] = [CKKSSQLWhereValue op:CKKSSQLWhereComparatorGreaterThan value:uuid];
}
#import <Foundation/Foundation.h>
#import "keychain/ckks/CKKSGroupOperation.h"
#if OCTAGON
+
+#import "keychain/ckks/CKKSOperationDependencies.h"
+#import "keychain/ot/OctagonStateMachineHelpers.h"
+
NS_ASSUME_NONNULL_BEGIN
@class CKKSKeychainView;
@class CKKSItem;
-@interface CKKSIncomingQueueOperation : CKKSResultOperation
+@interface CKKSIncomingQueueOperation : CKKSResultOperation <OctagonStateTransitionOperationProtocol>
+@property CKKSOperationDependencies* deps;
@property (weak) CKKSKeychainView* ckks;
// 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
+ ckks:(CKKSKeychainView*)ckks
+ 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;
/*
- * Copyright (c) 2016 Apple Inc. All Rights Reserved.
+ * Copyright (c) 2016-2020 Apple Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* @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/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 <Security/SecItemPriv.h>
-#include <utilities/SecADWrapper.h>
#import <utilities/SecCoreAnalytics.h>
#if OCTAGON
@property bool newOutgoingEntries;
@property bool pendingClassAEntries;
@property bool missingKey;
+
+@property NSMutableSet<NSString*>* 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
+ ckks:(CKKSKeychainView*)ckks
+ intending:(OctagonState*)intending
+ errorState:(OctagonState*)errorState
+ errorOnClassAFailure:(bool)errorOnClassAFailure
+ handleMismatchedViewItems:(bool)handleMismatchedViewItems
+{
if(self = [super init]) {
+ _deps = dependencies;
_ckks = ckks;
+ _intendedState = intending;
+ _nextState = errorState;
+
// Can't process unless we have a reasonable key hierarchy.
if(ckks.keyStateReadyDependency) {
[self addDependency: ckks.keyStateReadyDependency];
_errorOnClassAFailure = errorOnClassAFailure;
_pendingClassAEntries = false;
- [self linearDependencies:ckks.incomingQueueOperations];
-
- 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;
- }
+ _handleMismatchedViewItems = handleMismatchedViewItems;
- [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";
+ _viewsToScan = [NSMutableSet set];
- [ckks scheduleOperation:updateManifestOperation];
- [self addSuccessDependency:updateManifestOperation];
- }
+ [self linearDependencies:ckks.incomingQueueOperations];
}
return self;
}
-- (bool)processNewCurrentItemPointers:(NSArray<CKKSCurrentItemPointer*>*)queueEntries withManifest:(CKKSManifest*)manifest egoManifest:(CKKSEgoManifest*)egoManifest
+- (bool)processNewCurrentItemPointers:(NSArray<CKKSCurrentItemPointer*>*)queueEntries
{
- 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", self.deps.zoneID, "Saving new current item pointer: %@", p);
if(error) {
- ckkserror("ckksincoming", ckks, "Error saving new current item pointer: %@ %@", error, p);
+ ckkserror("ckksincoming", self.deps.zoneID, "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];
+ [self.deps.notifyViewChangedScheduler trigger];
}
return (error == nil);
}
-- (bool)processQueueEntries:(NSArray<CKKSIncomingQueueEntry*>*)queueEntries withManifest:(CKKSManifest*)manifest egoManifest:(CKKSEgoManifest*)egoManifest
+- (bool)processQueueEntries:(NSArray<CKKSIncomingQueueEntry*>*)queueEntries
{
CKKSKeychainView* ckks = self.ckks;
+ dispatch_assert_queue(ckks.queue);
NSMutableArray* newOrChangedRecords = [[NSMutableArray alloc] init];
NSMutableArray* deletedRecordIDs = [[NSMutableArray 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", self.deps.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
NSDictionary* attributes = [CKKSIncomingQueueOperation decryptCKKSItemToAttributes:iqe.item 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", self.deps.zoneID, "Keychain is locked; can't decrypt IQE %@", iqe);
+ CKKSKey* key = [CKKSKey tryFromDatabase:iqe.item.parentKeyUUID zoneID:self.deps.zoneID error:&localerror];
if(localerror || ([key.keyclass isEqualToString:SecCKKSKeyClassA] && self.errorOnClassAFailure)) {
self.error = error;
}
}
} 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", self.deps.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", self.deps.zoneID, "Couldn't decrypt IQE %@ for some reason: %@", iqe, error);
self.error = error;
}
self.errorItemsProcessed += 1;
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", self.deps.zoneID, "Synced item seems wrong: %@", self.error);
self.errorItemsProcessed += 1;
continue;
}
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", self.deps.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", self.deps.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(![self.deps.zoneID.zoneName isEqualToString:intendedView]) {
+ if(self.handleMismatchedViewItems) {
+ [self _onqueueHandleMismatchedViewItem:iqe
+ secDbClass:classP
+ attributes:attributes
+ intendedView:intendedView];
+ } else {
+ ckksnotice("ckksincoming", ckks, "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", ckks, "Couldn't save mismatched IQE to database: %@", error);
self.errorItemsProcessed += 1;
- return false;
+ self.error = error;
}
+
+ [ckks receivedItemForWrongView];
}
+ continue;
+ }
+
+ if([iqe.action isEqualToString: SecCKKSActionAdd] || [iqe.action isEqualToString: SecCKKSActionModify]) {
+ [self _onqueueHandleIQEChange:iqe
+ attributes:attributes
+ class:classP
+ sortedForThisView:YES];
+ [newOrChangedRecords addObject:[iqe.item CKRecordWithZoneID:self.deps.zoneID]];
+
+ } else if ([iqe.action isEqualToString: SecCKKSActionDelete]) {
+ [self _onqueueHandleIQEDelete: iqe class:classP];
+ [deletedRecordIDs addObject:[[CKRecordID alloc] initWithRecordName:iqe.uuid zoneID:self.deps.zoneID]];
}
}
}
if(newOrChangedRecords.count > 0 || deletedRecordIDs > 0) {
// Schedule a view change notification
- [ckks.notifyViewChangedScheduler trigger];
+ [self.deps.notifyViewChangedScheduler trigger];
}
if(self.missingKey) {
- [ckks.pokeKeyStateMachineScheduler trigger];
+ // TODO: will be removed when the IncomingQueueOperation is part of the state machine
+ [ckks.stateMachine _onqueuePokeStateMachine];
+ self.nextState = SecCKKSZoneKeyStateUnhealthy;
}
- if ([CKKSManifest shouldSyncManifests]) {
- [egoManifest updateWithNewOrChangedRecords:newOrChangedRecords deletedRecordIDs:deletedRecordIDs];
- }
return true;
}
+- (void)_onqueueHandleMismatchedViewItem:(CKKSIncomingQueueEntry*)iqe
+ secDbClass:(const SecDbClass*)secDbClass
+ attributes:(NSDictionary*)attributes
+ intendedView:(NSString* _Nullable)intendedView
+{
+ ckksnotice("ckksincoming", self.deps.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", self.deps.zoneID, "Unable to create SecDbItemRef from IQE: %@", cferror);
+ return;
+ }
+
+ [self _onqueueHandleIQEChange:iqe item:item sortedForThisView:NO];
+ [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", self.deps.zoneID, "Unable to load CKKSMirrorEntry from database* %@", loadError);
+ return;
+ }
+
+ if(ckme) {
+ ckksnotice("ckksincoming", self.deps.zoneID, "Other view (%@) already knows about this item, dropping incoming queue entry: %@", intendedView, ckme);
+ NSError* saveError = nil;
+ [iqe deleteFromDatabase:&saveError];
+ if(saveError) {
+ ckkserror("ckksincoming", self.deps.zoneID, "Unable to delete IQE: %@", saveError);
+ }
+
+ } else {
+ ckksnotice("ckksincoming", self.deps.zoneID, "Other view (%@) does not know about this item; processing delete for %@", intendedView, iqe);
+ [self _onqueueHandleIQEDelete:iqe class:secDbClass];
+ }
+
+ } else {
+ // We don't recognize this action. Do nothing.
+ }
+}
+
+ (NSDictionary* _Nullable)decryptCKKSItemToAttributes:(CKKSItem*)item error:(NSError**)error
{
NSMutableDictionary* attributes = [[CKKSItemEncrypter decryptItemToDictionary:item error:error] mutableCopy];
return true;
}
-- (void) main {
- // Synchronous, on some thread. Get back on the CKKS queue for thread-safety.
+- (void)main
+{
CKKSKeychainView* ckks = self.ckks;
- if(!ckks) {
- ckkserror("ckksincoming", ckks, "no CKKS object");
+
+ if(!ckks.itemSyncingEnabled) {
+ ckkserror("ckksincoming", self.deps.zoneID, "Item syncing for this view is disabled");
+ self.nextState = self.intendedState;
return;
}
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];
+ [logger logSuccessForEvent:CKKSEventProcessIncomingQueueClassC zoneName:self.deps.zoneID.zoneName];
+
if (!self.pendingClassAEntries) {
- [logger logSuccessForEvent:CKKSEventProcessIncomingQueueClassA inView:ckks];
+ [logger logSuccessForEvent:CKKSEventProcessIncomingQueueClassA zoneName:self.deps.zoneID.zoneName];
}
} else {
[logger logRecoverableError:self.error
forEvent:self.errorOnClassAFailure ? CKKSEventProcessIncomingQueueClassA : CKKSEventProcessIncomingQueueClassC
- inView:ckks
+ zoneName:self.deps.zoneID.zoneName
withAttributes:NULL];
}
};
- __block bool errored = false;
- [ckks dispatchSync: ^bool{
- if(self.cancelled) {
- ckksnotice("ckksincoming", ckks, "CKKSIncomingQueueOperation cancelled, quitting");
- return false;
- }
- ckks.lastIncomingQueueOperation = self;
+ ckksnotice("ckksincoming", self.deps.zoneID, "Processing incoming queue");
- ckksnotice("ckksincoming", ckks, "Processing incoming queue");
+ // 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.
- 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");
- }
- }
-
- bool ok = true; // Should commit transaction?
- __block NSError* error = nil;
+ BOOL success = [self loadAndProcessEntriesWithActionFilter:SecCKKSActionDelete];
+ if(!success) {
+ ckksnotice("ckksincoming", self.deps.zoneID, "Early-exiting from IncomingQueueOperation (after processing deletes): %@", self.error);
+ return;
+ }
- 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;
- }
+ success = [self loadAndProcessEntriesWithActionFilter:nil];
+ if(!success) {
+ ckksnotice("ckksincoming", self.deps.zoneID, "Early-exiting from IncomingQueueOperation (after processing all incoming entries): %@", self.error);
+ return;
+ }
- // take any existing unauthenticated entries and put them back in the new state
- NSArray<CKKSIncomingQueueEntry*>* 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;
- }
+ ckksnotice("ckksincoming", self.deps.zoneID, "Processed %lu items in incoming queue (%lu errors)", (unsigned long)self.successfulItemsProcessed, (unsigned long)self.errorItemsProcessed);
- 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;
- }
+ if(![self fixMismatchedViewItems]) {
+ ckksnotice("ckksincoming", ckks, "Early-exiting from IncomingQueueOperation due to failure fixing mismatched items");
+ return;
+ }
- 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;
- }
+ [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{
+ NSError* error = nil;
- lastMaxUUID = ([lastMaxUUID compare:unauthenticatedEntry.uuid] == NSOrderedDescending) ? lastMaxUUID : unauthenticatedEntry.uuid;
- }
+ NSArray<CKKSCurrentItemPointer*>* newCIPs = [CKKSCurrentItemPointer remoteItemPointers:self.deps.zoneID error:&error];
+ if(error || !newCIPs) {
+ ckkserror("ckksincoming", self.deps.zoneID, "Could not load remote item pointers: %@", error);
+ } else {
+ if (![self processNewCurrentItemPointers:newCIPs]) {
+ return CKKSDatabaseTransactionRollback;
}
+ ckksnotice("ckksincoming", self.deps.zoneID, "Processed %lu items in CIP queue", (unsigned long)newCIPs.count);
}
- errored = !ok;
- return ok;
+
+ return CKKSDatabaseTransactionCommit;
}];
- if(errored) {
- ckksnotice("ckksincoming", ckks, "Early-exiting from IncomingQueueOperation");
- return;
+ if(self.newOutgoingEntries) {
+ //[self.deps.flagHandler handleFlag:CKKSFlagProcessOutgoingQueue];
+ [ckks processOutgoingQueue:[CKOperationGroup CKKSGroupWithName:@"incoming-queue-response"]];
+ }
+
+ if(self.pendingClassAEntries) {
+ [ckks processIncomingQueueAfterNextUnlock];
+ //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", ckks, "Requesting scan for %@ (%@)", view, viewName);
+ [view scanLocalItems:@"policy-mismatch"];
}
+ self.nextState = self.intendedState;
+}
+
+- (BOOL)loadAndProcessEntriesWithActionFilter:(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<CKKSDatabaseProviderProtocol> databaseProvider = self.deps.databaseProvider;
+
while(lastCount == SecCKKSIncomingQueueItemsAtOnce) {
- [ckks dispatchSync: ^bool{
+ [databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{
NSArray<CKKSIncomingQueueEntry*> * queueEntries = nil;
if(self.cancelled) {
- ckksnotice("ckksincoming", ckks, "CKKSIncomingQueueOperation cancelled, quitting");
+ ckksnotice("ckksincoming", self.deps.zoneID, "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:self.deps.zoneID
+ error:&error];
if(error != nil) {
- ckkserror("ckksincoming", ckks, "Error fetching incoming queue records: %@", error);
+ ckkserror("ckksincoming", self.deps.zoneID, "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", self.deps.zoneID, "Nothing in incoming queue to process (filter: %@)", actionFilter);
+ return CKKSDatabaseTransactionCommit;
}
- [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventOutgoingQueue zone:ckks.zoneName count:[queueEntries count]];
+ [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventIncommingQueue zone:self.deps.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 processQueueEntries:queueEntries]) {
+ ckksnotice("ckksincoming", self.deps.zoneID, "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", self.deps.zoneID, "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
+{
+ if(!self.handleMismatchedViewItems) {
+ return YES;
+ }
- [ckks dispatchSync: ^bool{
- NSError* error = nil;
+ ckksnotice("ckksincoming", self.deps.zoneID, "Handling policy-mismatched items");
+ __block NSUInteger lastCount = SecCKKSIncomingQueueItemsAtOnce;
+ __block NSString* lastMaxUUID = nil;
+ __block BOOL errored = NO;
- NSArray<CKKSCurrentItemPointer*>* 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<CKKSDatabaseProviderProtocol> databaseProvider = self.deps.databaseProvider;
+
+ while(lastCount == SecCKKSIncomingQueueItemsAtOnce) {
+ [databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{
+ NSError* error = nil;
+ NSArray<CKKSIncomingQueueEntry*>* queueEntries = [CKKSIncomingQueueEntry fetch:SecCKKSIncomingQueueItemsAtOnce
+ startingAtUUID:lastMaxUUID
+ state:SecCKKSStateMismatchedView
+ action:nil
+ zoneID:self.deps.zoneID
+ error:&error];
+ if(error) {
+ ckksnotice("ckksincoming", self.deps.zoneID, "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", self.deps.zoneID, "No mismatched view items");
+ return CKKSDatabaseTransactionCommit;
+ }
- return true;
- }];
-}
+ ckksnotice("ckksincoming", self.deps.zoneID, "Inspecting %lu mismatched items", (unsigned long)queueEntries.count);
-- (void)_onqueueHandleIQEChange: (CKKSIncomingQueueEntry*) iqe attributes:(NSDictionary*)attributes class:(const SecDbClass *)classP {
- CKKSKeychainView* ckks = self.ckks;
- if(!ckks) {
- ckkserror("ckksincoming", ckks, "no CKKS object");
- return;
+ if (![self processQueueEntries:queueEntries]) {
+ ckksnotice("ckksincoming", self.deps.zoneID, "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;
+ }];
}
- dispatch_assert_queue(ckks.queue);
+ return !errored;
+}
+
+- (void)_onqueueHandleIQEChange:(CKKSIncomingQueueEntry*)iqe
+ attributes:(NSDictionary*)attributes
+ class:(const SecDbClass *)classP
+ sortedForThisView:(BOOL)sortedForThisView
+{
+ __block CFErrorRef cferror = NULL;
+ SecDbItemRef item = SecDbItemCreateWithAttributes(NULL, classP, (__bridge CFDictionaryRef) attributes, KEYBAG_DEVICE, &cferror);
+ if(!item || cferror) {
+ ckkserror("ckksincoming", self.deps.zoneID, "Unable to make SecDbItemRef out of attributes: %@", cferror);
+ return;
+ }
+ CFReleaseNull(cferror);
+
+ [self _onqueueHandleIQEChange:iqe
+ item:item
+ sortedForThisView:sortedForThisView];
+
+ CFReleaseNull(item);
+}
+
+- (void)_onqueueHandleIQEChange:(CKKSIncomingQueueEntry*)iqe
+ item:(SecDbItemRef)item
+ sortedForThisView:(BOOL)sortedForThisView
+{
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", self.deps.zoneID, "Rejecting a tombstone item addition from CKKS(%@): %@", iqe.uuid, item);
+
+ NSError* error = nil;
+ CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry withItem:item action:SecCKKSActionDelete zoneID:self.deps.zoneID error:&error];
+ [oqe saveToDatabase:&error];
+
+ if(error) {
+ ckkserror("ckksincoming", self.deps.zoneID, "Unable to save new deletion OQE: %@", error);
+ } else {
+ [iqe deleteFromDatabase: &error];
+ if(error) {
+ ckkserror("ckksincoming", self.deps.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", self.deps.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", self.deps.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:self.deps.zoneID
+ error:&ckmeError];
+
+ if(ckmeError) {
+ ckksnotice("ckksincoming", self.deps.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", self.deps.zoneID, "Primary key conflict; dropping CK item %@", item);
+ oqe = [CKKSOutgoingQueueEntry withItem:item action:SecCKKSActionDelete zoneID:self.deps.zoneID 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", self.deps.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:self.deps.zoneID error:&error];
[oqe saveToDatabase: &error];
self.newOutgoingEntries = true;
}
return replaceok;
});
- CFReleaseNull(item);
-
if(cferror) {
- ckkserror("ckksincoming", ckks, "couldn't process item from IncomingQueue: %@", cferror);
+ ckkserror("ckksincoming", self.deps.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", self.deps.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", self.deps.zoneID, "Couldn't handle IQE, but why?: %@", error);
self.error = error;
return;
}
if(ok) {
- ckksinfo("ckksincoming", ckks, "Correctly processed an IQE; deleting");
+ ckksinfo("ckksincoming", self.deps.zoneID, "Correctly processed an IQE; deleting");
[iqe deleteFromDatabase: &error];
if(error) {
- ckkserror("ckksincoming", ckks, "couldn't delete CKKSIncomingQueueEntry: %@", error);
+ ckkserror("ckksincoming", self.deps.zoneID, "couldn't delete CKKSIncomingQueueEntry: %@", error);
self.error = error;
self.errorItemsProcessed += 1;
} else {
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", self.deps.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", self.deps.zoneID, "Couldn't save errored IQE to database: %@", error);
self.error = error;
}
}
- (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);
-
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*) 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", self.deps.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", self.deps.zoneID, "couldn't create query: %@", cferror);
SecTranslateError(&error, cferror);
self.error = error;
return;
if(cferror) {
if(CFErrorGetCode(cferror) == errSecItemNotFound) {
- ckkserror("ckksincoming", ckks, "couldn't delete item (as it's already gone); this is okay: %@", cferror);
+ ckkserror("ckksincoming", self.deps.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", self.deps.zoneID, "couldn't delete item: %@", cferror);
SecTranslateError(&error, cferror);
self.error = error;
query_destroy(q, NULL);
ok = query_notify_and_destroy(q, ok, &cferror);
if(cferror) {
- ckkserror("ckksincoming", ckks, "couldn't delete query: %@", cferror);
+ ckkserror("ckksincoming", self.deps.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", self.deps.zoneID, "Correctly processed an IQE; deleting");
[iqe deleteFromDatabase: &error];
if(error) {
- ckkserror("ckksincoming", ckks, "couldn't delete CKKSIncomingQueueEntry: %@", error);
+ ckkserror("ckksincoming", self.deps.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", self.deps.zoneID, "IQE not correctly processed, but why? %@ %@", error, cferror);
self.error = error;
self.errorItemsProcessed += 1;
}
_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];
// 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;
}
// 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;
}
if(olditem) {
NSMutableDictionary* oldDictionary = [[CKKSItemEncrypter decryptItemToDictionary: olditem 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;
}
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;
}
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;
}
NS_ASSUME_NONNULL_BEGIN
+@class CKKSPeerProviderState;
+
@interface CKKSKey : CKKSCKRecordHolder
@property CKKSKeychainBackedKey* keycore;
@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;
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<CKKSPeerProviderState*>*)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;
#import "CKKSKeychainView.h"
#import "CKKSCurrentKeyPointer.h"
#import "CKKSKey.h"
+#import "keychain/ckks/CKKSPeerProvider.h"
#import "keychain/categories/NSError+UsefulConstructors.h"
#include "keychain/securityd/SecItemSchema.h"
#include <Security/SecItem.h>
@implementation CKKSKey
- (instancetype)init {
- self = [super init];
+ if ((self = [super init])) {
+ }
return self;
}
return self.keycore.uuid;
}
+- (NSString*)zoneName
+{
+ return self.keycore.zoneID.zoneName;
+}
+
- (void)setUuid:(NSString *)uuid
{
self.keycore.uuid = uuid;
// 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;
}
// 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;
return self.aessivkey;
}
+- (BOOL)unwrapViaTLKSharesTrustedBy:(NSArray<CKKSPeerProviderState*>*)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<CKKSTLKShareRecord*>* 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<CKKSPeerProviderState*>*)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];
}
}
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;
}
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;
}
}
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;
}
}
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
[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);
}
}
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;
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;
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
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);
}
}
- (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"];
- (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"];
#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 <utilities/SecDb.h>
#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"
@class CKKSAESSIVKey;
@class CKKSSynchronizeOperation;
@class CKKSRateLimiter;
-@class CKKSManifest;
-@class CKKSEgoManifest;
@class CKKSOutgoingQueueEntry;
@class CKKSZoneChangeFetcher;
@class CKKSCurrentKeySet;
-@interface CKKSKeychainView : CKKSZone <CKKSZoneUpdateReceiver,
+@interface CKKSKeychainView : NSObject <CKKSCloudKitAccountStateListener,
CKKSChangeFetcherClient,
- CKKSPeerUpdateListener>
-{
- CKKSZoneKeyState* _keyHierarchyState;
-}
+ CKKSPeerUpdateListener,
+ CKKSDatabaseProviderProtocol,
+ OctagonStateMachineEngine>
+
+@property (readonly) NSString* zoneName;
+@property CKKSAccountStatus accountStatus;
+@property (readonly) CKContainer* container;
+@property (readonly) CKDatabase* database;
+@property (weak) CKKSAccountStateTracker* accountTracker;
+@property (weak) CKKSReachabilityTracker* reachabilityTracker;
+@property (readonly) CKKSCloudKitClassDependencies* cloudKitClassDependencies;
+@property (readonly) dispatch_queue_t queue;
+
+@property (readonly) CKRecordZoneID* zoneID;
@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.
// 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<CKKSZoneKeyState*, CKKSCondition*>* keyHierarchyConditions;
+@property (readonly) NSDictionary<CKKSZoneKeyState*, CKKSCondition*>* 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;
@property CKKSOutgoingQueueOperation* lastOutgoingQueueOperation;
@property CKKSProcessReceivedKeysOperation* lastProcessReceivedKeysOperation;
@property CKKSReencryptOutgoingItemsOperation* lastReencryptOutgoingItemsOperation;
-@property CKKSScanLocalItemsOperation* lastScanLocalItemsOperation;
@property CKKSSynchronizeOperation* lastSynchronizeOperation;
@property CKKSResultOperation* lastFixupOperation;
@property NSOperation* holdLocalSynchronizeOperation;
@property CKKSResultOperation* holdFixupOperation;
+/* Used for testing */
+@property BOOL initiatedLocalScan;
+
/* 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;
-/* 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<id<CKKSPeerProvider>>* 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<CKKSPeerProviderState*>* currentTrustStates;
+@property (readonly) CKKSOperationDependencies* operationDependencies;
- (instancetype)initWithContainer:(CKContainer*)container
zoneName:(NSString*)zoneName
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<id<CKKSPeerProvider>>*)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;
+
+- (void)receivedItemForWrongView;
+
/* Synchronous operations */
- (void)handleKeychainEventDbConnection:(SecDbConnectionRef)dbconn
- (bool)outgoingQueueEmpty:(NSError* __autoreleasing*)error;
-- (CKKSResultOperation<CKKSKeySetProviderOperationProtocol>*)findKeySet;
+- (CKKSResultOperation<CKKSKeySetProviderOperationProtocol>*)findKeySet:(BOOL)refetchBeforeReturningKeySet;
- (void)receiveTLKUploadRecords:(NSArray<CKRecord*>*)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;
-
/* 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;
- (CKKSSynchronizeOperation*)resyncWithCloud;
- (CKKSLocalSynchronizeOperation*)resyncLocal;
-- (CKKSResultOperation*)fetchAndProcessCKChanges:(CKKSFetchBecause*)because;
-
- (CKKSResultOperation*)resetLocalData;
- (CKKSResultOperation*)resetCloudKitZone:(CKOperationGroup*)operationGroup;
// 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
- (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<id<CKKSPeer>>*)_onqueueFindPeers:(CKKSPeerProviderState*)trustState
- missingShare:(CKKSKey*)key
- afterUploading:(NSSet<CKKSTLKShareRecord*>* _Nullable)newShares
- error:(NSError* __autoreleasing*)error;
-
-- (BOOL)_onqueueAreNewSharesSufficient:(NSSet<CKKSTLKShareRecord*>*)newShares
- currentTLK:(CKKSKey*)key
- error:(NSError* __autoreleasing*)error;
-
-// For this key, share it to all trusted peers who don't have it yet
-- (NSSet<CKKSTLKShareRecord*>* _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<CKKSOutgoingQueueOperation*>* outgoingQueueOperations;
@property NSHashTable<CKKSScanLocalItemsOperation*>* scanLocalItemsOperations;
-@property CKKSScanLocalItemsOperation* initialScanOperation;
// Returns the current state of this view, fastStatus is the same, but as name promise, no expensive calculations
- (NSDictionary<NSString*, NSString*>*)status;
- (NSDictionary<NSString*, NSString*>*)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
#endif
#import "CKKS.h"
+#import "keychain/ckks/CKKSStates.h"
#import "OctagonAPSReceiver.h"
#import "CKKSIncomingQueueEntry.h"
#import "CKKSOutgoingQueueEntry.h"
#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"
#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"
#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"
#include "keychain/securityd/SecItemDb.h"
#include "keychain/securityd/SecItemSchema.h"
#include "keychain/securityd/SecItemServer.h"
-#include <utilities/debugging.h>
#include <Security/SecItemPriv.h>
#include "keychain/SecureObjectSync/SOSAccountTransaction.h"
-#include <utilities/SecADWrapper.h>
#include <utilities/SecPLWrappers.h>
#include <os/transaction_private.h>
+#import "keychain/trust/TrustedPeers/TPSyncingPolicy.h"
+#import <Security/SecItemInternal.h>
+
#if OCTAGON
@interface CKKSKeychainView()
-@property bool keyStateFetchRequested;
-@property bool keyStateProcessRequested;
-@property bool trustedPeersSetChanged;
-
-@property bool keyStateCloudKitDeleteRequested;
-@property NSHashTable<CKKSResultOperation*>* cloudkitDeleteZoneOperations;
-
-@property bool keyStateLocalResetRequested;
-@property NSHashTable<CKKSResultOperation*>* localResetOperations;
-
-@property bool tlkCreationRequested;
-@property NSHashTable<CKKSResultOperation<CKKSKeySetProviderOperationProtocol>*>* keysetProviderOperations;
-
-
-@property (atomic) NSString *activeTLK;
@property (readonly) Class<CKKSNotifier> notifierClass;
// Scratch space for resyncs
@property (nullable) NSMutableSet<NSString*>* resyncRecordsSeen;
+
+
+@property NSOperationQueue* operationQueue;
+@property CKKSResultOperation* accountLoggedInDependency;
+@property BOOL halted;
+
// Make these readwrite
-@property NSArray<id<CKKSPeerProvider>>* currentPeerProviders;
@property NSArray<CKKSPeerProviderState*>* currentTrustStates;
+@property NSMutableSet<CKKSFetchBecause*>* currentFetchReasons;
@end
#endif
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;
+ _zoneName = zoneName;
+ _accountTracker = accountTracker;
+ _reachabilityTracker = reachabilityTracker;
+ _cloudKitClassDependencies = cloudKitClassDependencies;
+
+ _halted = NO;
+
+ _database = [_container privateCloudDatabase];
+ _zoneID = [[CKRecordZoneID alloc] initWithZoneName:zoneName ownerName:CKCurrentUserDefaultName];
+
+ _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];
+
+
_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];
_scanLocalItemsOperations = [NSHashTable weakObjectsHashTable];
- _cloudkitDeleteZoneOperations = [NSHashTable weakObjectsHashTable];
- _localResetOperations = [NSHashTable weakObjectsHashTable];
- _keysetProviderOperations = [NSHashTable weakObjectsHashTable];
- _currentPeerProviders = @[];
_currentTrustStates = @[];
+ _currentFetchReasons = [NSMutableSet set];
+
_launch = [[CKKSLaunchSequence alloc] initWithRocketName:@"com.apple.security.ckks.launch"];
[_launch addAttribute:@"view" value:zoneName];
block:^{
STRONGIFY(self);
[self.notifierClass post:[NSString stringWithFormat:@"com.apple.security.view-change.%@", self.zoneName]];
+ [self.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
_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];
- }];
-
- // Use the keyHierarchyState setter to modify the zone key state map
- self.keyHierarchyState = SecCKKSZoneKeyStateLoggedOut;
- _keyHierarchyError = nil;
- _keyHierarchyOperationGroup = nil;
- _keyStateMachineOperation = nil;
- _keyStateFetchRequested = false;
- _keyStateProcessRequested = false;
- _tlkCreationRequested = false;
+ _stateMachine = [[OctagonStateMachine alloc] initWithName:[NSString stringWithFormat:@"ckks-%@", self.zoneName]
+ states:[NSSet setWithArray:[CKKSZoneKeyStateMap() allKeys]]
+ flags:CKKSAllStateFlags()
+ initialState:SecCKKSZoneKeyStateWaitForCloudKitAccountStatus
+ queue:self.queue
+ stateEngine:self
+ lockStateTracker:lockStateTracker];
+ [_stateMachine startOperation];
_waitingQueue = [[NSOperationQueue alloc] init];
_waitingQueue.maxConcurrentOperationCount = 5;
- _keyStateReadyDependency = [self createKeyStateReadyDependency: @"Key state has become ready for the first time." ckoperationGroup:[CKOperationGroup CKKSGroupWithName:@"initial-key-state-ready-scan"]];
-
- _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;
dependencyDescriptionCode:CKKSResultDescriptionPendingOutgoingQueueScheduling
block:^{}];
-
- 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);
-
- [self _onqueueAdvanceKeyStateMachineToState:nil withError:nil];
- return true;
- }];
- }];
+ _operationDependencies = [[CKKSOperationDependencies alloc] initWithZoneID:self.zoneID
+ zoneModifier:zoneModifier
+ ckoperationGroup:nil
+ flagHandler:_stateMachine
+ launchSequence:_launch
+ lockStateTracker:_lockStateTracker
+ reachabilityTracker:reachabilityTracker
+ peerProviders:@[]
+ databaseProvider:self
+ notifyViewChangedScheduler:_notifyViewChangedScheduler
+ savedTLKNotifier:savedTLKNotifier];
}
return self;
}
}
- (CKKSZoneKeyState*)keyHierarchyState {
- return _keyHierarchyState;
-}
-
-- (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];
- }
- }
+ return self.stateMachine.currentState;
}
-- (NSString *)lastActiveTLKUUID
+- (NSMutableDictionary<CKKSZoneKeyState*, CKKSCondition*>*)keyHierarchyConditions
{
- return self.activeTLK;
-}
-
-- (void)_onqueueResetSetup:(CKKSZoneKeyState*)newState resetMessage:(NSString*)resetMessage ckoperationGroup:(CKOperationGroup*)group {
- [super resetSetup];
-
- 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];
- }
+ return self.stateMachine.stateConditions;
}
- (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<OctagonStateTransitionOperationProtocol>*)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;
- }];
-
- CKKSResultOperation* viewInitializationOperation = [CKKSResultOperation named:@"view-initialization" withBlockTakingSelf:^(CKKSResultOperation * _Nonnull strongInternalOp) {
- STRONGIFY(self);
- if(!self) {
- ckkserror("ckks", self, "received callback for released object");
- return;
- }
-
- [self dispatchSyncWithAccountKeys: ^bool {
- ckksnotice("ckks", self, "Zone setup progress: %@ %d %@ %d %@",
- [CKKSAccountStateTracker stringFromAccountStatus:self.accountStatus],
- self.zoneCreated, self.zoneCreatedError, self.zoneSubscribed, self.zoneSubscribedError);
-
- NSError* error = nil;
- CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state: self.zoneName];
- ckse.ckzonecreated = self.zoneCreated;
- ckse.ckzonesubscribed = self.zoneSubscribed;
-
- // 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) {
-
- ckkserror("ckks", self, "zone subscription error appears to say the zone doesn't exist, fixing status: %@", self.zoneSubscribedError);
- ckse.ckzonecreated = false;
- }
- }
-
- [ckse saveToDatabase: &error];
- if(error) {
- ckkserror("ckks", self, "couldn't save zone creation status for %@: %@", self.zoneName, error);
- }
-
- 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];
- }
+ CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.zoneName];
- return true;
- }];
- }];
+ // Check if we believe we've synced this zone before.
+ if(ckse.changeToken == nil) {
+ self.operationDependencies.ckoperationGroup = [CKOperationGroup CKKSGroupWithName:@"initial-setup"];
- [viewInitializationOperation addDependency:zoneCreationOperation];
- [strongOp runBeforeGroupFinished:viewInitializationOperation];
- }];
+ ckksnotice("ckks", self, "No existing change token; going to try to match local items with CloudKit ones.");
- return initializationOp;
-}
+ // 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.
-- (void)_onqueuePerformKeyStateInitialized:(CKKSZoneStateEntry*)ckse {
- CKKSOutgoingQueueOperation* outgoingOperation = nil;
- NSOperation* initialProcess = nil;
+ [self.currentFetchReasons addObject:CKKSFetchBecauseInitialStart];
+ op.nextState = SecCKKSZoneKeyStateBeginFetch;
- // Check if we believe we've synced this zone before.
- if(ckse.changeToken == nil) {
- self.keyHierarchyOperationGroup = [CKOperationGroup CKKSGroupWithName:@"initial-setup"];
+ // Next, try to process them (replacing local entries). This will wait for the key state to be ready.
+ initialProcess = [self processIncomingQueue:true after:nil];
- ckksnotice("ckks", self, "No existing change token; going to try to match local items with CloudKit ones.");
+ // 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];
- // 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";
+ } 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;
+ }
- // Next, try to process them (replacing local entries)
- initialProcess = [self processIncomingQueue:true after:fetch];
- initialProcess.name = @"initial-process-incoming-queue";
+ // 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);
+ }
- // 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];
+ // Are there any entries waiting for reencryption? If so, set the flag.
+ error = nil;
+ NSArray<CKKSOutgoingQueueEntry*>* 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];
+ }
- } else {
- // Likely a restart of securityd!
+ self.operationDependencies.ckoperationGroup = [CKOperationGroup CKKSGroupWithName:@"restart-setup"];
- // 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);
- }
+ // 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.
- // 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];
- }
+ NSDate* now = [NSDate date];
+ NSDateComponents* offset = [[NSDateComponents alloc] init];
+ [offset setHour:-24];
+ NSDate* deadline = [[NSCalendar currentCalendar] dateByAddingComponents:offset toDate:now options:0];
- self.keyHierarchyOperationGroup = [CKOperationGroup CKKSGroupWithName:@"restart-setup"];
+ if(ckse.lastFetchTime == nil ||
+ [ckse.lastFetchTime compare: deadline] == NSOrderedAscending ||
+ ckse.moreRecordsInCloudKit) {
- if ([CKKSManifest shouldSyncManifests]) {
- self.egoManifest = [CKKSEgoManifest tryCurrentEgoManifestForZone:self.zoneName];
- }
+ op.nextState = SecCKKSZoneKeyStateBeginFetch;
- // 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.
+ } 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);
+ }
- NSDate* now = [NSDate date];
- NSDateComponents* offset = [[NSDateComponents alloc] init];
- [offset setHour:-24];
- NSDate* deadline = [[NSCalendar currentCalendar] dateByAddingComponents:offset toDate:now options:0];
+ 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;
- if(ckse.lastFetchTime == nil ||
- [ckse.lastFetchTime compare: deadline] == NSOrderedAscending ||
- ckse.moreRecordsInCloudKit) {
- initialProcess = [self fetchAndProcessCKChanges:CKKSFetchBecauseSecuritydRestart after:self.lastFixupOperation];
+ } else {
+ ckksnotice("ckkskey", self, "No existing key hierarchy for %@. Check if there's one in CloudKit...", self.zoneID.zoneName);
+ op.nextState = SecCKKSZoneKeyStateBeginFetch;
+ }
+ }
- // 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(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([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)
- */
-
- 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);
-}
+ /*
+ * 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
+ */
-- (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;
-
- [self dispatchSync: ^bool{
- [self _onqueueResetLocalData: &error];
- return true;
- }];
-
- strongOp.error = error;
- }];
- [pendingResetLocalOperation linearDependencies:self.localResetOperations];
- }
- return pendingResetLocalOperation;
- }
-}
-
-- (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;
+ 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];
}];
- [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;
- }];
+ [seemReady addNullableDependency:self.keyStateReadyDependency];
+ [seemReady addNullableDependency:outgoingOperation];
+ [seemReady addNullableDependency:initialScan];
+ [seemReady addNullableDependency:initialProcess];
+ [self scheduleOperation:seemReady];
- strongOp.error = error;
+ return CKKSDatabaseTransactionCommit;
}];
- [self scheduleOperationWithoutDependencies:pendingResetLocalOperation];
- return pendingResetLocalOperation;
- }
+ }];
}
-- (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*)resetLocalData {
+ ckksnotice("ckksreset", self, "Requesting local data reset");
-- (CKKSResultOperation*)resetCloudKitZone:(CKOperationGroup*)operationGroup {
+ 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*)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
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];
-
- [strongOp runBeforeGroupFinished:waitOp];
- }];
-
- [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];
+ NSDictionary* localResetPath = @{
+ SecCKKSZoneKeyStateInitializing: @{
+ SecCKKSZoneKeyStateInitialized: [OctagonStateTransitionPathStep success],
+ SecCKKSZoneKeyStateLoggedOut: [OctagonStateTransitionPathStep success],
+ },
+ };
+
+ // If the zone delete doesn't work, try it up to two more times
+
+ 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];
-}
-
-- (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];
+ [self.stateMachine handleFlag:CKKSFlagKeyStateProcessRequested];
}
-- (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<OctagonStateTransitionOperationProtocol>* _Nullable)_onqueueNextStateMachineTransition:(OctagonState*)currentState
+ flags:(OctagonFlags*)flags
+ pendingFlags:(id<OctagonStateOnqueuePendingFlagHandler>)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 ensureKeyStateReadyDependency:@"cloudkit-account-not-present"];
+ return [[CKKSLocalResetOperation alloc] initWithDependencies:self.operationDependencies
+ intendedState:SecCKKSZoneKeyStateLoggedOut
+ errorState:SecCKKSZoneKeyStateError];
+ }
- [self _onqueueHandleKeyStateNonTransientDependency:nil];
- self.launch = nil;
- return;
+ if([flags _onqueueContains:CKKSFlagCloudKitZoneMissing]) {
+ [flags _onqueueRemoveFlag:CKKSFlagCloudKitZoneMissing];
+
+ [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];
}
- [self.launch addEvent:state];
+ if([flags _onqueueContains:CKKSFlagChangeTokenExpired]) {
+ [flags _onqueueRemoveFlag:CKKSFlagChangeTokenExpired];
- // Resetting back to 'initialized' also takes precedence
- if([state isEqual:SecCKKSZoneKeyStateInitializing]) {
- ckksnotice("ckkskey", self, "Resetting the key hierarchy state machine back to '%@'", state);
+ [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];
+ }
- [self _onqueueResetSetup:SecCKKSZoneKeyStateInitializing
- resetMessage:@"Key state has become ready for the first time (after re-initializing)."
- ckoperationGroup:[CKOperationGroup CKKSGroupWithName:@"key-state-reset-to-initializing"]];
+ if([currentState isEqualToString:SecCKKSZoneKeyStateLoggedOut]) {
+ if([flags _onqueueContains:CKKSFlagCloudKitLoggedIn] || self.accountStatus == CKKSAccountStatusAvailable) {
+ [flags _onqueueRemoveFlag:CKKSFlagCloudKitLoggedIn];
- // 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];
+ ckksnotice("ckkskey", self, "CloudKit account now present");
+ return [OctagonStateTransitionOperation named:@"ck-sign-in"
+ entering:SecCKKSZoneKeyStateInitializing];
+ }
- [self _onqueueHandleKeyStateNonTransientDependency:nil];
- return;
+ if([flags _onqueueContains:CKKSFlag24hrNotification]) {
+ [flags _onqueueRemoveFlag:CKKSFlag24hrNotification];
+ }
+ return nil;
}
- // 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([currentState isEqualToString: SecCKKSZoneKeyStateWaitForCloudKitAccountStatus]) {
+ 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:CKKSFlagCloudKitLoggedOut]) {
+ [flags _onqueueRemoveFlag:CKKSFlagCloudKitLoggedOut];
+ ckksnotice("ckkskey", self, "No account available");
- [self ensureKeyStateReadyDependency:@"Key state has become ready for the first time (after lacking trust)."];
+ return [[CKKSLocalResetOperation alloc] initWithDependencies:self.operationDependencies
+ intendedState:SecCKKSZoneKeyStateLoggedOut
+ errorState:SecCKKSZoneKeyStateError];
+ }
+ return nil;
+ }
- 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];
+ [self.launch addEvent:currentState];
+
+ 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];
}
- // In wait for trust, we might have a keyset. Who knows!
- CKKSCurrentKeySet* keyset = [CKKSCurrentKeySet loadForZone:self.zoneID];
- [self _onqueueHandleKeyStateNonTransientDependency:keyset];
+ // 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;
+ return pendingInitializeOp;
}
- // 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([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;
}
- 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;
+ if([currentState isEqualToString:SecCKKSZoneKeyStateInitialized]) {
+ // We're initialized and CloudKit is ready. If we're trusted, see what needs done. Otherwise, wait.
+ return [self performInitializedOperation];
+ }
- [self.keyStateMachineOperation addNullableDependency:self.lockStateTracker.unlockDependency];
- [self scheduleOperation:self.keyStateMachineOperation];
+ // In error? You probably aren't getting out.
+ if([currentState isEqualToString:SecCKKSZoneKeyStateError]) {
+ if([flags _onqueueContains:CKKSFlagCloudKitLoggedIn]) {
+ [flags _onqueueRemoveFlag:CKKSFlagCloudKitLoggedIn];
- [self _onqueueHandleKeyStateNonTransientDependency:nil];
- return;
+ // Worth one last shot. Reset everything locally, and try again.
+ return [[CKKSLocalResetOperation alloc] initWithDependencies:self.operationDependencies
+ intendedState:SecCKKSZoneKeyStateInitializing
+ errorState:SecCKKSZoneKeyStateError];
+ }
- } else {
- // Error state: record the error and exit early
- ckkserror("ckkskey", self, "advised of error: coming from state (%@): %@", self.keyHierarchyState, error);
+ ckkserror("ckkskey", self, "Staying in error state %@", currentState);
+ return nil;
+ }
- [[CKKSAnalytics logger] logUnrecoverableError:error
- forEvent:CKKSEventStateError
- inView:self
- withAttributes:@{ @"previousKeyHierarchyState" : self.keyHierarchyState }];
+ if([currentState isEqualToString:SecCKKSZoneKeyStateResettingZone]) {
+ ckksnotice("ckkskey", self, "Deleting the CloudKit Zone");
+ [self ensureKeyStateReadyDependency:@"ck-zone-reset"];
+ return [[CKKSDeleteCKZoneOperation alloc] initWithDependencies:self.operationDependencies
+ intendedState:SecCKKSZoneKeyStateResettingLocalData
+ errorState:SecCKKSZoneKeyStateResettingZone];
+ }
- self.keyHierarchyState = SecCKKSZoneKeyStateError;
- self.keyHierarchyError = error;
+ if([currentState isEqualToString:SecCKKSZoneKeyStateResettingLocalData]) {
+ ckksnotice("ckkskey", self, "Resetting local data");
- [self _onqueueHandleKeyStateNonTransientDependency:nil];
- return;
- }
+ [self ensureKeyStateReadyDependency:@"local-data-reset"];
+ return [[CKKSLocalResetOperation alloc] initWithDependencies:self.operationDependencies
+ intendedState:SecCKKSZoneKeyStateInitializing
+ errorState:SecCKKSZoneKeyStateError];
}
- if([state isEqual: SecCKKSZoneKeyStateCancelled]) {
- ckkserror("ckkskey", self, "advised of cancel: coming from state (%@): %@", self.keyHierarchyState, error);
- self.keyHierarchyState = SecCKKSZoneKeyStateCancelled;
- self.keyHierarchyError = error;
+ if([currentState isEqualToString:SecCKKSZoneKeyStateZoneCreationFailed]) {
+ //Prepare to go back into initializing, as soon as the cloudkitRetryAfter is happy
+ OctagonStateTransitionOperation* op = [OctagonStateTransitionOperation named:@"recover-from-cloudkit-failure" entering:SecCKKSZoneKeyStateInitializing];
- // 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;
+ [op addNullableDependency:self.operationDependencies.zoneModifier.cloudkitRetryAfter.operationDependency];
+ [self.operationDependencies.zoneModifier.cloudkitRetryAfter trigger];
- [self.keyStateNonTransientDependency cancel];
- self.keyStateNonTransientDependency = nil;
- return;
+ return op;
}
- // 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([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(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
- // But, beginTrustedOperation is currently racy: if it acquires the queue and sets the trust bit between fetching the trust states and getting on the queue,
- // this will fire. So, release SecCKKSZoneKeyStateInitialized from this check.
- if(self.trustStatus == CKKSAccountStatusAvailable
- && ![state isEqualToString:SecCKKSZoneKeyStateLoggedOut]
- && ![state isEqualToString:SecCKKSZoneKeyStateInitialized]) {
- 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 isEqualToString:SecCKKSZoneKeyStateWaitForTrust]) {
+ if(self.trustStatus == CKKSAccountStatusAvailable) {
+ ckksnotice("ckkskey", self, "Beginning trusted state machine operation");
+ return [OctagonStateTransitionOperation named:@"begin-trusted-operation" entering:SecCKKSZoneKeyStateInitialized];
}
- NSAssert(hasSelfIdentities, @"Must have viable (or errored) self peers to advance key state");
+ if([flags _onqueueContains:CKKSFlagKeyStateProcessRequested]) {
+ [flags _onqueueRemoveFlag:CKKSFlagKeyStateProcessRequested];
+ return [OctagonStateTransitionOperation named:@"begin-trusted-operation" entering:SecCKKSZoneKeyStateProcess];
+ }
+
+ if([flags _onqueueContains:CKKSFlag24hrNotification]) {
+ [flags _onqueueRemoveFlag:CKKSFlag24hrNotification];
+ }
+
+ return nil;
}
-#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:SecCKKSZoneKeyStateBecomeReady]) {
+ return [[CKKSCheckKeyHierarchyOperation alloc] initWithDependencies:self.operationDependencies
+ intendedState:SecCKKSZoneKeyStateReady
+ errorState:SecCKKSZoneKeyStateError];
+ }
- // 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:SecCKKSZoneKeyStateReady]) {
+ // If we're ready, we can ignore the begin trusted flag
+ [flags _onqueueRemoveFlag:CKKSFlagBeginTrustedOperation];
-#if !defined(NDEBUG)
- {
- NSError* localerror = nil;
- NSError* allKeysError = nil;
- NSArray<CKKSKey*>* allKeys = [CKKSKey allKeys:self.zoneID error:&allKeysError];
+ 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);
+ [self ensureKeyStateReadyDependency:@"key-state-full-refetch"];
+ return [OctagonStateTransitionOperation named:@"full-refetch" entering:SecCKKSZoneKeyStateNeedFullRefetch];
+ }
- if(localerror) {
- ckkserror("ckkskey", self, "couldn't fetch all keys from local database, entering error state: %@", allKeysError);
+ 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];
}
- ckksdebug("ckkskey", self, "All keys: %@", allKeys);
- }
-#endif
- NSError* hierarchyError = nil;
+ 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(self.keyStateCloudKitDeleteRequested || [state isEqualToString:SecCKKSZoneKeyStateResettingZone]) {
- // CloudKit reset requests take precedence over all other state transitions
- ckksnotice("ckkskey", self, "Deleting the CloudKit Zone");
- CKKSGroupOperation* op = [[CKKSGroupOperation alloc] init];
+ 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];
+ }
- CKKSResultOperation* deleteOp = [self createPendingDeleteZoneOperation:self.keyHierarchyOperationGroup];
- [op runBeforeGroupFinished: deleteOp];
+ if([flags _onqueueContains:CKKSFlagTrustedPeersSetChanged]) {
+ [flags _onqueueRemoveFlag:CKKSFlagTrustedPeersSetChanged];
+ ckksnotice("ckkskey", self, "Received a nudge that the trusted peers set might have changed! Reprocessing.");
+ [self ensureKeyStateReadyDependency:@"Peer set changed"];
+ return [OctagonStateTransitionOperation named:@"trusted-peers-changed" entering:SecCKKSZoneKeyStateProcess];
+ }
- 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;
- }
+ if([flags _onqueueContains:CKKSFlag24hrNotification]) {
+ [flags _onqueueRemoveFlag:CKKSFlag24hrNotification];
- ckksnotice("ckkskey", self, "Zone deletion operation failed, will retry: %@", deleteOp.error);
- [self _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateResettingZone withError:nil];
+ // 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];
+ }
- return true;
- }];
- }];
+ if([flags _onqueueContains:CKKSFlagItemReencryptionNeeded]) {
+ [flags _onqueueRemoveFlag:CKKSFlagItemReencryptionNeeded];
- [nextStateOp addDependency:deleteOp];
- [op runBeforeGroupFinished:nextStateOp];
+ // 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.
+ }
- self.keyStateMachineOperation = op;
- self.keyStateCloudKitDeleteRequested = false;
+ if([flags _onqueueContains:CKKSFlagProcessIncomingQueue]) {
+ [flags _onqueueRemoveFlag:CKKSFlagProcessIncomingQueue];
+ // TODO: this should be part of the state machine
- // Also, pending operations should be cancelled
- [self cancelPendingOperations];
+ [self processIncomingQueue:true];
+ //return [OctagonStateTransitionOperation named:@"process-outgoing" entering:SecCKKSZoneKeyStateProcessIncomingQueue];
+ }
- } else if(self.keyStateLocalResetRequested || [state isEqualToString:SecCKKSZoneKeyStateResettingLocalData]) {
- // Local reset requests take precedence over all other state transitions
- ckksnotice("ckkskey", self, "Resetting local data");
- CKKSGroupOperation* op = [[CKKSGroupOperation alloc] init];
+ if([flags _onqueueContains:CKKSFlagScanLocalItems]) {
+ [flags _onqueueRemoveFlag:CKKSFlagScanLocalItems];
+ ckksnotice("ckkskey", self, "Launching a scan operation to find dropped items");
- CKKSResultOperation* resetOp = [self createPendingResetLocalDataOperation];
- [op runBeforeGroupFinished: resetOp];
+ // TODO: this should be a state flow
+ [self scanLocalItems:@"per-request"];
+ // fall through
+ }
- NSOperation* nextStateOp = [self operationToEnterState:SecCKKSZoneKeyStateInitializing keyStateError:nil named:@"state-resetting-initialize"];
- [nextStateOp addDependency:resetOp];
- [op runBeforeGroupFinished:nextStateOp];
+ if([flags _onqueueContains:CKKSFlagProcessOutgoingQueue]) {
+ [flags _onqueueRemoveFlag:CKKSFlagProcessOutgoingQueue];
- self.keyStateMachineOperation = op;
- self.keyStateLocalResetRequested = false;
+ [self processOutgoingQueue:nil];
+ // TODO: this should be a state flow.
+ //return [OctagonStateTransitionOperation named:@"process-outgoing" entering:SecCKKSZoneKeyStateProcessOutgoingQueue];
+ // fall through
+ }
- } else if([state 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];
+ // TODO: kick off a key roll if one has been requested
- } else if([state isEqualToString:SecCKKSZoneKeyStateWaitForTrust]) {
- // Actually entering this state should have been handled above, so let's check if we can exit it here...
- 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;
+ // If we reach this point, we're in ready, and will stay there.
+ // Tell the launch and the viewReadyScheduler about that.
- } else {
- ckksnotice("ckkskey", self, "Remaining in 'waitfortrust'");
+ [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: SecCKKSZoneKeyStateReady]) {
- NSError* localerror = nil;
- NSArray<CKKSKey*>* remoteKeys = [CKKSKey remoteKeys:self.zoneID error: &localerror];
+ return nil;
+ }
- 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([currentState isEqualToString:SecCKKSZoneKeyStateReadyPendingUnlock]) {
+ if([flags _onqueueContains:CKKSFlagDeviceUnlocked]) {
+ [flags _onqueueRemoveFlag:CKKSFlagDeviceUnlocked];
+ [self ensureKeyStateReadyDependency:@"Device unlocked"];
+ return [OctagonStateTransitionOperation named:@"key-state-ready-after-unlock" entering:SecCKKSZoneKeyStateBecomeReady];
}
- 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;
-
- } else if(self.keyStateFullRefetchRequested) {
- // In ready, but someone has requested a full fetch. Kick it off.
- ckksnotice("ckkskey", self, "Kicking off a full key refetch based on request:%d", self.keyStateFullRefetchRequested);
- nextState = 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) {
- ckksnotice("ckkskey", self, "Received a nudge that the trusted peers set might have changed! Reprocessing.");
- nextState = SecCKKSZoneKeyStateProcess;
- self.trustedPeersSetChanged = false;
+ if([flags _onqueueContains:CKKSFlagProcessOutgoingQueue]) {
+ [flags _onqueueRemoveFlag:CKKSFlagProcessOutgoingQueue];
+ [self processOutgoingQueue:nil];
+ // TODO: this should become part of the key state hierarchy
}
- // TODO: kick off a key roll if one has been requested
+ // Ready enough!
- 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;
- }
- }
+ [[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.
+ OctagonPendingFlag* unlocked = [[OctagonPendingFlag alloc] initWithFlag:CKKSFlagDeviceUnlocked
+ conditions:OctagonPendingConditionsDeviceUnlocked];
+ [pendingFlagHandler _onqueueHandlePendingFlag:unlocked];
+ 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!
+ if([currentState isEqualToString:SecCKKSZoneKeyStateBeginFetch]) {
+ ckksnotice("ckkskey", self, "Starting a key hierarchy fetch");
+ [flags _onqueueRemoveFlag:CKKSFlagFetchComplete];
- // Set this state, for test use
- self.keyHierarchyState = SecCKKSZoneKeyStateInitialized;
+ WEAKIFY(self);
- 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);
- }
+ NSSet<CKKSFetchBecause*>* fetchReasons = self.currentFetchReasons ?
+ [self.currentFetchReasons setByAddingObject:CKKSFetchBecauseKeyHierarchy] :
+ [NSSet setWithObject:CKKSFetchBecauseKeyHierarchy];
- if(keyset.tlk && keyset.classA && keyset.classC && !keyset.error) {
- // This is likely a restart of securityd, and we think we're ready. Double check.
+ CKKSResultOperation* fetchOp = [self.zoneChangeFetcher requestSuccessfulFetchForManyReasons:fetchReasons];
+ CKKSResultOperation* flagOp = [CKKSResultOperation named:@"post-fetch"
+ withBlock:^{
+ STRONGIFY(self);
+ [self.stateMachine handleFlag:CKKSFlagFetchComplete];
+ }];
+ [flagOp addDependency:fetchOp];
+ [self scheduleOperation:flagOp];
- 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;
+ return [OctagonStateTransitionOperation named:@"waiting-for-fetch" entering:SecCKKSZoneKeyStateFetch];
+ }
- } 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:SecCKKSZoneKeyStateFetch]) {
+ if([flags _onqueueContains:CKKSFlagFetchComplete]) {
+ [flags _onqueueRemoveFlag:CKKSFlagFetchComplete];
+ return [OctagonStateTransitionOperation named:@"fetch-complete" entering:SecCKKSZoneKeyStateFetchComplete];
}
- } else if([state isEqualToString:SecCKKSZoneKeyStateFetch]) {
- ckksnotice("ckkskey", self, "Starting a key hierarchy fetch");
- [self _onqueueKeyHierarchyFetch];
+ // 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([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;
+ return nil;
+ }
- } else if([state isEqualToString:SecCKKSZoneKeyStateWaitForFixupOperation]) {
- // We should enter 'initialized' when the fixup operation completes
- ckksnotice("ckkskey", self, "Waiting for the fixup operation: %@", self.lastFixupOperation);
+ if([currentState isEqualToString:SecCKKSZoneKeyStateNeedFullRefetch]) {
+ ckksnotice("ckkskey", self, "Starting a key hierarchy full refetch");
- self.keyStateMachineOperation = [NSBlockOperation named:@"key-state-after-fixup" withBlock:^{
- STRONGIFY(self);
- [self dispatchSyncWithAccountKeys:^bool{
- ckksnotice("ckkskey", self, "Fixup operation complete! Restarting key hierarchy machinery");
- [self _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateInitialized withError:nil];
- return true;
- }];
- }];
- [self.keyStateMachineOperation addNullableDependency:self.lastFixupOperation];
+ //TODO use states here instead of flags
+ self.keyStateMachineRefetched = true;
+ self.keyStateFullRefetchRequested = false;
- } 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:@"fetch-complete" entering:SecCKKSZoneKeyStateResettingLocalData];
+ }
- NSError* localerror = nil;
+ if([currentState isEqualToString:SecCKKSZoneKeyStateFetchComplete]) {
+ [self.launch addEvent:@"fetch-complete"];
+ [self.currentFetchReasons removeAllObjects];
- NSArray<CKKSKey*>* localKeys = [CKKSKey localKeys:self.zoneID error:&localerror];
- NSArray<CKKSKey*>* remoteKeys = [CKKSKey remoteKeys:self.zoneID error: &localerror];
+ return [OctagonStateTransitionOperation named:@"post-fetch-process" entering:SecCKKSZoneKeyStateProcess];
+ }
- 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: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.");
+ return [OctagonStateTransitionOperation named:@"wait-for-tlk-creation-process" entering:SecCKKSZoneKeyStateProcess];
- 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;
-
- } 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;
- }
- }
+ } else if([flags _onqueueContains:CKKSFlagFetchRequested]) {
+ [flags _onqueueRemoveFlag:CKKSFlagFetchRequested];
+ return [OctagonStateTransitionOperation named:@"fetch-requested" entering:SecCKKSZoneKeyStateBeginFetch];
- } else if([state isEqualToString:SecCKKSZoneKeyStateWaitForTLKCreation]) {
+ } else if([flags _onqueueContains:CKKSFlagTLKCreationRequested]) {
+ [flags _onqueueRemoveFlag:CKKSFlagTLKCreationRequested];
- if(self.tlkCreationRequested) {
- self.tlkCreationRequested = false;
- ckksnotice("ckkskey", self, "TLK creation requested; kicking off operation");
- self.keyStateMachineOperation = [[CKKSNewTLKOperation alloc] initWithCKKSKeychainView: self ckoperationGroup:self.keyHierarchyOperationGroup];
+ // 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];
- } else if(self.keyStateProcessRequested) {
- ckksnotice("ckkskey", self, "We believe we need to create TLKs but we also received a key nudge; moving to key state Process.");
- nextState = SecCKKSZoneKeyStateProcess;
+ 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([flags _onqueueContains:CKKSFlagFetchRequested]) {
+ ckksnotice("ckkskey", self, "Received a nudge to refetch CKKS");
+ return [OctagonStateTransitionOperation named:@"tlk-upload-refetch" entering:SecCKKSZoneKeyStateBeginFetch];
+ }
- 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:CKKSFlagKeyStateTLKsUploaded]) {
+ [flags _onqueueRemoveFlag:CKKSFlagKeyStateTLKsUploaded];
+
+ return [OctagonStateTransitionOperation named:@"wait-for-tlk-upload-process" entering:SecCKKSZoneKeyStateProcess];
}
- if(nextState == nil) {
- ckksnotice("ckkskey", self, "Alerting any listener of our proposed keyset: %@", self.lastNewTLKOperation.keyset);
- [self _onqueueRunKeysetProviderOperations:self.lastNewTLKOperation.keyset];
+ if([flags _onqueueContains:CKKSFlagEndTrustedOperation]) {
+ [flags _onqueueRemoveFlag:CKKSFlagEndTrustedOperation];
- ckksnotice("ckkskey", self, "Notifying Octagon again, just in case");
- [self.suggestTLKUpload trigger];
+ return [OctagonStateTransitionOperation named:@"trust-loss" entering:SecCKKSZoneKeyStateLoseTrust];
}
- } else if([state isEqualToString: SecCKKSZoneKeyStateWaitForTLK]) {
+ 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.
+ [self.operationDependencies provideKeySet:self.lastNewTLKOperation.keyset];
+
+ ckksnotice("ckkskey", self, "Notifying Octagon again, just in case");
+ [self.suggestTLKUpload trigger];
+ }
+
+ if([currentState isEqualToString:SecCKKSZoneKeyStateTLKMissing]) {
+ 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;
+ return [OctagonStateTransitionOperation named:@"wait-for-tlk-peers" entering:SecCKKSZoneKeyStateProcess];
+ }
- } else {
- keyset = [CKKSCurrentKeySet loadForZone:self.zoneID];
+ return nil;
+ }
- // 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;
- }
+ if([currentState isEqualToString:SecCKKSZoneKeyStateWaitForUnlock]) {
+ ckksnotice("ckkskey", self, "Requested to enter waitforunlock");
+
+ if([flags _onqueueContains:CKKSFlagDeviceUnlocked ]) {
+ [flags _onqueueRemoveFlag:CKKSFlagDeviceUnlocked];
+ return [OctagonStateTransitionOperation named:@"key-state-after-unlock" entering:SecCKKSZoneKeyStateInitialized];
}
- } else if([state 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];
+ OctagonPendingFlag* unlocked = [[OctagonPendingFlag alloc] initWithFlag:CKKSFlagDeviceUnlocked
+ conditions:OctagonPendingConditionsDeviceUnlocked];
+ [pendingFlagHandler _onqueueHandlePendingFlag:unlocked];
- } 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];
+ return nil;
+ }
- } else if([state isEqualToString: SecCKKSZoneKeyStateBadCurrentPointers]) {
+ 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];
-
- } 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 [[CKKSHealTLKSharesOperation alloc] initWithOperationDependencies:self.operationDependencies
+ ckks:self];
}
- // 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])) {
+ if([currentState isEqualToString:SecCKKSZoneKeyStateProcess]) {
+ [flags _onqueueRemoveFlag:CKKSFlagKeyStateProcessRequested];
- // 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];
- }
+ ckksnotice("ckksshare", self, "Launching key state process");
+ return [[CKKSProcessReceivedKeysOperation alloc] initWithDependencies:self.operationDependencies
+ intendedState:SecCKKSZoneKeyStateBecomeReady
+ errorState:SecCKKSZoneKeyStateError];
}
- 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;
+ return nil;
+}
- } else if([state isEqualToString:SecCKKSZoneKeyStateError]) {
- ckksnotice("ckkskey", self, "Entering key state 'error'");
- self.keyHierarchyState = state;
+- (OctagonStateTransitionOperation*)tlkMissingOperation:(CKKSZoneKeyState*)newState
+{
+ WEAKIFY(self);
+ return [OctagonStateTransitionOperation named:@"tlk-missing"
+ intending:newState
+ errorState:SecCKKSZoneKeyStateError
+ withBlockTakingSelf:^(OctagonStateTransitionOperation * _Nonnull op) {
+ STRONGIFY(self);
- } else if(nextState == nil) {
- ckksnotice("ckkskey", self, "Entering key state: %@", state);
- self.keyHierarchyState = state;
+ NSArray<CKKSPeerProviderState*>* trustStates = self.operationDependencies.currentTrustStates;
- } 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];
+ [self.operationDependencies.databaseProvider dispatchSyncWithReadOnlySQLTransaction:^{
+ CKKSCurrentKeySet* keyset = [CKKSCurrentKeySet loadForZone:self.zoneID];
- } 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(keyset.error) {
+ ckkserror("ckkskey", self, "Unable to load keyset: %@", keyset.error);
+ op.nextState = newState;
- // 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];
-}
+ [self.operationDependencies provideKeySet:keyset];
+ return;
+ }
-- (void)_onqueueHandleKeyStateNonTransientDependency:(CKKSCurrentKeySet* _Nullable)keyset {
- dispatch_assert_queue(self.queue);
+ 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(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(self.trustStatus != CKKSAccountStatusAvailable) {
+ ckksnotice("ckkskey", self, "TLK is missing, but no trust is present.");
+ op.nextState = SecCKKSZoneKeyStateLoseTrust;
- if(keyset && keyset.currentTLKPointer.currentKeyUUID) {
- [self _onqueueRunKeysetProviderOperations:keyset];
- } else {
- ckksnotice("ckkskey", self, "State machine is nontransient, but no keyset...");
- }
- }
-}
+ [self.operationDependencies provideKeySet:keyset];
+ return;
+ }
-- (NSOperation*)operationToEnterState:(CKKSZoneKeyState*)state keyStateError:(NSError* _Nullable)keyStateError named:(NSString*)name {
- WEAKIFY(self);
+ 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];
- return [NSBlockOperation named:name withBlock:^{
- STRONGIFY(self);
- if(!self) {
+ 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<CKKSPeerProviderState*>*)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];
NSMutableSet<NSString*>* trustedPeerIDs = [NSMutableSet set];
- for(CKKSPeerProviderState* trustState in self.currentTrustStates) {
+ for(CKKSPeerProviderState* trustState in trustStates) {
for(id<CKKSPeer> peer in trustState.currentTrustedPeers) {
[trustedPeerIDs addObject:peer.peerID];
}
NSError* localerror = nil;
- NSArray<CKKSDeviceStateEntry*>* allDeviceStates = [CKKSDeviceStateEntry allInZone:self.zoneID error:&localerror];
+ NSArray<CKKSDeviceStateEntry*>* allDeviceStates = [CKKSDeviceStateEntry allInZone:keyset.currentTLKPointer.zoneID error:&localerror];
if(localerror) {
ckkserror("ckkskey", self, "Error fetching device states: %@", localerror);
localerror = nil;
// The peerIDs in CDSEs aren't written with the peer prefix. Make sure we match both.
NSString* sosPeerID = device.circlePeerID ? [CKKSSOSPeerPrefix stringByAppendingString:device.circlePeerID] : nil;
- if([trustedPeerIDs containsObject:device.circlePeerID] ||
- [trustedPeerIDs containsObject:sosPeerID] ||
- [trustedPeerIDs containsObject:device.octagonPeerID]) {
- // Is this a recent DSE? If it's older than the deadline, skip it
- if([device.storedCKRecord.modificationDate compare:trustedDeadline] == NSOrderedAscending) {
- ckksnotice("ckkskey", self, "Trusted device state (%@) is too old; ignoring", device);
- continue;
- }
- } else {
- // Device is untrusted. How does it fare with the untrustedDeadline?
- if([device.storedCKRecord.modificationDate compare:untrustedDeadline] == NSOrderedAscending) {
- ckksnotice("ckkskey", self, "Device (%@) is not trusted and from too long ago; ignoring device state (%@)", device.circlePeerID, device);
- continue;
- } else {
- ckksnotice("ckkskey", self, "Device (%@) is not trusted, but very recent. Including in heuristic: %@", device.circlePeerID, device);
- }
- }
-
- if([device.keyState isEqualToString:SecCKKSZoneKeyStateReady] ||
- [device.keyState isEqualToString:SecCKKSZoneKeyStateReadyPendingUnlock]) {
- ckksnotice("ckkskey", self, "Other device (%@) has keys; it should send them to us", device);
- return true;
- }
- }
-
- NSArray<CKKSTLKShareRecord*>* tlkShares = [CKKSTLKShareRecord allForUUID:keyset.currentTLKPointer.currentKeyUUID
- zoneID:self.zoneID
- error:&localerror];
- if(localerror) {
- ckkserror("ckkskey", self, "Error fetching device states: %@", localerror);
- localerror = nil;
- return false;
- }
-
- for(CKKSTLKShareRecord* tlkShare in tlkShares) {
- if([trustedPeerIDs containsObject:tlkShare.senderPeerID] &&
- [tlkShare.storedCKRecord.modificationDate compare:trustedDeadline] == NSOrderedDescending) {
- ckksnotice("ckkskey", self, "Trusted TLK Share (%@) created recently; other devices have keys and should send them to us", tlkShare);
- return true;
- }
- }
-
- // Okay, how about the untrusted deadline?
- for(CKKSTLKShareRecord* tlkShare in tlkShares) {
- if([tlkShare.storedCKRecord.modificationDate compare:untrustedDeadline] == NSOrderedDescending) {
- ckksnotice("ckkskey", self, "Untrusted TLK Share (%@) created very recently; other devices might have keys and should rejoin the circle (and send them to us)", tlkShare);
- return true;
- }
- }
-
- 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<id<CKKSPeer>>*)_onqueueFindPeers:(CKKSPeerProviderState*)trustState
- missingShare:(CKKSKey*)key
- afterUploading:(NSSet<CKKSTLKShareRecord*>* _Nullable)newShares
- error:(NSError* __autoreleasing*)error
-{
- 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<id<CKKSPeer>>* 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<CKKSRemotePeerProtocol> 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<CKKSTLKShareRecord*>* 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<CKKSTLKShareRecord*>* 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<CKKSTLKShareRecord*>*)newShares
- currentTLK:(CKKSKey*)key
- error:(NSError* __autoreleasing*)error
-{
- dispatch_assert_queue(self.queue);
-
- for(CKKSPeerProviderState* trustState in self.currentTrustStates) {
- NSError* localError = nil;
- NSSet<id<CKKSPeer>>* 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<CKKSTLKShareRecord*>*)_onqueueCreateMissingKeyShares:(CKKSKey*)key
- error:(NSError* __autoreleasing*)error
-{
- NSError* localerror = nil;
- NSSet<CKKSTLKShareRecord*>* 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<CKKSTLKShareRecord*>* 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<CKKSTLKShareRecord*>*)_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<id<CKKSPeer>>* remainingPeers = [self _onqueueFindPeers:trustState missingShare:key afterUploading:nil error:error];
- NSMutableSet<CKKSTLKShareRecord*>* newShares = [NSMutableSet set];
-
- if(!remainingPeers) {
- return nil;
- }
-
- NSError* localerror = nil;
-
- if(![key ensureKeyLoaded:error]) {
- return nil;
- }
-
- for(id<CKKSPeer> 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<id<CKKSPeer>>* 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;
+ if([trustedPeerIDs containsObject:device.circlePeerID] ||
+ [trustedPeerIDs containsObject:sosPeerID] ||
+ [trustedPeerIDs containsObject:device.octagonPeerID]) {
+ // Is this a recent DSE? If it's older than the deadline, skip it
+ if([device.storedCKRecord.modificationDate compare:trustedDeadline] == NSOrderedAscending) {
+ ckksnotice("ckkskey", self, "Trusted device state (%@) is too old; ignoring", device);
+ continue;
}
- return SecCKKSZoneKeyStateHealTLKShares;
} else {
- ckksnotice("ckksshare", self, "TLK (%@) is shared correctly for trust state %@", set.tlk, trustState.peerProviderID);
+ // Device is untrusted. How does it fare with the untrustedDeadline?
+ if([device.storedCKRecord.modificationDate compare:untrustedDeadline] == NSOrderedAscending) {
+ ckksnotice("ckkskey", self, "Device (%@) is not trusted and from too long ago; ignoring device state (%@)", device.circlePeerID, device);
+ continue;
+ } else {
+ ckksnotice("ckkskey", self, "Device (%@) is not trusted, but very recent. Including in heuristic: %@", device.circlePeerID, device);
+ }
}
- anyTrustStateSucceeded |= true;
- }
-
- if(!anyTrustStateSucceeded) {
- if(error) {
- *error = localerror;
+ if([device.keyState isEqualToString:SecCKKSZoneKeyStateReady] ||
+ [device.keyState isEqualToString:SecCKKSZoneKeyStateReadyPendingUnlock]) {
+ ckksnotice("ckkskey", self, "Other device (%@) has keys; it should send them to us", device);
+ return true;
}
-
- 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<CKKSFetchBecause*>*)reasons
-{
- dispatch_assert_queue(self.queue);
+ NSArray<CKKSTLKShareRecord*>* tlkShares = [CKKSTLKShareRecord allForUUID:keyset.currentTLKPointer.currentKeyUUID
+ zoneID:keyset.currentTLKPointer.zoneID
+ error:&localerror];
+ if(localerror) {
+ ckkserror("ckkskey", self, "Error fetching device states: %@", localerror);
+ localerror = nil;
+ return false;
+ }
- WEAKIFY(self);
- self.keyStateMachineOperation = [NSBlockOperation blockOperationWithBlock: ^{
- STRONGIFY(self);
- if(!self) {
- ckkserror("ckks", self, "received callback for released object");
- return;
+ for(CKKSTLKShareRecord* tlkShare in tlkShares) {
+ if([trustedPeerIDs containsObject:tlkShare.senderPeerID] &&
+ [tlkShare.storedCKRecord.modificationDate compare:trustedDeadline] == NSOrderedDescending) {
+ ckksnotice("ckkskey", self, "Trusted TLK Share (%@) created recently; other devices have keys and should send them to us", tlkShare);
+ return true;
}
- [self.launch addEvent:@"fetch-complete"];
+ }
- [self dispatchSyncWithAccountKeys: ^bool{
- [self _onqueueAdvanceKeyStateMachineToState: SecCKKSZoneKeyStateFetchComplete withError: nil];
+ // Okay, how about the untrusted deadline?
+ for(CKKSTLKShareRecord* tlkShare in tlkShares) {
+ if([tlkShare.storedCKRecord.modificationDate compare:untrustedDeadline] == NSOrderedDescending) {
+ ckksnotice("ckkskey", self, "Untrusted TLK Share (%@) created very recently; other devices might have keys and should rejoin the circle (and send them to us)", tlkShare);
return true;
- }];
- }];
- self.keyStateMachineOperation.name = @"waiting-for-fetch";
-
- NSOperation* fetchOp = [self.zoneChangeFetcher requestSuccessfulFetchForManyReasons:reasons];
- [self.keyStateMachineOperation addDependency: fetchOp];
+ }
+ }
- self.keyStateFetchRequested = false;
+ return false;
}
-- (void) handleKeychainEventDbConnection: (SecDbConnectionRef) dbconn
- source:(SecDbTransactionSource)txionSource
- added: (SecDbItemRef) added
- deleted: (SecDbItemRef) deleted
- rateLimiter: (CKKSRateLimiter*) rateLimiter
+- (void)handleKeychainEventDbConnection:(SecDbConnectionRef) dbconn
+ source:(SecDbTransactionSource)txionSource
+ added:(SecDbItemRef) added
+ deleted:(SecDbItemRef) deleted
+ rateLimiter:(CKKSRateLimiter*) rateLimiter
{
if(!SecCKKSIsEnabled()) {
ckksnotice("ckks", self, "Skipping handleKeychainEventDbConnection due to disabled CKKS");
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);
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.
}
if(txionSource == kSecDbSOSTransaction) {
- ckksnotice("ckks", self, "Received an incoming %@ from SOS", isAdd ? @"addition" : (isModify ? @"modification" : @"deletion"));
+ 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];
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.
[CKKSViewManager callSyncCallbackWithErrorNoAccount: syncCallback];
}
- return true;
+ return CKKSDatabaseTransactionCommit;
}
CKKSOutgoingQueueEntry* oqe = nil;
if (isAdd) {
- oqe = [CKKSOutgoingQueueEntry withItem: added action: SecCKKSActionAdd ckks:self error: &error];
+ oqe = [CKKSOutgoingQueueEntry withItem: added action: SecCKKSActionAdd zoneID:self.zoneID error: &error];
} else if(isDelete) {
- oqe = [CKKSOutgoingQueueEntry withItem: deleted action: SecCKKSActionDelete ckks:self error: &error];
+ oqe = [CKKSOutgoingQueueEntry withItem: deleted action: SecCKKSActionDelete zoneID:self.zoneID error: &error];
} else if(isModify) {
- oqe = [CKKSOutgoingQueueEntry withItem: added action: SecCKKSActionModify ckks:self error: &error];
+ oqe = [CKKSOutgoingQueueEntry withItem: added action: SecCKKSActionModify zoneID:self.zoneID error: &error];
} else {
ckkserror("ckks", self, "processKeychainEventItemAdded given garbage: %@ %@", added, deleted);
- return true;
+ return CKKSDatabaseTransactionCommit;
+ }
+
+ 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 = [CKOperationGroup CKKSGroupWithName:@"keychain-api-use"];
+ 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) {
[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<CKKSOutgoingQueueEntry*>* 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);
+ ckkserror("ckks", self, "Couldn't load OQE siblings for %@: %@", oqe, error);
}
- if(reencryptOQE) {
- [reencryptOQE deleteFromDatabase:&error];
- if(error) {
- ckkserror("ckks", self, "Couldn't delete reencrypt OQE sibling(%@) for %@: %@", reencryptOQE, 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);
}
- error = nil;
}
- 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);
- }
- 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;
}];
}
STRONGIFY(self);
- [self dispatchSync: ^bool {
+ [self dispatchSyncWithReadOnlySQLTransaction:^{
NSError* error = nil;
NSString* currentIdentifier = [NSString stringWithFormat:@"%@-%@", accessGroup, identifier];
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) {
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;
}];
}];
[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<CKKSKeySetProviderOperationProtocol>*)findKeySet
+- (CKKSResultOperation<CKKSKeySetProviderOperationProtocol>*)findKeySet:(BOOL)refetchBeforeReturningKeySet
{
__block CKKSResultOperation<CKKSKeySetProviderOperationProtocol>* keysetOp = nil;
+ __block BOOL moveFromWaitForTrust = NO;
- [self dispatchSyncWithAccountKeys:^bool {
- CKKSCurrentKeySet* keyset = [CKKSCurrentKeySet loadForZone:self.zoneID];
- if(keyset.currentTLKPointer.currentKeyUUID && keyset.tlk.uuid) {
- ckksnotice("ckks", self, "Already have keyset %@", keyset);
-
- keysetOp = [[CKKSProvideKeySetOperation alloc] initWithZoneName:self.zoneName keySet:keyset];
- [self scheduleOperationWithoutDependencies:keysetOp];
- return true;
- } else if([self.keyHierarchyState isEqualToString:SecCKKSZoneKeyStateWaitForTLKUpload]) {
- CKKSCurrentKeySet* proposedKeySet = self.lastNewTLKOperation.keyset;
- ckksnotice("ckks", self, "Already have proposed keyset %@", proposedKeySet);
+ [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:proposedKeySet];
+ // 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 {
- // 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");
+ if(refetchBeforeReturningKeySet) {
+ ckksnotice("ckks", self, "Refetch requested before returning key set!");
- keysetOp = (CKKSProvideKeySetOperation*) [self findFirstPendingOperation:self.keysetProviderOperations];
- if(!keysetOp) {
- keysetOp = [[CKKSProvideKeySetOperation alloc] initWithZoneName:self.zoneName];
- [self.keysetProviderOperations addObject:keysetOp];
+ [self.stateMachine _onqueueHandleFlag:CKKSFlagFetchRequested];
+ [self.stateMachine _onqueueHandleFlag:CKKSFlagTLKCreationRequested];
- // 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];
+ if([self.stateMachine.currentState isEqualToString:SecCKKSZoneKeyStateWaitForTrust]) {
+ moveFromWaitForTrust = YES;
}
-
- [self _onqueueAdvanceKeyStateMachineToState:nil withError:nil];
+ return;
}
- return true;
- }];
+ 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);
- return keysetOp;
-}
+ [keysetOp provideKeySet:keyset];
+ return;
-- (void)_onqueueRunKeysetProviderOperations:(CKKSCurrentKeySet*)keyset
-{
- ckksnotice("ckkskey", self, "Providing keyset (%@) to listeners", keyset);
+ } else if([self.stateMachine.currentState isEqualToString:SecCKKSZoneKeyStateWaitForTrust]) {
+ // No keyset exists, but we're in waitfortrust? Seems like a bug. Move us out of this state...
- // We have some keyset; they can ask again if they want a new one
- self.tlkCreationRequested = false;
+ ckksnotice("ckks", self, "Received a keyset request in an odd state; forwarding to state machine");
+ [self.stateMachine _onqueueHandleFlag:CKKSFlagTLKCreationRequested];
+ moveFromWaitForTrust = YES;
- for(CKKSResultOperation<CKKSKeySetProviderOperationProtocol>* op in self.keysetProviderOperations) {
- if([op isPending]) {
- [op provideKeySet:keyset];
- }
+ } else {
+ // The key state machine will know what to do.
+ [self.stateMachine _onqueueHandleFlag:CKKSFlagTLKCreationRequested];
+ };
+ }];
+
+ if(moveFromWaitForTrust) {
+ [self.stateMachine handleExternalRequest:[[OctagonStateTransitionRequest alloc] init:@"fix-bug"
+ sourceStates:[NSSet setWithObject:SecCKKSZoneKeyStateWaitForTrust]
+ serialQueue:self.queue
+ timeout:5 * NSEC_PER_SEC
+ transitionOp:[OctagonStateTransitionOperation named:@"fix-bug"
+ entering:SecCKKSZoneKeyStateWaitForTLKCreation]]];
}
+
+ return keysetOp;
}
- (void)receiveTLKUploadRecords:(NSArray<CKRecord*>*)records
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];
}
}
-// 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;
- }
-}
-
-- (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
{
CKKSOutgoingQueueOperation* outgoingop =
(CKKSOutgoingQueueOperation*) [self findFirstPendingOperation:self.outgoingQueueOperations
}
// 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];
}
}
- CKKSOutgoingQueueOperation* op = [[CKKSOutgoingQueueOperation alloc] initWithCKKSKeychainView:self ckoperationGroup:ckoperationGroup];
+ CKKSOutgoingQueueOperation* op = [[CKKSOutgoingQueueOperation alloc] initWithDependencies:self.operationDependencies
+ ckks:self
+ intending:SecCKKSZoneKeyStateReady
+ errorState:SecCKKSZoneKeyStateUnhealthy
+ ckoperationGroup:ckoperationGroup];
op.name = @"outgoing-queue-operation";
[op addNullableDependency:after];
[op addNullableDependency:self.outgoingQueueOperationScheduler.operationDependency];
}
- (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");
// 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
+ ckks:self
+ intending:SecCKKSZoneKeyStateReady
+ errorState:SecCKKSZoneKeyStateUnhealthy
+ errorOnClassAFailure:failOnClassA
+ handleMismatchedViewItems:policyConsideredAuthoritative];
op.name = @"incoming-queue-operation";
if(after != nil) {
[op addSuccessDependency: after];
if(self.resultsOfNextIncomingQueueOperationOperation) {
[self.resultsOfNextIncomingQueueOperationOperation addSuccessDependency:op];
[self scheduleOperation:self.resultsOfNextIncomingQueueOperationOperation];
+ self.resultsOfNextIncomingQueueOperationOperation = nil;
}
[self scheduleOperation: op];
}
}
- scanOperation = [[CKKSScanLocalItemsOperation alloc] initWithCKKSKeychainView:self ckoperationGroup:operationGroup];
+ scanOperation = [[CKKSScanLocalItemsOperation alloc] initWithDependencies:self.operationDependencies
+ ckks:self
+ intending:SecCKKSZoneKeyStateReady
+ errorState:SecCKKSZoneKeyStateError
+ ckoperationGroup:operationGroup];
scanOperation.name = operationName;
[scanOperation addNullableDependency:self.lastFixupOperation];
[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.
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 {
+ dispatch_assert_queue(self.queue);
NSError* localerror = nil;
CKKSAccountStateTracker* accountTracker = self.accountTracker;
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
//
// 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];
+ [self.stateMachine _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, "CKKS Server extension has told us about %@ for record %@; requesting refetch and reprocess of key hierarchy", thirdLevelError, recordID);
- [self _onqueueKeyStateMachineRequestFetch];
+ [self.stateMachine _onqueueHandleFlag:CKKSFlagFetchRequested];
} else {
ckkserror("ckks", self, "CKKS Server extension has told us about %@ for record %@, but we don't currently handle this error", thirdLevelError, recordID);
// 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);
+ ckksnotice("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];
if(iqeerror) {
ckkserror("ckks", self, "Couldn't save incoming queue entry: %@", iqeerror);
}
+
+ // Delete any pending local changes; this delete wins
+ NSArray<CKKSOutgoingQueueEntry*>* siblings = [CKKSOutgoingQueueEntry allWithUUID:iqe.uuid
+ states:@[SecCKKSStateNew,
+ SecCKKSStateReencrypt,
+ SecCKKSStateError]
+ zoneID:self.zoneID
+ error:&error];
+ if(error) {
+ ckkserror("ckks", self, "Couldn't load OQE sibling for %@: %@", iqe.uuid, error);
+ }
+
+ for(CKKSOutgoingQueueEntry* oqe in siblings) {
+ NSError* deletionError = nil;
+ [oqe deleteFromDatabase:&deletionError];
+ if(deletionError) {
+ ckkserror("ckks", self, "Couldn't delete OQE sibling(%@) for %@: %@", oqe, iqe.uuid, deletionError);
+ }
+ }
}
ckksinfo("ckks", self, "CKKSMirrorEntry was deleted: %@ %@ error: %@", recordID, ckme, error);
// TODO: actually pass error back up
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");
+ ckksnotice("ckks", self, "CloudKit has told us of record we already know about for %@; skipping update", ckme.uuid);
return;
}
if(error) {
ckkserror("ckks", self, "couldn't save new CKRecord to database: %@ %@", record, error);
} else {
- ckksdebug("ckks", self, "CKKSMirrorEntry was created: %@", ckme);
+ ckksinfo("ckks", self, "CKKSMirrorEntry was created: %@", ckme);
}
NSError* iqeerror = nil;
if(iqeerror) {
ckkserror("ckks", self, "Couldn't save modified incoming queue entry: %@", iqeerror);
} else {
- ckksdebug("ckks", self, "CKKSIncomingQueueEntry was created: %@", iqe);
+ ckksinfo("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];
+ NSArray<CKKSOutgoingQueueEntry*>* siblings = [CKKSOutgoingQueueEntry allWithUUID:iqe.uuid
+ states:@[SecCKKSStateNew,
+ SecCKKSStateReencrypt,
+ SecCKKSStateError]
+ zoneID:self.zoneID
+ error:&error];
if(error) {
- ckkserror("ckks", self, "Couldn't load OutgoingQueueEntry: %@", error);
- }
- if(oqe) {
- [self _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateDeleted error:&error];
+ ckkserror("ckks", self, "Couldn't load OQE sibling for %@: %@", iqe.uuid, 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);
+ for(CKKSOutgoingQueueEntry* oqe in siblings) {
+ NSError* deletionError = nil;
+ [oqe deleteFromDatabase:&deletionError];
+ if(deletionError) {
+ ckkserror("ckks", self, "Couldn't delete OQE sibling(%@) for %@: %@", oqe, iqe.uuid, deletionError);
}
}
}
}
// We've saved a new key in the database; trigger a rekey operation.
- [self _onqueueKeyStateMachineRequestProcess];
+ [self.stateMachine _onqueueHandleFlag:CKKSFlagKeyStateProcessRequested];
}
- (void)_onqueueCKRecordTLKShareChanged:(CKRecord*)record resync:(bool)resync {
ckkserror("ckksshare", self, "Couldn't save new TLK share to database: %@ %@", share, error);
}
- [self _onqueueKeyStateMachineRequestProcess];
+ [self.stateMachine _onqueueHandleFlag:CKKSFlagKeyStateProcessRequested];
}
- (void)_onqueueCKRecordCurrentKeyPointerChanged:(CKRecord*)record resync:(bool)resync {
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];
+ [self.stateMachine _onqueueHandleFlag:CKKSFlagKeyStateProcessRequested];
}
}
- (void)_onqueueCKRecordManifestChanged:(CKRecord*)record resync:(bool)resync
{
+ dispatch_assert_queue(self.queue);
NSError* error = nil;
CKKSPendingManifest* manifest = [[CKKSPendingManifest alloc] initWithCKRecord:record];
[manifest saveToDatabase:&error];
- (void)_onqueueCKRecordManifestLeafChanged:(CKRecord*)record resync:(bool)resync
{
+ dispatch_assert_queue(self.queue);
NSError* error = nil;
CKKSManifestLeafRecord* manifestLeaf = [[CKKSManifestPendingLeafRecord alloc] initWithCKRecord:record];
[manifestLeaf saveToDatabase:&error];
}
- (void)_onqueueCKRecordDeviceStateChanged:(CKRecord*)record resync:(bool)resync {
+ dispatch_assert_queue(self.queue);
if(resync) {
NSError* dserror = nil;
CKKSDeviceStateEntry* cdse = [CKKSDeviceStateEntry tryFromDatabase:record.recordID.recordName zoneID:self.zoneID error:&dserror];
}
- (bool)_onqueueResetAllInflightOQE:(NSError**)error {
+ dispatch_assert_queue(self.queue);
NSError* localError = nil;
while(true) {
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 = [[CKKSViewManager manager] claimCallbackForUUID:oqe.uuid];
- if(callback) {
- callback(false, itemError);
- }
- 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
-{
- 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)) {
+ // 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;
}
- ckkserror("ckksshare", self, "Errored unwrapping TLK with TLKShares: %@", localerror);
- return false;
- } else {
- ckkserror("ckksshare", self, "Non-fatal error unwrapping TLK with TLKShares: %@", localerror);
+ }
+ } else {
+ oqe.state = state;
+ [oqe saveToDatabase: &localerror];
+ if(localerror) {
+ ckkserror("ckks", self, "Couldn't save %@ as %@: %@", oqe, state, 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;
+ oqe.state = state;
+ [oqe saveToDatabase: &localerror];
+ if(localerror) {
+ ckkserror("ckks", self, "Couldn't save %@ as %@: %@", oqe, state, localerror);
}
-
- ckkserror("ckksshare", self, "Unable to recover TLK from trust set: %@", localerror);
}
- // Only report the last error
if(error && localerror) {
*error = localerror;
}
- return false;
+ return localerror == nil;
}
-- (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;
- }
+- (bool)_onqueueErrorOutgoingQueueEntry: (CKKSOutgoingQueueEntry*) oqe itemError: (NSError*) itemError error: (NSError* __autoreleasing*) error {
+ dispatch_assert_queue(self.queue);
- 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;
+ SecBoolNSErrorCallback callback = [[CKKSViewManager manager] claimCallbackForUUID:oqe.uuid];
+ if(callback) {
+ callback(false, itemError);
}
+ NSError* localerror = nil;
- NSError* lastShareError = nil;
-
- for(id<CKKSSelfPeer> selfPeer in trustState.currentSelfPeers.allSelves) {
- NSArray<CKKSTLKShareRecord*>* 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;
- }
- }
+ // 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) {
- *error = [NSError errorWithDomain:CKKSErrorDomain
- code:CKKSNoTrustedTLKShares
- description:[NSString stringWithFormat:@"No trusted TLKShares for %@", proposedTLK]
- underlying:lastShareError];
+ if(error && localerror) {
+ *error = localerror;
}
- return false;
+ return localerror == nil;
}
-- (bool)dispatchSyncWithConnection:(SecDbConnectionRef _Nonnull)dbconn block:(bool (^)(void))block {
+- (bool)dispatchSyncWithConnection:(SecDbConnectionRef _Nonnull)dbconn
+ readWriteTxion:(BOOL)readWriteTxion
+ block:(CKKSDatabaseTransactionResult (^)(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) {
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...
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);
+ }
+
+ (void)transaction;
+}
+
+- (void)dispatchSyncWithReadOnlySQLTransaction:(void (^)(void))block
+{
+ // Please don't jetsam us...
+ os_transaction_t transaction = os_transaction_create([[NSString stringWithFormat:@"com.apple.securityd.ckks.%@", self.zoneName] UTF8String]);
+
+ CFErrorRef cferror = NULL;
+
+ // 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);
(void)transaction;
}
-- (void)dispatchSyncWithAccountKeys:(bool (^)(void))block
+- (BOOL)insideSQLTransaction
+{
+ return CKKSSQLInTransaction;
+}
+
+#pragma mark - CKKSZone operations
+
+- (void)beginCloudKitOperation
{
- [self dispatchSyncWithPeerProviders:self.currentPeerProviders override:false block:block];
+ [self.accountTracker registerForNotificationsOfCloudKitAccountStatusChange:self];
}
-- (void)dispatchSyncWithPeerProviders:(NSArray<id<CKKSPeerProvider>>*)peerProviders
- override:(bool)overridePeerProviders
- block:(bool (^)(void))block
+- (CKKSResultOperation*)createAccountLoggedInDependency:(NSString*)message
{
- NSArray<id<CKKSPeerProvider>>* actualPeerProviders = overridePeerProviders ? peerProviders : self.currentPeerProviders;
- NSMutableArray<CKKSPeerProviderState*>* trustStates = [NSMutableArray array];
+ WEAKIFY(self);
+ CKKSResultOperation* accountLoggedInDependency = [CKKSResultOperation named:@"account-logged-in-dependency" withBlock:^{
+ STRONGIFY(self);
+ ckksnotice("ckkszone", self, "%@", message);
+ }];
+ accountLoggedInDependency.descriptionErrorCode = CKKSResultDescriptionPendingAccountLoggedIn;
+ return accountLoggedInDependency;
+}
+
+#pragma mark - CKKSZoneUpdateReceiverProtocol
- for(id<CKKSPeerProvider> provider in actualPeerProviders) {
- ckksnotice("ckks", self, "Fetching account keys for provider %@", provider);
- [trustStates addObject:provider.currentState];
+- (CKKSAccountStatus)accountStatusFromCKAccountInfo:(CKAccountInfo*)info
+{
+ if(!info) {
+ return CKKSAccountStatusUnknown;
+ }
+ if(info.accountStatus == CKAccountStatusAvailable &&
+ info.hasValidCredentials) {
+ return CKKSAccountStatusAvailable;
+ } else {
+ return CKKSAccountStatusNoAccount;
}
+}
- [self dispatchSync:^bool{
- if(overridePeerProviders) {
- self.currentPeerProviders = peerProviders;
- }
- self.currentTrustStates = trustStates;
+- (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);
- bool result = block();
+ // Filter for device2device encryption and cloudkit grey mode
+ CKKSAccountStatus oldStatus = [self accountStatusFromCKAccountInfo:oldAccountInfo];
+ CKKSAccountStatus currentStatus = [self accountStatusFromCKAccountInfo:currentAccountInfo];
- // Forget the peers; they might have class A key material
- NSMutableArray<CKKSPeerProviderState*>* noTrustStates = [NSMutableArray array];
- for(id<CKKSPeerProvider> provider in peerProviders) {
- (void)provider;
- [noTrustStates addObject:[CKKSPeerProviderState noPeersState:provider]];
+ 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;
+ };
}
- self.currentTrustStates = noTrustStates;
+ break;
- return result;
- }];
-}
+ case CKKSAccountStatusNoAccount: {
+ ckksnotice("ckkszone", self, "Logging out of iCloud. Shutting down.");
+
+ if(!self.accountLoggedInDependency) {
+ self.accountLoggedInDependency = [self createAccountLoggedInDependency:@"CloudKit account logged in again."];
+ }
-#pragma mark - CKKSZoneUpdateReceiver
+ [self handleCKLogout];
+ }
+ break;
-- (void)notifyZoneChange: (CKRecordZoneNotification*) notification {
- ckksnotice("ckks", self, "received a zone change notification for %@ %@", self, notification);
+ 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);
- [self fetchAndProcessCKChangesDueToAPNS:notification];
-}
+ if(!self.accountLoggedInDependency) {
+ self.accountLoggedInDependency = [self createAccountLoggedInDependency:@"CloudKit account logged in again."];
+ }
-- (void)superHandleCKLogin {
- [super handleCKLogin];
+ [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];
-}
+ [self.stateMachine handleFlag:CKKSFlagCloudKitLoggedIn];
-- (void)superHandleCKLogout {
- [super handleCKLogout];
+ [self.accountStateKnown fulfill];
}
-- (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];
+- (void)handleCKLogout
+{
+ dispatch_sync(self.queue, ^{
+ ckksinfo("ckkszone", self, "received a notification of CK logout");
- self.loggedIn = [[CKKSCondition alloc] initToChain: self.loggedIn];
- [self.loggedOut fulfill];
- [self.accountStateKnown fulfill];
+ self.accountStatus = CKKSAccountStatusNoAccount;
+ self.loggedIn = [[CKKSCondition alloc] initToChain:self.loggedIn];
+ [self.loggedOut fulfill];
+ });
- return true;
- }];
- }];
+ [self.stateMachine handleFlag:CKKSFlagCloudKitLoggedOut];
- [self scheduleAccountStatusOperation: logout];
+ [self.accountStateKnown fulfill];
}
#pragma mark - Trust operations
- (void)beginTrustedOperation:(NSArray<id<CKKSPeerProvider>>*)peerProviders
suggestTLKUpload:(CKKSNearFutureScheduler*)suggestTLKUpload
+ requestPolicyCheck:(CKKSNearFutureScheduler*)requestPolicyCheck
{
for(id<CKKSPeerProvider> peerProvider in peerProviders) {
[peerProvider registerForPeerChangeUpdates:self];
[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;
+
CKKSAccountStatus oldTrustStatus = self.trustStatus;
self.suggestTLKUpload = suggestTLKUpload;
+ self.requestPolicyCheck = requestPolicyCheck;
self.trustStatus = CKKSAccountStatusAvailable;
- if(self.trustDependency) {
- [self scheduleOperation: self.trustDependency];
- self.trustDependency = nil;
- }
- [self _onqueueAdvanceKeyStateMachineToState:nil withError:nil];
+ [self.stateMachine _onqueueHandleFlag:CKKSFlagBeginTrustedOperation];
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];
+ }
+ });
+}
+
+- (void)receivedItemForWrongView
+{
+ [self.requestPolicyCheck trigger];
}
#pragma mark - CKKSChangeFetcherClient
{
__block BOOL ready = NO;
- [self dispatchSync: ^bool {
+ [self dispatchSyncWithReadOnlySQLTransaction:^{
ready = (bool)[self _onQueueZoneIsReadyForFetching];
- return ready;
}];
return ready;
- (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;
}
{
__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;
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) {
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 dispatchSync:^bool {
- ckkserror("ckksfetch", self, "No record changes in this fetch");
+ [self dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{
+ ckksinfo("ckksfetch", self, "No record changes in this fetch");
NSError* error = nil;
CKKSZoneStateEntry* state = [CKKSZoneStateEntry state:self.zoneName];
if(error) {
ckkserror("ckksfetch", self, "Couldn't save new server change token: %@", error);
}
- return true;
+ return CKKSDatabaseTransactionCommit;
}];
return;
}
- [self dispatchSyncWithAccountKeys:^bool{
+ [self dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{
for (CKRecord* record in changedRecords) {
[self _onqueueCKRecordChanged:record resync:resync];
}
ckksnotice("ckksfetch", self, "Finished processing changes for %@", self.zoneID);
- return true;
+ return CKKSDatabaseTransactionCommit;
}];
}
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;
}
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;
}
// 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 {
}
}
+#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) {
}
[self.scanLocalItemsOperations removeAllObjects];
}
-
- [super cancelAllOperations];
}
- (void)cancelAllOperations {
- [self.zoneSetupOperation cancel];
- [self.keyStateMachineOperation cancel];
[self.keyStateReadyDependency cancel];
- [self.keyStateNonTransientDependency cancel];
[self.zoneChangeFetcher cancel];
[self.notifyViewChangedScheduler cancel];
- [self.pokeKeyStateMachineScheduler 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;
#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);
}
@"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;
}
__block NSDictionary* ret = nil;
- [self dispatchSync: ^bool {
+ [self dispatchSyncWithReadOnlySQLTransaction:^{
+ CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.zoneName];
ret = @{
@"view": CKKSNilToNSNull(self.zoneName),
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;
--- /dev/null
+
+#import <Foundation/Foundation.h>
+
+#if OCTAGON
+
+#import "keychain/ckks/CKKSKeychainView.h"
+#import "keychain/ckks/CKKSOperationDependencies.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface CKKSLocalResetOperation : CKKSResultOperation <OctagonStateTransitionOperationProtocol>
+@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
--- /dev/null
+
+#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;
+
+ CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.deps.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", self.deps.zoneID, "couldn't reset zone status: %@", localerror);
+ self.error = localerror;
+ localerror = nil;
+ }
+
+ [CKKSMirrorEntry deleteAll:self.deps.zoneID error:&localerror];
+ if(localerror && self.error == nil) {
+ ckkserror("local-reset", self.deps.zoneID, "couldn't delete all CKKSMirrorEntry: %@", localerror);
+ self.error = localerror;
+ localerror = nil;
+ }
+
+ [CKKSOutgoingQueueEntry deleteAll:self.deps.zoneID error:&localerror];
+ if(localerror && self.error == nil) {
+ ckkserror("local-reset", self.deps.zoneID, "couldn't delete all CKKSOutgoingQueueEntry: %@", localerror);
+ self.error = localerror;
+ localerror = nil;
+ }
+
+ [CKKSIncomingQueueEntry deleteAll:self.deps.zoneID error:&localerror];
+ if(localerror && self.error == nil) {
+ ckkserror("local-reset", self.deps.zoneID, "couldn't delete all CKKSIncomingQueueEntry: %@", localerror);
+ self.error = localerror;
+ localerror = nil;
+ }
+
+ [CKKSKey deleteAll:self.deps.zoneID error:&localerror];
+ if(localerror && self.error == nil) {
+ ckkserror("local-reset", self.deps.zoneID, "couldn't delete all CKKSKey: %@", localerror);
+ self.error = localerror;
+ localerror = nil;
+ }
+
+ [CKKSTLKShareRecord deleteAll:self.deps.zoneID error:&localerror];
+ if(localerror && self.error == nil) {
+ ckkserror("local-reset", self.deps.zoneID, "couldn't delete all CKKSTLKShare: %@", localerror);
+ self.error = localerror;
+ localerror = nil;
+ }
+
+ [CKKSCurrentKeyPointer deleteAll:self.deps.zoneID error:&localerror];
+ if(localerror && self.error == nil) {
+ ckkserror("local-reset", self.deps.zoneID, "couldn't delete all CKKSCurrentKeyPointer: %@", localerror);
+ self.error = localerror;
+ localerror = nil;
+ }
+
+ [CKKSCurrentItemPointer deleteAll:self.deps.zoneID error:&localerror];
+ if(localerror && self.error == nil) {
+ ckkserror("local-reset", self.deps.zoneID, "couldn't delete all CKKSCurrentItemPointer: %@", localerror);
+ self.error = localerror;
+ localerror = nil;
+ }
+
+ [CKKSDeviceStateEntry deleteAll:self.deps.zoneID error:&localerror];
+ if(localerror && self.error == nil) {
+ ckkserror("local-reset", self.deps.zoneID, "couldn't delete all CKKSDeviceStateEntry: %@", localerror);
+ self.error = localerror;
+ localerror = nil;
+ }
+
+ if(!self.error) {
+ ckksnotice("local-reset", self.deps.zoneID, "Successfully deleted all local data");
+ self.nextState = self.intendedState;
+ }
+}
+
+@end
+
+#endif // OCTAGON
+
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;
[self dependOnBeforeGroupFinished:outgoingOp];
// Step 2
- CKKSIncomingQueueOperation* incomingOp = [[CKKSIncomingQueueOperation alloc] initWithCKKSKeychainView:ckks errorOnClassAFailure:true];
+ CKKSIncomingQueueOperation* incomingOp = [[CKKSIncomingQueueOperation alloc] initWithDependencies:ckks.operationDependencies
+ ckks:ckks
+ 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];
[self runBeforeGroupFinished:reloadOp];
// Step 4
- CKKSIncomingQueueOperation* incomingResyncOp = [[CKKSIncomingQueueOperation alloc] initWithCKKSKeychainView:ckks errorOnClassAFailure:true];
+ CKKSIncomingQueueOperation* incomingResyncOp = [[CKKSIncomingQueueOperation alloc] initWithDependencies:ckks.operationDependencies
+ ckks:ckks
+ 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];
[restart addExecutionBlock:^{
STRONGIFY(self);
if(!self) {
- secerror("ckksresync: received callback for released object");
+ ckkserror("ckksresync", ckks, "received callback for released object");
return;
}
[restart addSuccessDependency: scan];
[self runBeforeGroupFinished: restart];
- return true;
+ return CKKSDatabaseTransactionCommit;
}];
}
- (void)main {
CKKSKeychainView* strongCKKS = self.ckks;
- [strongCKKS dispatchSync: ^bool{
+ [strongCKKS dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{
NSError* error = nil;
NSArray<CKKSMirrorEntry*>* 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
[strongCKKS _onqueueCKRecordChanged:ckmeRecord resync:true];
}
- return true;
+ return CKKSDatabaseTransactionCommit;
}];
}
@end
-(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 locked = true;
if(!SecAKSGetIsLocked(&locked, &aksError)) {
- secerror("ckks: error querying lock state: %@", aksError);
+ ckkserror_global("ckks", "error querying lock state: %@", aksError);
CFReleaseNull(aksError);
}
});
}
--(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
--- /dev/null
+
+#import <Foundation/Foundation.h>
+#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;
+}
[[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;
}
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;
}
[[CKKSEgoManifest egoHelper] performWithPeerVerifyingKeys:^(NSDictionary<NSString*, SFECPublicKey*>* 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;
}
- (instancetype)initWithDigestValue:(NSData*)digestValue zone:(NSString*)zone generationCount:(NSUInteger)generationCount leafRecordIDs:(NSArray<NSString*>*)leafRecordIDs peerManifestIDs:(NSArray<NSString*>*)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;
}
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;
{
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],
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;
}
}
NSData* derData = [[NSData alloc] initWithBase64EncodedString:record[SecCKRecordManifestLeafDERKey] options:0];
NSDictionary<NSString*, NSData*>* 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;
}
- (instancetype)initWithUUID:(NSString*)uuid digest:(NSData*)digest recordDigestDict:(NSDictionary<NSString*, NSData*>*)recordDigestDict zone:(NSString*)zone
{
if ([uuid containsString:manifestLeafRecordNameDelimiter]) {
- secerror("uuid contains delimiter: %@", uuid);
+ ckkserror_global("ckksmanifest", "uuid contains delimiter: %@", uuid);
return nil;
}
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;
NSData* derData = [[NSData alloc] initWithBase64EncodedString:record[SecCKRecordManifestLeafDERKey] options:0];
NSDictionary<NSString*, NSData*>* 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;
}
// 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;
}
}
#import <Foundation/Foundation.h>
#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 <CKKSKeySetContainerProtocol>
+@interface CKKSNewTLKOperation : CKKSGroupOperation <CKKSKeySetContainerProtocol,
+ OctagonStateTransitionOperationProtocol>
+@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
#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"
#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;
}
return;
}
+ NSArray<CKKSPeerProviderState*>* currentTrustStates = self.deps.currentTrustStates;
+
// Synchronous, on some thread. Get back on the CKKS queue for SQL thread-safety.
- __block bool enterWaitForTLKUpload = false;
- [ckks dispatchSyncWithAccountKeys: ^bool{
+ [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{
if(self.cancelled) {
ckksnotice("ckkstlk", ckks, "CKKSNewTLKOperation cancelled, quitting");
- return false;
+ return CKKSDatabaseTransactionRollback;
}
ckks.lastNewTLKOperation = self;
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:
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]
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];
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
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;
[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<CKKSTLKShareRecord*>* 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;
// 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
- enterWaitForTLKUpload = true;
- return true;
+ // We'll provide the keyset after the commit occurs.
+ self.nextState = SecCKKSZoneKeyStateWaitForTLKUpload;
+ return CKKSDatabaseTransactionCommit;
}];
- if(enterWaitForTLKUpload) {
- // And move the CKKS state machine:
- [ckks dispatchSyncWithAccountKeys: ^bool{
- [ckks _onqueueAdvanceKeyStateMachineToState:SecCKKSZoneKeyStateWaitForTLKUpload withError:nil];
- return true;
- }];
+ if(self.keyset) {
+ [self.deps provideKeySet:self.keyset];
}
}
#import "CKKSNotifier.h"
#import <notify.h>
-#import <utilities/debugging.h>
+#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]);
}
}
--- /dev/null
+#if OCTAGON
+
+#import <Foundation/Foundation.h>
+#import <CloudKit/CloudKit.h>
+
+#import "keychain/ckks/CKKSCurrentKeyPointer.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) CKRecordZoneID* zoneID;
+@property (nullable) CKOperationGroup* ckoperationGroup;
+
+@property (readonly) CKKSLaunchSequence* launch;
+@property (readonly) id<OctagonStateFlagHandler> flagHandler;
+
+@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<id<CKKSPeerProvider>>* 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<CKKSDatabaseProviderProtocol> databaseProvider;
+
+@property CKKSZoneModifier* zoneModifier;
+
+@property (readonly) CKKSNearFutureScheduler* notifyViewChangedScheduler;
+@property (readonly) CKKSNearFutureScheduler* savedTLKNotifier;
+
+// This might contain some key set provider operations. if you're an operation that knows about keysets, feel free to provide them.
+@property NSHashTable<CKKSResultOperation<CKKSKeySetProviderOperationProtocol>*>* keysetProviderOperations;
+
+- (instancetype)initWithZoneID:(CKRecordZoneID*)zoneID
+ zoneModifier:(CKKSZoneModifier*)zoneModifier
+ ckoperationGroup:(CKOperationGroup* _Nullable)operationGroup
+ flagHandler:(id<OctagonStateFlagHandler>)flagHandler
+ launchSequence:(CKKSLaunchSequence*)launchSequence
+ lockStateTracker:(CKKSLockStateTracker*)lockStateTracker
+ reachabilityTracker:(CKKSReachabilityTracker*)reachabilityTracker
+ peerProviders:(NSArray<id<CKKSPeerProvider>>*)peerProviders
+ databaseProvider:(id<CKKSDatabaseProviderProtocol>)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<CKKSPeerProviderState*>*)currentTrustStates;
+
+- (void)provideKeySet:(CKKSCurrentKeySet*)keyset;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // OCTAGON
--- /dev/null
+
+#if OCTAGON
+
+#import "keychain/ckks/CKKS.h"
+#import "keychain/ckks/CKKSOperationDependencies.h"
+
+@implementation CKKSOperationDependencies
+
+- (instancetype)initWithZoneID:(CKRecordZoneID*)zoneID
+ zoneModifier:(CKKSZoneModifier*)zoneModifier
+ ckoperationGroup:(CKOperationGroup* _Nullable)operationGroup
+ flagHandler:(id<OctagonStateFlagHandler>)flagHandler
+ launchSequence:(CKKSLaunchSequence*)launchSequence
+ lockStateTracker:(CKKSLockStateTracker*)lockStateTracker
+ reachabilityTracker:(CKKSReachabilityTracker*)reachabilityTracker
+ peerProviders:(NSArray<id<CKKSPeerProvider>>*)peerProviders
+ databaseProvider:(id<CKKSDatabaseProviderProtocol>)databaseProvider
+ notifyViewChangedScheduler:(CKKSNearFutureScheduler*)notifyViewChangedScheduler
+ savedTLKNotifier:(CKKSNearFutureScheduler*)savedTLKNotifier
+{
+ if((self = [super init])) {
+ _zoneID = zoneID;
+ _zoneModifier = zoneModifier;
+ _ckoperationGroup = operationGroup;
+ _flagHandler = flagHandler;
+ _launch = launchSequence;
+ _lockStateTracker = lockStateTracker;
+ _reachabilityTracker = reachabilityTracker;
+ _peerProviders = peerProviders;
+ _databaseProvider = databaseProvider;
+ _notifyViewChangedScheduler = notifyViewChangedScheduler;
+ _savedTLKNotifier = savedTLKNotifier;
+
+ _keysetProviderOperations = [NSHashTable weakObjectsHashTable];
+ }
+ return self;
+}
+
+- (NSArray<CKKSPeerProviderState*>*)currentTrustStates
+{
+ NSArray<id<CKKSPeerProvider>>* peerProviders = self.peerProviders;
+ NSMutableArray<CKKSPeerProviderState*>* 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<CKKSPeerProvider> 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<CKKSKeySetProviderOperationProtocol>* op in self.keysetProviderOperations) {
+ [op provideKeySet:keyset];
+ }
+}
+
+@end
+
+#endif // OCTAGON
+ (instancetype)withItem:(SecDbItemRef)item
action:(NSString*)action
- ckks:(CKKSKeychainView*)ckks
+ zoneID:(CKRecordZoneID*)zoneID
error:(NSError* __autoreleasing*)error;
+ (instancetype)fromDatabase:(NSString*)uuid
state:(NSString*)state
zoneID:(CKRecordZoneID*)zoneID
error:(NSError* __autoreleasing*)error;
++ (NSArray<CKKSOutgoingQueueEntry*>*)allWithUUID:(NSString*)uuid
+ states:(NSArray<NSString*>*)states
+ zoneID:(CKRecordZoneID*)zoneID
+ error:(NSError * __autoreleasing *)error;
+
+ (NSDictionary<NSString*, NSNumber*>*)countsByStateInZone:(CKRecordZoneID*)zoneID error:(NSError* __autoreleasing*)error;
+ (NSInteger)countByState:(CKKSItemState *)state zone:(CKRecordZoneID*)zoneID error: (NSError * __autoreleasing *) error;
true) ? YES : NO;
}
-+ (instancetype)withItem:(SecDbItemRef)item action:(NSString*)action ckks:(CKKSKeychainView*)ckks error: (NSError * __autoreleasing *) error {
+
++ (CKKSKey*)keyForItem:(SecDbItemRef)item zoneID:(CKRecordZoneID*)zoneID 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 = [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
+ error:(NSError * __autoreleasing *)error
+{
CFErrorRef cferror = NULL;
CKKSKey* key = nil;
NSString* uuid = nil;
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
+ 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;
}
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;
}
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;
}
}
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;
}
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;
}
}
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:
// (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]) {
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 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;
CKKSItem* baseitem = [[CKKSItem alloc] initWithUUID:uuid
parentKeyUUID:key.uuid
- zoneID:ckks.zoneID
+ zoneID:zoneID
encodedCKRecord:nil
encItem:nil
wrappedkey:nil
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;
}
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;
}
return [self allWhere: @{@"state":CKKSNilToNSNull(state), @"ckzone":CKKSNilToNSNull(zoneID.zoneName)} error:error];
}
++ (NSArray<CKKSOutgoingQueueEntry*>*)allWithUUID:(NSString*)uuid states:(NSArray<NSString*>*)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
* @APPLE_LICENSE_HEADER_END@
*/
-#import <Foundation/Foundation.h>
-#import "keychain/ckks/CKKSGroupOperation.h"
#if OCTAGON
+#import <Foundation/Foundation.h>
#import <CloudKit/CloudKit.h>
+#import "keychain/ckks/CKKSGroupOperation.h"
+#import "keychain/ckks/CKKSOperationDependencies.h"
+#import "keychain/ot/OctagonStateMachineHelpers.h"
+
NS_ASSUME_NONNULL_BEGIN
@class CKKSKeychainView;
-@interface CKKSOutgoingQueueOperation : CKKSGroupOperation
+@interface CKKSOutgoingQueueOperation : CKKSGroupOperation <OctagonStateTransitionOperationProtocol>
+@property CKKSOperationDependencies* deps;
@property (weak) CKKSKeychainView* ckks;
@property CKOperationGroup* ckoperationGroup;
@property size_t itemsProcessed;
- (instancetype)init NS_UNAVAILABLE;
-- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup;
-
+- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies
+ ckks:(CKKSKeychainView*)ckks
+ intending:(OctagonState*)intending
+ errorState:(OctagonState*)errorState
+ ckoperationGroup:(CKOperationGroup*)ckoperationGroup;
@end
NS_ASSUME_NONNULL_END
#import <CloudKit/CloudKit.h>
#import <CloudKit/CloudKit_Private.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 "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/CloudKitCategories.h"
#import "keychain/ot/ObjCImprovements.h"
#include "keychain/securityd/SecItemServer.h"
#include "keychain/securityd/SecItemDb.h"
#include <Security/SecItemPriv.h>
-#include <utilities/SecADWrapper.h>
#import "CKKSPowerCollection.h"
+#import "utilities/SecCoreAnalytics.h"
@interface CKKSOutgoingQueueOperation()
@property CKModifyRecordsOperation* modifyRecordsOperation;
@end
@implementation CKKSOutgoingQueueOperation
-
-- (instancetype)init {
- if(self = [super init]) {
- }
- return nil;
-}
-- (instancetype)initWithCKKSKeychainView:(CKKSKeychainView*)ckks ckoperationGroup:(CKOperationGroup*)ckoperationGroup {
+@synthesize nextState = _nextState;
+@synthesize intendedState = _intendedState;
+
+- (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies
+ ckks:(CKKSKeychainView*)ckks
+ intending:(OctagonState*)intending
+ errorState:(OctagonState*)errorState
+ ckoperationGroup:(CKOperationGroup*)ckoperationGroup
+{
if(self = [super init]) {
+ _deps = dependencies;
_ckks = ckks;
_ckoperationGroup = ckoperationGroup;
+ _nextState = errorState;
+ _intendedState = intending;
+
[self addNullableDependency:ckks.holdOutgoingQueueOperation];
// Depend on all previous CKKSOutgoingQueueOperations
}
- (void) groupStart {
- // Synchronous, on some thread. Get back on the CKKS queue for thread-safety.
WEAKIFY(self);
CKKSKeychainView* ckks = self.ckks;
if(!ckks) {
- ckkserror("ckksoutgoing", ckks, "no ckks object");
+ ckkserror("ckksoutgoing", self.deps.zoneID, "no ckks object");
return;
}
- [ckks dispatchSync: ^bool{
- ckks.lastOutgoingQueueOperation = self;
- if(self.cancelled) {
- ckksnotice("ckksoutgoing", ckks, "CKKSOutgoingQueueOperation cancelled, quitting");
- return false;
- }
+ if(!ckks.itemSyncingEnabled) {
+ ckkserror("ckksoutgoing", self.deps.zoneID, "Item syncing for this view is disabled");
+ return;
+ }
+
+ ckks.lastOutgoingQueueOperation = self;
+
+ [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{
NSError* error = nil;
for(NSString* uuid in priorityUUIDs) {
NSError* priorityFetchError = nil;
- CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry tryFromDatabase:uuid zoneID:ckks.zoneID error:&priorityFetchError];
+ CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry tryFromDatabase:uuid zoneID:self.deps.zoneID error:&priorityFetchError];
if(priorityFetchError) {
- ckkserror("ckksoutgoing", ckks, "Unable to fetch priority uuid %@: %@", uuid, priorityFetchError);
+ ckkserror("ckksoutgoing", self.deps.zoneID, "Unable to fetch priority uuid %@: %@", uuid, priorityFetchError);
continue;
}
}
if(![oqe.state isEqualToString:SecCKKSStateNew]) {
- ckksnotice("ckksoutgoing", ckks, "Priority uuid %@ is not in 'new': %@", uuid, oqe);
+ ckksnotice("ckksoutgoing", self.deps.zoneID, "Priority uuid %@ is not in 'new': %@", uuid, oqe);
continue;
}
if(oqe) {
- ckksnotice("ckksoutgoing", ckks, "Found OQE to fetch priority uuid %@: %@", uuid, priorityFetchError);
+ ckksnotice("ckksoutgoing", self.deps.zoneID, "Found OQE to fetch priority uuid %@: %@", uuid, priorityFetchError);
[priorityEntries addObject:oqe];
[priorityEntryUUIDs addObject:oqe.uuid];
}
// We only actually care about queue items in the 'new' state
NSArray<CKKSOutgoingQueueEntry*> * newEntries = [CKKSOutgoingQueueEntry fetch:SecCKKSOutgoingQueueItemsAtOnce
state:SecCKKSStateNew
- zoneID:ckks.zoneID
+ zoneID:self.deps.zoneID
error:&error];
if(error != nil) {
- ckkserror("ckksoutgoing", ckks, "Error fetching outgoing queue records: %@", error);
+ ckkserror("ckksoutgoing", self.deps.zoneID, "Error fetching outgoing queue records: %@", error);
self.error = error;
- return false;
+ return CKKSDatabaseTransactionRollback;
}
// Build our list of oqes to transmit
bool fullUpload = queueEntries.count >= SecCKKSOutgoingQueueItemsAtOnce;
- [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventOutgoingQueue zone:ckks.zoneName count:[queueEntries count]];
+ [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventOutgoingQueue zone:self.deps.zoneID.zoneName count:[queueEntries count]];
- ckksinfo("ckksoutgoing", ckks, "processing outgoing queue: %@", queueEntries);
+ ckksinfo("ckksoutgoing", self.deps.zoneID, "processing outgoing queue: %@", queueEntries);
NSMutableDictionary<CKRecordID*, CKRecord*>* recordsToSave = [[NSMutableDictionary alloc] init];
NSMutableSet<CKRecordID*>* recordIDsModified = [[NSMutableSet alloc] init];
NSMutableSet<CKKSOutgoingQueueEntry*>*oqesModified = [[NSMutableSet alloc] init];
NSMutableArray<CKRecordID *>* recordIDsToDelete = [[NSMutableArray alloc] init];
- CKKSCurrentKeyPointer* currentClassAKeyPointer = [CKKSCurrentKeyPointer fromDatabase: SecCKKSKeyClassA zoneID:ckks.zoneID error: &error];
- CKKSCurrentKeyPointer* currentClassCKeyPointer = [CKKSCurrentKeyPointer fromDatabase: SecCKKSKeyClassC zoneID:ckks.zoneID error: &error];
+ CKKSCurrentKeyPointer* currentClassAKeyPointer = [CKKSCurrentKeyPointer fromDatabase:SecCKKSKeyClassA zoneID:self.deps.zoneID error:&error];
+ CKKSCurrentKeyPointer* currentClassCKeyPointer = [CKKSCurrentKeyPointer fromDatabase:SecCKKSKeyClassC zoneID:self.deps.zoneID error:&error];
NSMutableDictionary<CKKSKeyClass*, CKKSCurrentKeyPointer*>* currentKeysToSave = [[NSMutableDictionary alloc] init];
bool needsReencrypt = false;
if(error != nil) {
- ckkserror("ckksoutgoing", ckks, "Couldn't load current class keys: %@", error);
- return false;
+ ckkserror("ckksoutgoing", self.deps.zoneID, "Couldn't load current class keys: %@", error);
+ return CKKSDatabaseTransactionRollback;
}
for(CKKSOutgoingQueueEntry* oqe in queueEntries) {
if(self.cancelled) {
secdebug("ckksoutgoing", "CKKSOutgoingQueueOperation cancelled, quitting");
- return false;
+ return CKKSDatabaseTransactionRollback;
}
- CKKSOutgoingQueueEntry* inflight = [CKKSOutgoingQueueEntry tryFromDatabase: oqe.uuid state:SecCKKSStateInFlight zoneID:ckks.zoneID error: &error];
+ CKKSOutgoingQueueEntry* inflight = [CKKSOutgoingQueueEntry tryFromDatabase: oqe.uuid state:SecCKKSStateInFlight zoneID:self.deps.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;
} 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);
+ ckksnotice("ckksoutgoing", self.deps.zoneID, "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);
+ ckkserror("ckksoutgoing", self.deps.zoneID, "couldn't save oqe to database: %@", error);
self.error = error;
error = nil;
}
}
if([oqe.action isEqualToString: SecCKKSActionAdd]) {
- CKRecord* record = [oqe.item CKRecordWithZoneID: ckks.zoneID];
+ CKRecord* record = [oqe.item CKRecordWithZoneID:self.deps.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);
+ ckkserror("ckksoutgoing", self.deps.zoneID, "couldn't save state for CKKSOutgoingQueueEntry: %@", error);
self.error = error;
}
} else if ([oqe.action isEqualToString: SecCKKSActionDelete]) {
- CKRecordID* recordIDToDelete = [[CKRecordID alloc] initWithRecordName: oqe.item.uuid zoneID: ckks.zoneID];
+ CKRecordID* recordIDToDelete = [[CKRecordID alloc] initWithRecordName:oqe.item.uuid zoneID:self.deps.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);
+ ckkserror("ckksoutgoing", self.deps.zoneID, "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];
+ CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:oqe.item.uuid zoneID:self.deps.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);
+ ckkserror("ckksoutgoing", self.deps.zoneID, "update to a record that doesn't exist? %@", oqe.item.uuid);
// treat as an add.
- CKRecord* record = [oqe.item CKRecordWithZoneID: ckks.zoneID];
+ CKRecord* record = [oqe.item CKRecordWithZoneID:self.deps.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);
+ ckkserror("ckksoutgoing", self.deps.zoneID, "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);
+ ckksnotice("ckksoutgoing", self.deps.zoneID, "Record (%@)'s change tag doesn't match ckmirror's change tag, reencrypting", oqe);
[ckks _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateReencrypt error:&error];
if(error) {
- ckkserror("ckksoutgoing", ckks, "couldn't save oqe to database: %@", error);
+ ckkserror("ckksoutgoing", self.deps.zoneID, "couldn't save oqe to database: %@", error);
self.error = error;
error = nil;
}
continue;
}
// Grab the old ckrecord and update it
- CKRecord* record = [oqe.item updateCKRecord: ckme.item.storedCKRecord zoneID: ckks.zoneID];
+ CKRecord* record = [oqe.item updateCKRecord: ckme.item.storedCKRecord zoneID: self.deps.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);
+ ckkserror("ckksoutgoing", self.deps.zoneID, "couldn't save state for CKKSOutgoingQueueEntry: %@", error);
}
}
}
}
if(needsReencrypt) {
- ckksnotice("ckksoutgoing", ckks, "An item needs reencryption!");
-
- CKKSReencryptOutgoingItemsOperation* op = [[CKKSReencryptOutgoingItemsOperation alloc] initWithCKKSKeychainView:ckks ckoperationGroup:self.ckoperationGroup];
- [ckks scheduleOperation: op];
+ ckksnotice("ckksoutgoing", self.deps.zoneID, "An item needs reencryption!");
+ [self.deps.flagHandler _onqueueHandleFlag:CKKSFlagItemReencryptionNeeded];
}
if([recordsToSave count] == 0 && [recordIDsToDelete count] == 0) {
// Nothing to do! exit.
- ckksnotice("ckksoutgoing", ckks, "Nothing in outgoing queue to process");
+ ckksnotice("ckksoutgoing", self.deps.zoneID, "Nothing in outgoing queue to process");
if(self.ckoperationGroup) {
- ckksnotice("ckksoutgoing", ckks, "End of operation group: %@", self.ckoperationGroup);
+ ckksinfo("ckksoutgoing", self.deps.zoneID, "End of operation group: %@", self.ckoperationGroup);
}
return true;
}
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<CKRecord*>*, NSArray<CKRecordID*>*, NSError*) = ^(NSArray<CKRecord *> *savedRecords, NSArray<CKRecordID *> *deletedRecordIDs, NSError *ckerror) {
STRONGIFY(self);
CKKSKeychainView* strongCKKS = self.ckks;
if(!self || !strongCKKS) {
- ckkserror("ckksoutgoing", strongCKKS, "received callback for released object");
+ ckkserror("ckksoutgoing", self.deps.zoneID, "received callback for released object");
return;
}
CKKSAnalytics* logger = [CKKSAnalytics logger];
- [strongCKKS dispatchSyncWithAccountKeys: ^bool{
+ [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{
if(ckerror) {
- ckkserror("ckksoutgoing", strongCKKS, "error processing outgoing queue: %@", ckerror);
+ ckkserror("ckksoutgoing", self.deps.zoneID, "error processing outgoing queue: %@", ckerror);
[logger logRecoverableError:ckerror
forEvent:CKKSEventProcessOutgoingQueue
- inView:strongCKKS
+ zoneName:self.deps.zoneID.zoneName
withAttributes:NULL];
// Tell CKKS about any out-of-date records
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'");
+ ckksnotice("ckksoutgoing", self.deps.zoneID, "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'");
+ ckksnotice("ckksoutgoing", self.deps.zoneID, "Error is due to the key records missing. Marking all as 'needs reencrypt'");
[self _onqueueModifyAllRecords:failedRecords.allKeys as:SecCKKSStateReencrypt];
askForReencrypt = true;
for(CKRecordID* recordID in failedRecords) {
NSError* recordError = failedRecords[recordID];
- ckksnotice("ckksoutgoing", strongCKKS, "failed record: %@ %@", recordID, recordError);
+ ckksnotice("ckksoutgoing", self.deps.zoneID, "failed record: %@ %@", recordID, recordError);
if([recordError.domain isEqualToString: CKErrorDomain] && recordError.code == CKErrorServerRecordChanged) {
if([recordID.recordName isEqualToString: SecCKKSKeyClassA] ||
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);
+ ckkserror("ckksoutgoing", self.deps.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", strongCKKS, "Unknown error on row: %@ %@", recordID, recordError);
+ ckkserror("ckksoutgoing", self.deps.zoneID, "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];
+ [self.deps.flagHandler _onqueueHandleFlag:CKKSFlagItemReencryptionNeeded];
}
} 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'");
+ ckksnotice("ckks", self.deps.zoneID, "Error is scary: putting all inflight OQEs back into state 'new'");
[self _onqueueModifyAllRecords:[recordIDsModified allObjects] as:SecCKKSStateNew];
}
self.error = ckerror;
- return true;
+ return CKKSDatabaseTransactionCommit;
}
- ckksnotice("ckksoutgoing", strongCKKS, "Completed processing outgoing queue (%d modifications, %d deletions)", (int)savedRecords.count, (int)deletedRecordIDs.count);
+ for(CKRecordID* deletedRecordID in deletedRecordIDs) {
+ ckksnotice("ckksoutgoing", self.deps.zoneID, "Record deletion successful for %@", deletedRecordID.recordName);
+ }
+
+ ckksnotice("ckksoutgoing", self.deps.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:strongCKKS.zoneID error:&error];
+ CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry fromDatabase:record.recordID.recordName
+ state:SecCKKSStateInFlight
+ zoneID:self.deps.zoneID
+ error:&error];
[strongCKKS _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateDeleted error:&error];
if(error) {
- ckkserror("ckksoutgoing", strongCKKS, "Couldn't update %@ in outgoingqueue: %@", record.recordID.recordName, error);
+ ckkserror("ckksoutgoing", self.deps.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", strongCKKS, "Couldn't save %@ to ckmirror: %@", record.recordID.recordName, error);
+ ckkserror("ckksoutgoing", self.deps.zoneID, "Couldn't save %@ to ckmirror: %@", record.recordID.recordName, error);
self.error = error;
}
CKKSCurrentKeyPointer* currentkey = [[CKKSCurrentKeyPointer alloc] initWithCKRecord: record];
[currentkey saveToDatabase: &error];
if(error) {
- ckkserror("ckksoutgoing", strongCKKS, "Couldn't save %@ to currentkey: %@", record.recordID.recordName, error);
+ ckkserror("ckksoutgoing", self.deps.zoneID, "Couldn't save %@ to currentkey: %@", record.recordID.recordName, error);
self.error = error;
}
CKKSDeviceStateEntry* newcdse = [[CKKSDeviceStateEntry alloc] initWithCKRecord:record];
[newcdse saveToDatabase:&error];
if(error) {
- ckkserror("ckksoutgoing", strongCKKS, "Couldn't save %@ to ckdevicestate: %@", record.recordID.recordName, error);
+ ckkserror("ckksoutgoing", self.deps.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", strongCKKS, "unknown record type in results: %@", record);
+ ckkserror("ckksoutgoing", self.deps.zoneID, "unknown record type in results: %@", record);
}
}
for(CKRecordID* ckrecordID in deletedRecordIDs) {
NSError* error = nil;
- CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry fromDatabase: ckrecordID.recordName state: SecCKKSStateInFlight zoneID:strongCKKS.zoneID error:&error];
+ CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry fromDatabase:ckrecordID.recordName
+ state:SecCKKSStateInFlight
+ zoneID:self.deps.zoneID
+ error:&error];
[strongCKKS _onqueueChangeOutgoingQueueEntry:oqe toState:SecCKKSStateDeleted error:&error];
if(error) {
- ckkserror("ckksoutgoing", strongCKKS, "Couldn't delete %@ from outgoingqueue: %@", ckrecordID.recordName, error);
+ ckkserror("ckksoutgoing", self.deps.zoneID, "Couldn't delete %@ from outgoingqueue: %@", ckrecordID.recordName, error);
self.error = error;
}
error = nil;
- CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase: ckrecordID.recordName zoneID:strongCKKS.zoneID error:&error];
+ CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase: ckrecordID.recordName zoneID:self.deps.zoneID error:&error];
[ckme deleteFromDatabase: &error];
if(error) {
- ckkserror("ckksoutgoing", strongCKKS, "Couldn't delete %@ from ckmirror: %@", ckrecordID.recordName, error);
+ ckkserror("ckksoutgoing", self.deps.zoneID, "Couldn't delete %@ from ckmirror: %@", ckrecordID.recordName, error);
self.error = error;
}
[plstats commit];
if(self.error) {
- ckkserror("ckksoutgoing", strongCKKS, "Operation failed; rolling back: %@", self.error);
+ ckkserror("ckksoutgoing", self.deps.zoneID, "Operation failed; rolling back: %@", self.error);
[logger logRecoverableError:self.error
forEvent:CKKSEventProcessOutgoingQueue
- inView:strongCKKS
+ zoneName:strongCKKS.zoneName
withAttributes:NULL];
- return false;
+ return CKKSDatabaseTransactionRollback;
} else {
- [logger logSuccessForEvent:CKKSEventProcessOutgoingQueue inView:strongCKKS];
+ [logger logSuccessForEvent:CKKSEventProcessOutgoingQueue zoneName:strongCKKS.zoneName];
}
- return true;
+ return CKKSDatabaseTransactionCommit;
}];
+ self.nextState = self.intendedState;
[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];
+ // 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
+ 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];
+ }
};
- ckksinfo("ckksoutgoing", ckks, "Current keys to update: %@", currentKeysToSave);
+ ckksinfo("ckksoutgoing", self.deps.zoneID, "Current keys to update: %@", currentKeysToSave);
for(CKKSCurrentKeyPointer* keypointer in currentKeysToSave.allValues) {
- CKRecord* record = [keypointer CKRecordWithZoneID: ckks.zoneID];
+ CKRecord* record = [keypointer CKRecordWithZoneID:self.deps.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];
+ CKRecord* cdseRecord = [cdse CKRecordWithZoneID:self.deps.zoneID];
if(cdseError) {
- ckkserror("ckksoutgoing", ckks, "Can't make current device state: %@", cdseError);
+ ckkserror("ckksoutgoing", self.deps.zoneID, "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");
+ ckkserror("ckksoutgoing", self.deps.zoneID, "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);
+ ckksnotice("ckksoutgoing", self.deps.zoneID, "Updating device state: %@", cdse);
recordsToSave[cdseRecord.recordID] = cdseRecord;
}
- ckksinfo("ckksoutgoing", ckks, "Saving records %@ to CloudKit zone %@", recordsToSave, ckks.zoneID);
+ ckksinfo("ckksoutgoing", self.deps.zoneID, "Saving records %@ to CloudKit zone %@", recordsToSave, self.deps.zoneID);
self.modifyRecordsOperation = [[CKModifyRecordsOperation alloc] initWithRecordsToSave:recordsToSave.allValues recordIDsToDelete:recordIDsToDelete];
self.modifyRecordsOperation.atomic = TRUE;
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);
+ ckksnotice("ckksoutgoing", self.deps.zoneID, "QoS: %d; operation group is %@", (int)self.modifyRecordsOperation.qualityOfService, self.modifyRecordsOperation.group);
+ ckksnotice("ckksoutgoing", self.deps.zoneID, "Beginning upload for %d records, deleting %d records",
+ (int)recordsToSave.count,
+ (int)recordIDsToDelete.count);
+
+ for(CKRecordID* recordID in [recordsToSave allKeys]) {
+ ckksinfo("ckksoutgoing", self.deps.zoneID, "Record to save: %@", recordID);
+ }
+ for(CKRecordID* recordID in recordIDsToDelete) {
+ ckksinfo("ckksoutgoing", self.deps.zoneID, "Record to delete: %@", recordID);
+ }
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);
+ ckksnotice("ckksoutgoing", self.deps.zoneID, "Record upload successful for %@ (%@)", record.recordID.recordName, record.recordChangeTag);
} else {
- ckkserror("ckksoutgoing", blockCKKS, "error on row: %@ %@", error, record);
+ ckkserror("ckksoutgoing", self.deps.zoneID, "error on row: %@ %@", error, record);
}
};
- (void)_onqueueModifyRecordAsError:(CKRecordID*)recordID recordError:(NSError*)itemerror {
CKKSKeychainView* ckks = self.ckks;
if(!ckks) {
- ckkserror("ckksoutgoing", ckks, "no CKKS object");
+ ckkserror("ckksoutgoing", self.deps.zoneID, "no CKKS object");
return;
}
[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];
+ CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry fromDatabase:recordID.recordName state:SecCKKSStateInFlight zoneID:self.deps.zoneID error:&error];
[ckks _onqueueErrorOutgoingQueueEntry: oqe itemError: itemerror error:&error];
if(error) {
- ckkserror("ckksoutgoing", ckks, "Couldn't set OQE %@ as error: %@", recordID.recordName, error);
+ ckkserror("ckksoutgoing", self.deps.zoneID, "Couldn't set OQE %@ as error: %@", recordID.recordName, error);
self.error = error;
}
count ++;
- (void)_onqueueModifyAllRecords:(NSArray<CKRecordID*>*)recordIDs as:(CKKSItemState*)state {
CKKSKeychainView* ckks = self.ckks;
if(!ckks) {
- ckkserror("ckksoutgoing", ckks, "no CKKS object");
+ ckkserror("ckksoutgoing", self.deps.zoneID, "no CKKS object");
return;
}
[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];
+ CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry fromDatabase:recordID.recordName state:SecCKKSStateInFlight zoneID:self.deps.zoneID error:&error];
[ckks _onqueueChangeOutgoingQueueEntry:oqe toState:state error:&error];
if(error) {
- ckkserror("ckksoutgoing", ckks, "Couldn't set OQE %@ as %@: %@", recordID.recordName, state, error);
+ ckkserror("ckksoutgoing", self.deps.zoneID, "Couldn't set OQE %@ as %@: %@", recordID.recordName, state, error);
self.error = error;
}
count ++;
}
if([state isEqualToString:SecCKKSStateReencrypt]) {
- SecADAddValueForScalarKey((__bridge CFStringRef) SecCKKSAggdItemReencryption, count);
+ [SecCoreAnalytics sendEvent:SecCKKSAggdItemReencryption event:@{SecCoreAnalyticsValue: [NSNumber numberWithUnsignedInteger:count]}];
}
}
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;
}
}
}
- (bool)_onqueueIsErrorBadEtagOnKeyPointersOnly:(NSError*)ckerror {
+ CKKSKeychainView* ckks = self.ckks;
+ dispatch_assert_queue(ckks.queue);
bool anyOtherErrors = false;
if([ckerror.domain isEqualToString:CKErrorDomain] && (ckerror.code == CKErrorPartialFailure)) {
- (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"];
- (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"];
#import <Foundation/Foundation.h>
#import "keychain/ckks/CKKSPeer.h"
+#import "keychain/ckks/CKKSCurrentKeyPointer.h"
NS_ASSUME_NONNULL_BEGIN
#pragma mark - CKKSPeerProviderState
+@class CKKSKey;
+@class CKKSTLKShareRecord;
+
@interface CKKSPeerProviderState : NSObject
@property NSString* peerProviderID;
trustedPeers:(NSSet<id<CKKSPeer>>* _Nullable)currentTrustedPeers
trustedPeersError:(NSError* _Nullable)trustedPeersError;
+- (NSSet<id<CKKSPeer>>* _Nullable)findPeersMissingTLKSharesFor:(CKKSCurrentKeySet*)keyset
+ error:(NSError**)error;
+
+- (BOOL)unwrapKey:(CKKSKey*)proposedTLK
+ fromShares:(NSArray<CKKSTLKShareRecord*>*)tlkShares
+ error:(NSError**)error;
+
+ (CKKSPeerProviderState*)noPeersState:(id<CKKSPeerProvider>)provider;
// Intended for use in PeerProviders. Thread-safety is up to the PeerProvider.
#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
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<id<CKKSPeer>>* _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<CKKSTLKShareRecord*>* tlkShares = [keyset.tlkShares arrayByAddingObjectsFromArray:keyset.pendingTLKShares ?: @[]];
+
+ NSMutableSet<id<CKKSPeer>>* 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<CKKSRemotePeerProtocol> 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<CKKSTLKShareRecord*>*)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<CKKSSelfPeer> selfPeer in self.currentSelfPeers.allSelves) {
+ NSMutableArray<CKKSTLKShareRecord*>* 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
@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 <OctagonStateTransitionOperationProtocol>
+@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
#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<CKKSPeerProviderState*>* currentTrustStates = self.deps.currentTrustStates;
- CKKSKeychainView* ckks = self.ckks;
- if(!ckks) {
- secerror("ckkskeys: No CKKS object");
- return;
- }
-
- if(self.cancelled) {
- ckksinfo("ckkskey", ckks, "CKKSProcessReceivedKeysOperation cancelled, quitting");
- return;
- }
+ [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult {
+ bool ok = [self _onqueueMain:currentTrustStates];
- [ckks dispatchSyncWithAccountKeys: ^bool{
- return [self _onqueueMain:ckks];
+ return ok ? CKKSDatabaseTransactionCommit : CKKSDatabaseTransactionRollback;
}];
}
-- (bool)_onqueueMain:(CKKSKeychainView*)ckks
+- (bool)_onqueueMain:(NSArray<CKKSPeerProviderState*>*)currentTrustStates
{
- if(self.cancelled) {
- ckksinfo("ckkskey", ckks, "CKKSProcessReceivedKeysOperation cancelled, quitting");
- return false;
- }
-
- ckks.lastProcessReceivedKeysOperation = self;
-
NSError* error = nil;
CKKSKey* tlk = nil;
CKKSKey* topKey = nil;
// Updates from CloudKit are marked 'remote'; everything else is 'local'.
// Step 1. Find all remote keys.
- NSArray<CKKSKey*>* remoteKeys = [CKKSKey remoteKeys:ckks.zoneID error:&error];
+ NSArray<CKKSKey*>* 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;
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;
}
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.
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
// 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]
}
}
- ckksnotice("ckkskey", ckks, "New key %@ wraps to tlk %@", key, tlk);
+ ckksnotice("ckkskey", self.deps.zoneID, "New key %@ wraps to tlk %@", key, tlk);
}
[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;
}
@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
// But! -timeout: will work, and the operation will finish
@interface CKKSProvideKeySetOperation : CKKSGroupOperation <CKKSKeySetProviderOperationProtocol>
- (instancetype)initWithZoneName:(NSString*)zoneName;
-- (instancetype)initWithZoneName:(NSString*)zoneName keySet:(CKKSCurrentKeySet*)set;
- (void)provideKeySet:(CKKSCurrentKeySet*)keyset;
@end
@interface CKKSProvideKeySetOperation ()
@property (nullable) CKKSCurrentKeySet* keyset;
+@property dispatch_queue_t queue;
@property (nullable) NSOperation* startDependency;
@end
_zoneName = zoneName;
_keyset = nil;
_startDependency = [NSBlockOperation blockOperationWithBlock:^{}];
+ _startDependency.name = @"key-set-provided";
- [self addDependency:_startDependency];
- }
- return self;
-}
+ _queue = dispatch_queue_create("key-set-queue", DISPATCH_QUEUE_SERIAL);
-- (instancetype)initWithZoneName:(NSString*)zoneName keySet:(CKKSCurrentKeySet*)set
-{
- if((self = [super init])) {
- _zoneName = zoneName;
- _keyset = set;
- _startDependency = nil;
+ [self addDependency:_startDependency];
}
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
#if OCTAGON
#import "CKKSRateLimiter.h"
-#import <utilities/debugging.h>
#import <TargetConditionals.h>
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],
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);
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);
}
}];
_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;
#import <CloudKit/CloudKit.h>
#import <Foundation/Foundation.h>
#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 <OctagonStateTransitionOperationProtocol>
+@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
// 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;
NSError* error = nil;
bool newItems = false;
- NSArray<CKKSOutgoingQueueEntry*>* oqes = [CKKSOutgoingQueueEntry allInState: SecCKKSStateReencrypt zoneID:ckks.zoneID error:&error];
+ NSArray<CKKSOutgoingQueueEntry*>* 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];
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;
continue;
}
- ckksnotice("ckksreencrypt", ckks, "Reencrypting item %@", oqe);
+ ckksnotice("ckksreencrypt", self.deps.zoneID, "Reencrypting item %@", oqe);
NSDictionary* item = [CKKSItemEncrypter decryptItemToDictionary: oqe.item 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;
}
// 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 = [CKKSKey fromDatabase: 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 = [CKKSKey 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;
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;
[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;
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;
}];
}
@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;
#import "keychain/ckks/CKKSCondition.h"
#import "keychain/categories/NSError+UsefulConstructors.h"
#import "keychain/ot/ObjCImprovements.h"
-#include <utilities/debugging.h>
+#import "keychain/ckks/CKKS.h"
@interface CKKSResultOperation()
@property NSMutableArray<CKKSResultOperation*>* successDependencies;
[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;
}
// 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];
- (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
authenticatedData:(NSDictionary<NSString*, NSData*>* _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
}
- (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];
return self;
}
++ (CKKSWrappedAESSIVKey*)zeroedKey
+{
+ NSData* zeroedData = [NSMutableData dataWithLength:CKKSWrappedKeySize];
+ return [[CKKSWrappedAESSIVKey alloc] initWithData:zeroedData];
+}
+
@end
@implementation CKKSAESSIVKey
return localerror == NULL;
}
+- (NSData*)keyMaterial
+{
+ return [NSData _newZeroingDataWithBytes:self->key length:self->size];
+}
+
@end
- (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 <NSCopying>
@property (copy) NSDictionary<NSString*, NSString*>* originalSelfWhereClause;
+ (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
+ (instancetype)op:(CKKSSQLWhereComparator)op value:(NSString*)value;
@end
+@interface CKKSSQLWhereIn : NSObject
+@property NSArray<NSString*>* values;
+- (instancetype)initWithValues:(NSArray<NSString*>*)values;
+@end
+
NS_ASSUME_NONNULL_END
#import <Foundation/Foundation.h>
#import "CKKSSQLDatabaseObject.h"
#include "keychain/securityd/SecItemServer.h"
+#include "keychain/securityd/SecItemDb.h"
#import "keychain/ckks/CKKS.h"
#import "CKKSKeychainView.h"
}
@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];
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];
}
+ (void)bindWhereClause:(sqlite3_stmt*)stmt whereDict:(NSDictionary*)whereDict cferror:(CFErrorRef*)cferror
{
- __block int whereObjectsSkipped = 0;
+ __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, (int)(i+1-whereObjectsSkipped), (__bridge CFStringRef)obj.value, cferror);
+ SecDbBindObject(stmt, whereLocation, (__bridge CFStringRef)obj.value, cferror);
+ whereLocation++;
+
} else if([whereDict[key] class] == [CKKSSQLWhereColumn class]) {
// skip
- whereObjectsSkipped += 1;
+ } 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, (int)(i+1-whereObjectsSkipped), (__bridge CFStringRef) whereDict[key], cferror);
+ 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];
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 {
}
@end
+
+#pragma mark - CKKSSQLWhereIn
+
+@implementation CKKSSQLWhereIn : NSObject
+- (instancetype)initWithValues:(NSArray<NSString*>*)values
+{
+ if((self = [super init])) {
+ _values = values;
+ }
+ return self;
+}
+@end
/*
- * Copyright (c) 2016 Apple Inc. All Rights Reserved.
+ * Copyright (c) 2016-2020 Apple Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#import <Foundation/Foundation.h>
-#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
-@property CKOperationGroup* ckoperationGroup;
+@interface CKKSScanLocalItemsOperation : CKKSResultOperation <OctagonStateTransitionOperationProtocol>
+@property (nullable) CKOperationGroup* ckoperationGroup;
+@property CKKSOperationDependencies* deps;
@property (weak) CKKSKeychainView* ckks;
@property size_t recordsFound;
@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
*/
#if OCTAGON
-#import <TrustedPeers/TPPolicy.h>
+#import <TrustedPeers/TPSyncingPolicy.h>
#import <TrustedPeers/TPPBPolicyKeyViewMapping.h>
#import <TrustedPeers/TPDictionaryMatchingRules.h>
#import "keychain/ckks/CKKSGroupOperation.h"
#import "keychain/ckks/CKKSKey.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"
@interface CKKSScanLocalItemsOperation ()
@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;
}
-// returns true if the currently loaded TPPolicy in the view manager says that only items with a VewHint
-// matching the viewName belong to this view.
-- (BOOL)policyRecommendsOnlyViewHintItems:(CKKSKeychainView*)ckks
-{
- // Early-exit for when feature is not on:
- if(![[CKKSViewManager manager] useCKKSViewsFromPolicy]) {
- return YES;
- }
-
+- (NSDictionary*)queryPredicatesForViewMapping {
TPPBPolicyKeyViewMapping* viewRule = nil;
- // If there's more than one rule matching this view, then exit with NO.
+ // 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:ckks.zoneName]) {
+ 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", ckks, "Too many policy rules for view %@", ckks.zoneName);
- return NO;
+ ckksnotice("ckksscan", self.deps.zoneID, "Too many policy rules for view %@", self.deps.zoneID.zoneName);
+ return @{};
}
}
}
!viewRule.matchingRule.hasNot &&
!viewRule.matchingRule.hasExists &&
viewRule.matchingRule.hasMatch) {
- if([@"vwht" isEqualToString:viewRule.matchingRule.match.fieldName] &&
- [viewRule.matchingRule.match.regex isEqualToString:[NSString stringWithFormat:@"^%@$", ckks.zoneName]]) {
- return YES;
+ 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", ckks, "Policy view rule is not a match against viewhint: %@", viewRule);
+ ckksnotice("ckksscan", self.deps.zoneID, "Policy view rule is not a match against viewhint: %@", viewRule);
}
} else {
- ckksnotice("ckksscan", ckks, "Policy view rule is of unknown type: %@", viewRule);
+ ckksnotice("ckksscan", self.deps.zoneID, "Policy view rule is complex: %@", viewRule);
}
- return NO;
+ return @{};
}
-- (void) main {
- // Take a strong reference.
- CKKSKeychainView* ckks = self.ckks;
- if(!ckks) {
- ckkserror("ckksscan", ckks, "no CKKS object");
+- (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 error:(NSError**)error
+{
+ NSError* itemSaveError = nil;
+
+ CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry withItem:item
+ action:SecCKKSActionAdd
+ zoneID:self.deps.zoneID
+ 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<NSString*>*)uuids itemClass:(NSString*)itemClass databaseProvider:(id<CKKSDatabaseProviderProtocol>)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 {
+ 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 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<NSDictionary*>*)primaryKeys databaseProvider:(id<CKKSDatabaseProviderProtocol>)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;
+
+ 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 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;
+ });
- [ckks dispatchSyncWithAccountKeys: ^bool{
- if(self.cancelled) {
- ckksnotice("ckksscan", ckks, "CKKSScanLocalItemsOperation cancelled, quitting");
- return false;
+ 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<NSString*>*)mirrorUUIDs
+ ckks:(CKKSKeychainView*)ckks
+ databaseProvider:(id<CKKSDatabaseProviderProtocol>)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?
+ // <rdar://problem/36166435> 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<CKKSDatabaseProviderProtocol> databaseProvider = self.deps.databaseProvider;
+ CKKSKeychainView* ckks = self.ckks;
+
+ [self.deps.launch addEvent:@"scan-local-items"];
+
+ // A map of ItemClass -> Set of found UUIDs
+ NSMutableDictionary<NSString*, NSMutableSet<NSString*>*>* itemUUIDsNotYetInCKKS = [NSMutableDictionary dictionary];
+
+ // A list of primary keys of items that fit in this view, but have no UUIDs
+ NSMutableSet<NSDictionary*>* primaryKeysWithNoUUIDs = [NSMutableSet set];
+
+ // We want this set to be empty after scanning, or else the keychain (silently) dropped something on the floor
+ NSMutableSet<NSString*>* 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<NSString*>* mirrorUUIDs = [NSMutableSet setWithArray:[CKKSMirrorEntry allUUIDs:ckks.zoneID error:&error]];
+ [mirrorUUIDs addObjectsFromArray:[CKKSMirrorEntry allUUIDs:self.deps.zoneID error:&error]];
// 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;
}
- // As a performance optimization, if the current policy says that this view only includes items by viewhint,
- // add that to the query.
- BOOL limitToViewHint = [self policyRecommendsOnlyViewHintItems:ckks];
+ NSString* itemClass = (__bridge NSString*)(*class)->name;
NSMutableDictionary* queryAttributes = [
- @{(__bridge NSString*) kSecClass: (__bridge NSString*) (*class)->name,
- (__bridge NSString*) kSecReturnRef: @(YES),
- (__bridge NSString*) kSecAttrSynchronizable: @(YES),
- (__bridge NSString*) kSecAttrTombstone: @(NO),
+ @{(__bridge NSString*)kSecClass: itemClass,
+ (__bridge NSString*)kSecReturnRef: @(YES),
+ (__bridge NSString*)kSecAttrSynchronizable: @(YES),
+ (__bridge NSString*)kSecAttrTombstone: @(NO),
} mutableCopy];
- if(limitToViewHint) {
- queryAttributes[(__bridge NSString*)kSecAttrSyncViewHint] = ckks.zoneName;
- }
-
- ckksnotice("ckksscan", ckks, "Scanning all synchronizable %@ items(%@) for: %@", (__bridge NSString*)(*class)->name, self.name, queryAttributes);
-
- Query *q = query_create_with_limit( (__bridge CFDictionaryRef) queryAttributes, NULL, kSecMatchUnlimited, &cferror);
- bool ok = false;
+ NSDictionary* extraQueryPredicates = [self queryPredicatesForViewMapping];
+ [queryAttributes addEntriesFromDictionary:extraQueryPredicates];
- if(cferror) {
- ckkserror("ckksscan", ckks, "couldn't create query: %@", cferror);
- SecTranslateError(&error, cferror);
- self.error = error;
- continue;
- }
+ ckksnotice("ckksscan", self.deps.zoneID, "Scanning all synchronizable %@ items(%@) for: %@", itemClass, self.name, queryAttributes);
- ok = kc_with_dbt(true, &cferror, ^(SecDbConnectionRef dbt) {
- return SecDbItemQuery(q, NULL, dbt, &cferror, ^(SecDbItemRef item, bool *stop) {
- ckksnotice("ckksscan", ckks, "scanning item: %@", item);
+ [self executeQuery:queryAttributes readWrite:false error:&error block:^(SecDbItemRef item) {
+ ckksnotice("ckksscan", self.deps.zoneID, "scanning item: %@", item);
- self.processedItems += 1;
+ self.processedItems += 1;
- SecDbItemRef itemToSave = NULL;
-
- // First check: is this a tombstone? If so, skip with prejudice.
- if(SecDbItemIsTombstone(item)) {
- ckksinfo("ckksscan", ckks, "Skipping tombstone %@", item);
- return;
- }
+ // First check: is this a tombstone? If so, skip with prejudice.
+ if(SecDbItemIsTombstone(item)) {
+ ckksinfo("ckksscan", self.deps.zoneID, "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;
- }
+ // 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: 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;
- }
+ // 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, 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);
+ // Fourth check: does this item have a UUID? If not, mark for later onboarding.
+ CFErrorRef cferror = NULL;
- } 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);
- }
+ 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);
- // Hurray, we can help!
- self.recordsFound += 1;
+ NSMutableDictionary* primaryKey = [(NSDictionary*)CFBridgingRelease(SecDbItemCopyPListWithMask(item, kSecDbPrimaryKeyFlag, &cferror)) mutableCopy];
- CKKSOutgoingQueueEntry* oqe = [CKKSOutgoingQueueEntry withItem: itemToSave action: SecCKKSActionAdd ckks:ckks error: &error];
+ // Class is an important part of a primary key, SecDb
+ primaryKey[(id)kSecClass] = itemClass;
- if(error) {
- ckkserror("ckksscan", ckks, "Need to upload %@, but can't create outgoing entry: %@", item, error);
+ 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;
- CFReleaseNull(itemToSave);
return;
}
- ckksnotice("ckksscan", ckks, "Syncing new item: %@", oqe);
- CFReleaseNull(itemToSave);
+ [primaryKeysWithNoUUIDs addObject:primaryKey];
+ return;
+ }
- [oqe saveToDatabase: &error];
- if(error) {
- ckkserror("ckksscan", ckks, "Need to upload %@, but can't save to database: %@", oqe, error);
- self.error = error;
+ // 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]) {
+ // Fair enough.
return;
+ } else {
+ ckksnotice("ckksscan", self.deps.zoneID, "Existing mirror entry with UUID %@ does not match local item", uuid);
}
- 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;
- }
+ // 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;
+ }
- ok = query_notify_and_destroy(q, ok, &cferror);
+ // Hurray, we can help!
+ ckksnotice("ckksscan", self.deps.zoneID, "Item(%@) is new; will attempt to add to CKKS", uuid);
+ self.recordsFound += 1;
- if(cferror || !ok) {
- ckkserror("ckksscan", ckks, "couldn't delete query: %@", cferror);
- SecTranslateError(&error, cferror);
- self.error = error;
- continue;
- }
+ NSMutableSet<NSString*>* classUUIDs = itemUUIDsNotYetInCKKS[itemClass];
+ if(!classUUIDs) {
+ classUUIDs = [NSMutableSet set];
+ itemUUIDsNotYetInCKKS[itemClass] = classUUIDs;
+ }
+ [classUUIDs addObject:uuid];
+ }];
}
- // We're done checking local keychain for extra items, now let's make sure the mirror doesn't have extra items, either
+ // 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", 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]]];
+ 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, "unable to inspect incoming queue: %@", error);
+ ckkserror("ckksscan", self.deps.zoneID, "unable to inspect incoming queue: %@", error);
self.error = error;
- return false;
+ return;
}
- [mirrorUUIDs minusSet:[NSSet setWithArray:[CKKSOutgoingQueueEntry allUUIDs:ckks.zoneID error:&error]]];
+ [mirrorUUIDs minusSet:[NSSet setWithArray:[CKKSOutgoingQueueEntry allUUIDs:self.deps.zoneID error:&error]]];
if (error) {
- ckkserror("ckksscan", ckks, "unable to inspect outgoing queue: %@", error);
+ ckkserror("ckksscan", self.deps.zoneID, "unable to inspect outgoing queue: %@", error);
self.error = error;
- return false;
+ return;
}
+ }
- 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;
+ // Drop off of read-only transaction
+ }];
- [[CKKSAnalytics logger] logMetric:[NSNumber numberWithUnsignedInteger:mirrorUUIDs.count] withName:CKKSEventMissingLocalItemsFound];
+ if(self.error) {
+ ckksnotice("ckksscan", self.deps.zoneID, "Exiting due to previous error: %@", self.error);
+ return;
+ }
- for (NSString* uuid in mirrorUUIDs) {
- CKKSMirrorEntry* ckme = [CKKSMirrorEntry tryFromDatabase:uuid zoneID:ckks.zoneID error:&error];
- [ckks _onqueueCKRecordChanged:ckme.item.storedCKRecord resync:true];
- }
+ ckksnotice("ckksscan", self.deps.zoneID, "Found %d item classes with missing items", (int)itemUUIDsNotYetInCKKS.count);
- // And, if you're not in the tests, try to collect a sysdiagnose I guess?
- // <rdar://problem/36166435> 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");
- }
- }
+ for(NSString* itemClass in [itemUUIDsNotYetInCKKS allKeys]) {
+ [self onboardItemsWithUUIDs:itemUUIDsNotYetInCKKS[itemClass] itemClass:itemClass databaseProvider:databaseProvider];
+ }
- [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventScanLocalItems zone:ckks.zoneName count:self.processedItems];
+ [self fixUUIDlessItemsWithPrimaryKeys:primaryKeysWithNoUUIDs databaseProvider:databaseProvider];
- 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;
- }
+ [self retriggerMissingMirrorEntires:mirrorUUIDs
+ ckks:ckks
+ databaseProvider:databaseProvider];
- [manifest saveToDatabase:&error];
- if (error) {
- ckkserror("ckksscan", ckks, "could not save manifest to database: %@", error);
- self.error = error;
- return false;
- }
+ [CKKSPowerCollection CKKSPowerEvent:kCKKSPowerEventScanLocalItems zone:self.deps.zoneID.zoneName count:self.processedItems];
- ckks.egoManifest = manifest;
- }
+ // Write down that a scan occurred
+ [databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{
+ CKKSZoneStateEntry* zoneState = [CKKSZoneStateEntry state:self.deps.zoneID.zoneName];
- if(newEntries) {
- // Schedule a "view changed" notification
- [ckks.notifyViewChangedScheduler trigger];
+ zoneState.lastLocalKeychainScanTime = [NSDate now];
- // notify CKKS that it should process these new entries
- [ckks processOutgoingQueue:self.ckoperationGroup];
- }
+ NSError* saveError = nil;
+ [zoneState saveToDatabase:&saveError];
- if(self.missingLocalItemsFound > 0) {
- [ckks processIncomingQueue:false];
+ if(saveError) {
+ ckkserror("ckksscan", self.deps.zoneID, "Unable to save 'scanned' bit: %@", saveError);
+ } else {
+ ckksnotice("ckksscan", self.deps.zoneID, "Saved scanned status.");
}
- ckksnotice("ckksscan", ckks, "Completed scan");
- ckks.droppedItems = false;
- return true;
+ 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
{
- CKKSKeychainView* ckks = self.ckks;
-
NSError* localerror = nil;
NSDictionary* attributes = [CKKSIncomingQueueOperation decryptCKKSItemToAttributes:ckksItem 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;
}
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;
--- /dev/null
+
+#if OCTAGON
+
+#import <Foundation/Foundation.h>
+#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 CKKSFlagProcessIncomingQueue;
+extern CKKSFlag* const CKKSFlagProcessOutgoingQueue;
+extern CKKSFlag* const CKKSFlagScanLocalItems;
+extern CKKSFlag* const CKKSFlagItemReencryptionNeeded;
+
+extern CKKSFlag* const CKKSFlag24hrNotification;
+
+NSSet<CKKSFlag*>* CKKSAllStateFlags(void);
+
+NS_ASSUME_NONNULL_END
+
+#endif
--- /dev/null
+
+#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 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<CKKSFlag*>* CKKSAllStateFlags(void)
+{
+ static NSSet<CKKSFlag*>* 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,
+ ]];
+ });
+ return s;
+}
+
+#endif
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;
[self runBeforeGroupFinished: fetchOp];
// Step 2
- CKKSIncomingQueueOperation* incomingOp = [[CKKSIncomingQueueOperation alloc] initWithCKKSKeychainView:ckks errorOnClassAFailure:true];
+ CKKSIncomingQueueOperation* incomingOp = [[CKKSIncomingQueueOperation alloc] initWithDependencies:ckks.operationDependencies
+ ckks:ckks
+ 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];
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];
[restart addExecutionBlock:^{
STRONGIFY(self);
if(!self) {
- secerror("ckksresync: received callback for released object");
+ ckkserror("ckksresync", ckks, "received callback for released object");
return;
}
[restart addSuccessDependency: outgoingOp];
[self runBeforeGroupFinished: restart];
- return true;
+ return CKKSDatabaseTransactionCommit;
}];
}
- (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
- (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
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
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) {
- (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"];
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;
}
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;
}
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;
}
WEAKIFY(self);
- [ckks dispatchSyncWithAccountKeys:^bool {
+ [ckks dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{
if(self.cancelled) {
ckksnotice("ckkscurrent", ckks, "CKKSUpdateCurrentItemPointerOperation cancelled, quitting");
- return false;
+ return CKKSDatabaseTransactionRollback;
}
NSError* error = nil;
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.
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
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)));
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;
}
}
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];
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;
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
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!
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);
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";
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];
__block NSError* error = nil;
- [strongCKKS dispatchSync: ^bool{
+ [strongCKKS dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{
for(CKRecord* record in savedRecords) {
// Save the item records
if([record.recordType isEqualToString: SecCKRecordCurrentItemType]) {
// Schedule a 'view changed' notification
[strongCKKS.notifyViewChangedScheduler trigger];
}
- return true;
+ return CKKSDatabaseTransactionCommit;
}];
self.error = error;
[self dependOnBeforeGroupFinished: self.modifyRecordsOperation];
[ckks.database 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;
},
NULL,
1,
+ NULL,
&blockcfError);
if(blockcfError || !q) {
ckkserror("ckkscurrent", ckks, "couldn't create query for item persistentRef: %@", blockcfError);
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) {
self.error = [NSError errorWithDomain:@"securityd"
code:errSecInternalError
userInfo:@{NSLocalizedDescriptionKey: @"Rate-limited the CKKSUpdateDeviceStateOperation"}];
- return false;
+ return CKKSDatabaseTransactionRollback;
}
}
__block NSError* error = nil;
- [strongCKKS dispatchSync: ^bool{
+ [strongCKKS dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{
for(CKRecord* record in savedRecords) {
// Save the item records
if([record.recordType isEqualToString: SecCKRecordDeviceStateType]) {
}
}
}
- return true;
+ return CKKSDatabaseTransactionCommit;
}];
self.error = error;
[self dependOnBeforeGroupFinished: self.modifyRecordsOperation];
[ckks.database addOperation: self.modifyRecordsOperation];
- return true;
+ return CKKSDatabaseTransactionCommit;
}];
}
#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 <CKKSControlProtocol>
@property id<OTSOSAdapter> sosPeerAdapter;
-@property (readonly, nullable) TPPolicy* policy;
+@property (readonly, nullable) TPSyncingPolicy* policy;
@property (readonly) NSMutableDictionary<NSString*, CKKSKeychainView*>* views;
lockStateTracker:(CKKSLockStateTracker*)lockStateTracker
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<CKKSKeychainView*>*)currentViews;
-- (NSDictionary<NSString*, NSString*>*)activeTLKs;
-
- (void)setupAnalytics;
- (NSString* _Nullable)viewNameForItem:(SecDbItemRef)item;
// 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.
-- (void)setSyncingViews:(NSSet<NSString*>* _Nullable)viewNames sortingPolicy:(TPPolicy* _Nullable)policy;
+- (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;
// 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<CKKSKeychainBackedKey*>* _Nullable)currentTLKsFilteredByPolicy:(BOOL)restrictToPolicy error:(NSError**)error;
+
// Interfaces to examine sync callbacks
-- (SecBoolNSErrorCallback _Nullable)claimCallbackForUUID:(NSString*)uuid;
+- (SecBoolNSErrorCallback _Nullable)claimCallbackForUUID:(NSString* _Nullable)uuid;
- (NSSet<NSString*>*)pendingCallbackUUIDs;
+ (void)callSyncCallbackWithErrorNoAccount:(SecBoolNSErrorCallback)syncCallback;
@end
#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"
#import "keychain/ot/OTConstants.h"
#import "keychain/ot/ObjCImprovements.h"
-#import "TPPolicy.h"
+#import "keychain/trust/TrustedPeers/TPSyncingPolicy.h"
#import "SecEntitlements.h"
@property BOOL itemModificationsBeforePolicyLoaded;
// Make writable
-@property (nullable) TPPolicy* policy;
+@property (nullable) TPSyncingPolicy* policy;
+@property CKKSCondition* policyLoaded;
#endif
@end
_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
}];
_policy = nil;
+ _policyLoaded = [[CKKSCondition alloc] init];
_listener = [NSXPCListener anonymousListener];
_listener.delegate = self;
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];
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];
[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 */
+ 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;
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) {
return [self.views.allKeys copy];
}
-- (void)setSyncingViews:(NSSet<NSString*>*)viewNames sortingPolicy:(TPPolicy*)policy
+- (BOOL)setCurrentSyncingPolicy:(TPSyncingPolicy* _Nullable)syncingPolicy
{
- secnotice("ckks-policy", "New syncing policy: %@ views: %@", policy, viewNames);
+ 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<NSString*>* viewNames = syncingPolicy.viewList;
+ ckksnotice_global("ckks-policy", "New syncing policy: %@ views: %@", syncingPolicy, viewNames);
if(![self useCKKSViewsFromPolicy]) {
// Thanks, but no thanks.
viewNames = [self defaultViewList];
- secnotice("ckks-policy", "Reverting to default view list: %@", viewNames);
+ ckksnotice_global("ckks-policy", "Reverting to default view list: %@", viewNames);
}
if(self.viewAllowList) {
- secnotice("ckks-policy", "Intersecting view list with allow list: %@", self.viewAllowList);
+ ckksnotice_global("ckks-policy", "Intersecting view list with allow list: %@", self.viewAllowList);
NSMutableSet<NSString*>* set = [viewNames mutableCopy];
[set intersectSet:self.viewAllowList];
viewNames = set;
- secnotice("ckks-policy", "Final list: %@", viewNames);
+ ckksnotice_global("ckks-policy", "Final list: %@", viewNames);
}
- self.policy = policy;
+ // 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<CKKSKeychainView*>* 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]) {
- secnotice("ckks-policy", "Stopping old view %@", 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]) {
- CKKSKeychainView* view = [self findView:viewName];
- secnotice("ckks-policy", "Already have view %@", view);
+ view = [self findView:viewName];
+ ckksinfo_global("ckks-policy", "Already have view %@", view);
+
} else {
- CKKSKeychainView* view = [self findOrCreateView:viewName];
- secnotice("ckks-policy", "Created new view %@", view);
+ view = [self findOrCreateView:viewName];
+ ckksnotice_global("ckks-policy", "Created new view %@", view);
+ viewsChanged = YES;
}
}
+ activeViews = [self.views.allValues copy];
+
if(self.itemModificationsBeforePolicyLoaded) {
- secnotice("ckks-policy", "Issuing scan suggestions to handle missed items");
- for(CKKSKeychainView* view in [self.views allValues]) {
- [view scanLocalItems:@"item-added-before-policy"];
- }
+ 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"];
+ }
+ }
+
+ // The policy is considered loaded once the views have been created
+ [self.policyLoaded fulfill];
+ return viewsChanged;
}
- (void)setSyncingViewsAllowList:(NSSet<NSString*>*)viewNames
- (void)resetSyncingPolicy
{
- secnotice("ckks-policy", "Setting policy to nil");
+ ckksnotice_global("ckks-policy", "Setting policy to nil");
self.policy = nil;
+ self.policyLoaded = [[CKKSCondition alloc] init];
self.startCKOperationAtViewCreation = NO;
}
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];
(void)view;
}
} else {
- secnotice("ckks-views", "Not loading default view list due to enabled CKKS4All");
+ ckksnotice_global("ckks-views", "Not loading default view list due to enabled CKKS4All");
}
}
}
}
-- (NSDictionary<NSString *,NSString *> *)activeTLKs
-{
- NSMutableDictionary<NSString *,NSString *> *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;
- }
- }
- }
- return tlks;
-}
-
- (void)haltZone:(NSString*)viewName
{
@synchronized(self.views) {
- (CKKSKeychainView*)restartZone:(NSString*)viewName {
[self haltZone:viewName];
- return [self findOrCreateView: viewName];
+ CKKSKeychainView* view = [self findOrCreateView: viewName];
+
+ [view setCurrentSyncingPolicy:self.policy policyIsFresh:NO];
+
+ return view;
}
- (NSString*)viewNameForViewHint: (NSString*) viewHint {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
- secnotice("ckks", "ViewsFromPolicy feature flag: %@", viewsFromPolicy ? @"on" : @"off");
+ ckksnotice_global("ckks", "ViewsFromPolicy feature flag: %@", viewsFromPolicy ? @"on" : @"off");
});
return viewsFromPolicy;
}
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 nil;
}
- NSString* view = [self.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) {
- secerror("ckks: No view returned from policy (%@): %@", self.policy, dict);
+ ckkserror_global("ckks", "No view returned from policy (%@): %@", self.policy, item);
return nil;
}
- // Horrible hack until <rdar://problem/57810109> Cuttlefish: remove Safari prefix from view names
- if([view isEqualToString:@"CreditCards"]) {
- return @"SafariCreditCards";
- }
- if([view isEqualToString:@"Passwords"]) {
- return @"SafariPasswords";
- }
-
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;
}
- (void)registerSyncStatusCallback: (NSString*) uuid callback: (SecBoolNSErrorCallback) callback {
// Someone is requesting future notification of this item.
@synchronized(self.pendingSyncCallbacks) {
- secnotice("ckkscallback", "registered callback for UUID: %@", uuid);
+ ckksnotice_global("ckkscallback", "registered callback for UUID: %@", uuid);
self.pendingSyncCallbacks[uuid] = callback;
}
}
-- (SecBoolNSErrorCallback _Nullable)claimCallbackForUUID:(NSString*)uuid
+- (SecBoolNSErrorCallback _Nullable)claimCallbackForUUID:(NSString* _Nullable)uuid
{
+ if(!uuid) {
+ return nil;
+ }
+
@synchronized(self.pendingSyncCallbacks) {
SecBoolNSErrorCallback callback = self.pendingSyncCallbacks[uuid];
if(callback) {
- secerror("ckkscallback : fetched UUID: %@", uuid);
+ ckksnotice_global("ckkscallback", "fetched UUID: %@", uuid);
}
self.pendingSyncCallbacks[uuid] = nil;
} else {
@synchronized(self.pendingSyncCallbacks) {
if(self.pendingSyncCallbacks.count > 0) {
- secnotice("ckkscallback", "No CK account; failing all pending sync callbacks");
+ ckksnotice_global("ckkscallback", "No CK account; failing all pending sync callbacks");
for(NSString* uuid in [self.pendingSyncCallbacks allKeys]) {
[CKKSViewManager callSyncCallbackWithErrorNoAccount:self.pendingSyncCallbacks[uuid]];
if(!addedSync && !deletedSync) {
// Local-only change. Skip with prejudice.
- secinfo("ckks", "skipping sync of non-sync item (%d, %d)", addedSync, deletedSync);
+ ckksinfo_global("ckks", "skipping sync of non-sync item (%d, %d)", addedSync, deletedSync);
return;
}
@synchronized(self.views) {
if([self useCKKSViewsFromPolicy] && !self.policy) {
- secerror("ckks: No policy configured(%@). Skipping item: %@", self.policy, modified);
+ ckkserror_global("ckks", "No policy configured(%@). Skipping item: %@", self.policy, modified);
self.itemModificationsBeforePolicyLoaded = YES;
return;
}
-
- viewName = [self viewNameForItem:modified];
}
+ viewName = [self viewNameForItem:modified];
+
if(!viewName) {
- secnotice("ckks", "No intended CKKS view for item; skipping: %@", modified);
+ ckksnotice_global("ckks", "No intended CKKS view for item; skipping: %@", modified);
return;
}
CKKSKeychainView* view = [self findView:viewName];
if(!view) {
- secnotice("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];
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;
}
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;
}
-(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];
}
SOSAccount* account = (__bridge SOSAccount*)SOSKeychainAccountGetSharedAccount();
if(!account) {
- secnotice("ckks", "Failed to get account object");
+ ckksnotice_global("ckks", "Failed to get account object");
return;
}
(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<CKKSKeychainBackedKey*>* _Nullable)currentTLKsFilteredByPolicy:(BOOL)restrictToPolicy error:(NSError**)error
+{
+ NSError* localError = nil;
+ NSArray<CKKSKeychainView*>* 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<CKKSResultOperation<CKKSKeySetProviderOperationProtocol>*>* keyFetchOperations = [NSMutableArray array];
+ for (CKKSKeychainView* view in actualViews) {
+ if(restrictToPolicy && [self useCKKSViewsFromPolicy] && ![self.policy.viewsToPiggybackTLKs containsObject:view.zoneName]) {
+ continue;
+ }
+
+ CKKSResultOperation<CKKSKeySetProviderOperationProtocol>* op = [view findKeySet:NO];
+ [op timeout:10*NSEC_PER_SEC];
+ [keyFetchOperations addObject:op];
+ }
+
+ NSMutableArray<CKKSKeychainBackedKey*>* tlks = [NSMutableArray array];
+
+ for(CKKSResultOperation<CKKSKeySetProviderOperationProtocol>* 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 <NSString *, NSNumber *> *counter))reply {
}
- (NSArray<CKKSKeychainView*>*)views:(NSString*)viewName operation:(NSString*)opName error:(NSError**)error
+{
+ return [self views:viewName operation:opName errorOnPolicyMissing:YES error:error];
+}
+
+- (NSArray<CKKSKeychainView*>*)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]]];
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));
}];
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;
}
[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));
}];
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;
}
// 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));
}];
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;
}
// 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));
}];
{
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;
// 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");
+ 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:5*NSEC_PER_SEC];
+ [view.stateMachine registerMultiStateArrivalWatcher:waitForTransient];
+
+ [statusOp addDependency:waitForTransient.result];
}
- [statusOp addDependency:blockOp];
- [self.operationQueue addOperation:blockOp];
}
[self.operationQueue addOperation:statusOp];
}];
[[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"];
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
+++ /dev/null
-/*
- * 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 <Foundation/Foundation.h>
-
-#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 <CKKSZoneUpdateReceiver, CKKSCloudKitAccountStateListener>
-{
- 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
+++ /dev/null
-/*
- * 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 <AssertMacros.h>
-
-#import <Foundation/Foundation.h>
-
-#if OCTAGON
-#import "CloudKitDependencies.h"
-#import "keychain/ckks/CKKSAccountStateTracker.h"
-#import "keychain/ckks/CloudKitCategories.h"
-#import "keychain/categories/NSError+UsefulConstructors.h"
-#import <CloudKit/CloudKit.h>
-#import <CloudKit/CloudKit_Private.h>
-
-#import "keychain/ot/ObjCImprovements.h"
-
-#import "CKKSKeychainView.h"
-#import "CKKSZone.h"
-
-#include <utilities/debugging.h>
-
-@interface CKKSZone()
-
-@property CKDatabaseOperation<CKKSModifyRecordZonesOperation>* zoneCreationOperation;
-@property CKDatabaseOperation<CKKSModifyRecordZonesOperation>* zoneDeletionOperation;
-@property CKDatabaseOperation<CKKSModifySubscriptionsOperation>* zoneSubscriptionOperation;
-
-@property NSOperationQueue* operationQueue;
-@property CKKSResultOperation* accountLoggedInDependency;
-
-@property NSHashTable<NSOperation*>* 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];
-
- // And now, wait for all operations that are running
- for(NSOperation* op in self.operationQueue.operations) {
- if(op.isExecuting) {
- [op waitUntilFinished];
- }
- }
-}
-
-@end
-
-#endif /* OCTAGON */
-
#import <Foundation/Foundation.h>
#import "keychain/ckks/CKKSResultOperation.h"
#import "keychain/ckks/CKKSFetchAllRecordZoneChangesOperation.h"
+#import "keychain/ckks/OctagonAPSReceiver.h"
NS_ASSUME_NONNULL_BEGIN
@class CKKSReachabilityTracker;
@class CKKSNearFutureScheduler;
-@interface CKKSZoneChangeFetcher : NSObject
+@interface CKKSZoneChangeFetcher : NSObject <CKKSZoneUpdateReceiverProtocol>
@property (readonly) Class<CKKSFetchRecordZoneChangesOperation> fetchRecordZoneChangesOperationClass;
@property (readonly) CKContainer* container;
@property CKKSReachabilityTracker* reachabilityTracker;
- (CKKSResultOperation*)requestSuccessfulFetch:(CKKSFetchBecause*)why;
- (CKKSResultOperation*)requestSuccessfulFetchForManyReasons:(NSSet<CKKSFetchBecause*>*)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;
@property bool newRequests; // true if there's someone pending on successfulFetchDependency
@property CKKSZoneChangeFetchDependencyOperation* successfulFetchDependency;
+@property (nullable) CKKSZoneChangeFetchDependencyOperation* inflightFetchDependency;
+
@property CKKSResultOperation* holdOperation;
@end
_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);
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;
for(id<CKKSChangeFetcherClient> client in clients) {
if([client zoneIsReadyForFetching]) {
notReady = NO;
+ break;
}
}
[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;
});
if (notReady) {
- secnotice("ckksfetch", "Skipping fetching size no zone is ready");
+ ckksnotice_global("ckksfetch", "Skipping fetching size no zone is ready");
return NULL;
}
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.newRequests &&
WEAKIFY(self);
CKKSZoneChangeFetchDependencyOperation* dependency = self.successfulFetchDependency;
+ self.inflightFetchDependency = dependency;
+
NSMutableSet<CKKSFetchBecause*>* 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<CKRecordZoneNotification*>* lastAPNSPushes = self.apnsPushes;
self.apnsPushes = [[NSMutableSet alloc] init];
NSArray<id<CKKSChangeFetcherClient>> *clients = [self clients];
if(clients.count == 0u) {
- secnotice("ckksfetcher", "No clients");
+ ckksnotice_global("ckksfetcher", "No clients");
// Nothing to do, really.
}
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];
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) {
[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
#import "keychain/ckks/CKKSReachabilityTracker.h"
#import "keychain/ckks/CKKSZoneModifier.h"
-#import "utilities/debugging.h"
#import "keychain/ot/ObjCImprovements.h"
@implementation CKKSZoneModifyOperations
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
{
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:^{
- (CKDatabaseOperation<CKKSModifyRecordZonesOperation>*)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<CKKSModifyRecordZonesOperation>* zoneModifyOperation = [[self.cloudKitClassDependencies.modifyRecordZonesOperationClass alloc] initWithRecordZonesToSave:ops.zonesToCreate recordZoneIDsToDelete:ops.zoneIDsToDelete];
[zoneModifyOperation linearDependencies:self.ckOperations];
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;
};
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];
}
- (CKDatabaseOperation<CKKSModifySubscriptionsOperation>* _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];
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;
[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];
}
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];
}
}
@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;
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;
changeToken:(NSData*)changetoken
moreRecordsInCloudKit:(BOOL)moreRecords
lastFetch:(NSDate*)lastFetch
+ lastScan:(NSDate* _Nullable)lastScan
lastFixup:(CKKSFixup)lastFixup
encodedRateLimiter:(NSData*)encodedRateLimiter
{
_encodedChangeToken = changetoken;
_moreRecordsInCloudKit = moreRecords;
_lastFetchTime = lastFetch;
+ _lastLocalKeychainScanTime = lastScan;
_lastFixup = lastFixup;
self.encodedRateLimiter = encodedRateLimiter;
((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;
}
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) {
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];
}
+ (NSArray<NSString*>*) 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<NSString*,NSString*>*) whereClauseToFindSelf {
- (NSDictionary<NSString*,id>*) 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<NSString*, CKKSSQLResult*>*)row {
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
];
if([cuttlefishError.domain isEqualToString:CuttlefishErrorDomain]) {
NSNumber* val = cuttlefishError.userInfo[CuttlefishErrorRetryAfterKey];
- if (val) {
+ if (val != nil) {
return (NSTimeInterval)val.doubleValue;
}
}
@property (nonatomic, copy) NSString *operationID;
@property (nonatomic, readonly, strong, nullable) CKOperationConfiguration *resolvedConfiguration;
+
+@property (nonatomic, strong) NSString *deviceIdentifier;
@end
@interface CKFetchRecordZoneChangesOperation () <CKKSFetchRecordZoneChangesOperation>
/* APSConnection */
@protocol OctagonAPSConnection <NSObject>
+@property NSArray<NSString*>* enabledTopics;
+@property NSArray<NSString*>* opportunisticTopics;
+@property NSArray<NSString*>* darkWakeTopics;
+
+ (instancetype)alloc;
- (id)initWithEnvironmentName:(NSString*)environmentName
namedDelegatePort:(NSString*)namedDelegatePort
queue:(dispatch_queue_t)queue;
-- (void)setEnabledTopics:(NSArray<NSString *> *)enabledTopics;
-- (void)setDarkWakeTopics:(NSArray<NSString *> *)darkWakeTopics;
@property (nonatomic, readwrite, assign) id<APSConnectionDelegate> delegate;
@end
*/
#import <Foundation/Foundation.h>
+#import "keychain/ckks/CKKS.h"
#import "keychain/ckks/NSOperationCategories.h"
#import "keychain/ot/ObjCImprovements.h"
-#import "utilities/debugging.h"
@implementation NSOperation (CKKSUsefulPrintingOperation)
- (NSString*)selfname {
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];
}
@property (nonatomic, strong, nullable) NSDate* ckksPushReceivedDate;
@end
-@protocol CKKSZoneUpdateReceiver <NSObject>
+@protocol CKKSZoneUpdateReceiverProtocol <NSObject>
- (void)notifyZoneChange:(CKRecordZoneNotification* _Nullable)notification;
@end
@property (readonly) BOOL haveStalePushes;
-+ (instancetype)receiverForEnvironment:(NSString*)environmentName
- namedDelegatePort:(NSString*)namedDelegatePort
- apsConnectionClass:(Class<OctagonAPSConnection>)apsConnectionClass;
++ (instancetype)receiverForNamedDelegatePort:(NSString*)namedDelegatePort
+ apsConnectionClass:(Class<OctagonAPSConnection>)apsConnectionClass;
++ (void)resetGlobalDelegatePortMap;
-- (CKKSCondition*)registerReceiver:(id<CKKSZoneUpdateReceiver>)receiver forZoneID:(CKRecordZoneID*)zoneID;
+- (void)registerForEnvironment:(NSString*)environmentName;
+
+- (CKKSCondition*)registerCKKSReceiver:(id<CKKSZoneUpdateReceiverProtocol>)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<OctagonCuttlefishUpdateReceiver>)receiver forContainerName:(NSString*)containerName;
// Test support:
-- (instancetype)initWithEnvironmentName:(NSString*)environmentName
- namedDelegatePort:(NSString*)namedDelegatePort
+- (instancetype)initWithNamedDelegatePort:(NSString*)namedDelegatePort
apsConnectionClass:(Class<OctagonAPSConnection>)apsConnectionClass;
-- (instancetype)initWithEnvironmentName:(NSString*)environmentName
- namedDelegatePort:(NSString*)namedDelegatePort
+- (instancetype)initWithNamedDelegatePort:(NSString*)namedDelegatePort
apsConnectionClass:(Class<OctagonAPSConnection>)apsConnectionClass
stalePushTimeout:(uint64_t)stalePushTimeout;
+
// This is the queue that APNS will use send the notifications to us
+ (dispatch_queue_t)apsDeliveryQueue;
+- (NSArray<NSString *>*)registeredPushEnvironments;
@end
@interface OctagonAPSReceiver (Testing)
-+ (void)resetGlobalEnviornmentMap;
-- (void)reportDroppedPushes:(NSDictionary<NSString*, NSMutableSet<CKRecordZoneNotification*>*>*)notifications;
+- (void)reportDroppedPushes:(NSSet<CKRecordZoneNotification*>*)notifications;
@end
NS_ASSUME_NONNULL_END
#import "keychain/ot/ObjCImprovements.h"
#import <CloudKit/CloudKit_Private.h>
#include <utilities/SecAKSWrappers.h>
-#include <utilities/debugging.h>
@implementation CKRecordZoneNotification (CKKSPushTracing)
- (void)setCkksPushTracingEnabled:(BOOL)ckksPushTracingEnabled {
@property CKKSNearFutureScheduler *clearStalePushNotifications;
+@property NSString* namedDelegatePort;
+@property NSMutableDictionary<NSString*, id<OctagonAPSConnection>>* 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<NSString*, NSMutableSet<CKRecordZoneNotification*>*>* undeliveredUpdates;
+@property NSMutableSet<CKRecordZoneNotification*>* undeliveredUpdates;
// Same, but for cuttlefish containers (and only remember that a push was received; don't remember the pushes themselves)
@property NSMutableSet<NSString*>* undeliveredCuttlefishUpdates;
-@property NSMapTable<NSString*, id<CKKSZoneUpdateReceiver>>* zoneMap;
+@property (nullable) id<CKKSZoneUpdateReceiverProtocol> zoneUpdateReceiver;
@property NSMapTable<NSString*, id<OctagonCuttlefishUpdateReceiver>>* octagonContainerMap;
@end
@implementation OctagonAPSReceiver
-+ (instancetype)receiverForEnvironment:(NSString *)environmentName
- namedDelegatePort:(NSString*)namedDelegatePort
- apsConnectionClass:(Class<OctagonAPSConnection>)apsConnectionClass
++ (instancetype)receiverForNamedDelegatePort:(NSString*)namedDelegatePort
+ apsConnectionClass:(Class<OctagonAPSConnection>)apsConnectionClass
{
- if(environmentName == nil) {
- secnotice("octagonpush", "No push environment; not bringing up APS.");
- return nil;
- }
-
@synchronized([self class]) {
- NSMutableDictionary<NSString*, OctagonAPSReceiver*>* environmentMap = [self synchronizedGlobalEnvironmentMap];
+ NSMutableDictionary<NSString*, OctagonAPSReceiver*>* 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<NSString*, OctagonAPSReceiver*>*)synchronizedGlobalEnvironmentMap
++ (NSMutableDictionary<NSString*, OctagonAPSReceiver*>*)synchronizedGlobalDelegatePortMap
{
- return [self resettableSynchronizedGlobalEnvironmentMap:NO];
+ return [self resettableSynchronizedGlobalDelegatePortMap:NO];
}
-+ (NSMutableDictionary<NSString*, OctagonAPSReceiver*>*)resettableSynchronizedGlobalEnvironmentMap:(BOOL)reset
++ (NSMutableDictionary<NSString*, OctagonAPSReceiver*>*)resettableSynchronizedGlobalDelegatePortMap:(BOOL)reset
{
- static NSMutableDictionary<NSString*, OctagonAPSReceiver*>* environmentMap = nil;
+ static NSMutableDictionary<NSString*, OctagonAPSReceiver*>* delegatePortMap = nil;
- if(environmentMap == nil || reset) {
- environmentMap = [[NSMutableDictionary alloc] init];
+ if(delegatePortMap == nil || reset) {
+ delegatePortMap = [[NSMutableDictionary alloc] init];
}
- return environmentMap;
+ return delegatePortMap;
+}
+
+- (NSArray<NSString *>*)registeredPushEnvironments
+{
+ __block NSArray<NSString*>* environments = nil;
+ dispatch_sync([OctagonAPSReceiver apsDeliveryQueue], ^{
+ environments = [self.environmentMap allKeys];
+ });
+ return environments;
}
+ (dispatch_queue_t)apsDeliveryQueue {
return haveStalePushes;
}
-- (NSSet<NSString*>*)cuttlefishPushTopics
+- (NSArray<NSString*>*)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<OctagonAPSConnection>)apsConnectionClass
+- (instancetype)initWithNamedDelegatePort:(NSString*)namedDelegatePort
+ apsConnectionClass:(Class<OctagonAPSConnection>)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<OctagonAPSConnection>)apsConnectionClass
- stalePushTimeout:(uint64_t)stalePushTimeout
+- (instancetype)initWithNamedDelegatePort:(NSString*)namedDelegatePort
+ apsConnectionClass:(Class<OctagonAPSConnection>)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<NSString*, NSMutableSet<CKRecordZoneNotification*>*> *droppedUpdates;
+ NSMutableSet<CKRecordZoneNotification*> *droppedUpdates;
STRONGIFY(self);
if (self == nil) {
return;
droppedUpdates = self.undeliveredUpdates;
- self.undeliveredUpdates = [NSMutableDictionary dictionary];
+ self.undeliveredUpdates = [NSMutableSet set];
[self.undeliveredCuttlefishUpdates removeAllObjects];
[self reportDroppedPushes:droppedUpdates];
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<OctagonAPSConnection> 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<NSString*, NSMutableSet<CKRecordZoneNotification*>*>*)notifications
+- (void)reportDroppedPushes:(NSSet<CKRecordZoneNotification*>*)notifications
{
bool hasBeenUnlocked = false;
CFErrorRef error = NULL;
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<CKKSZoneUpdateReceiver>)receiver forZoneID:(CKRecordZoneID *)zoneID {
+- (CKKSCondition*)registerCKKSReceiver:(id<CKKSZoneUpdateReceiverProtocol>)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);
+
+ self.zoneUpdateReceiver = receiver;
- NSMutableSet<CKRecordZoneNotification*>* currentPendingMessages = self.undeliveredUpdates[zoneID.zoneName];
- [self.undeliveredUpdates removeObjectForKey:zoneID.zoneName];
+ NSMutableSet<CKRecordZoneNotification*>* 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];
}
dispatch_async([OctagonAPSReceiver apsDeliveryQueue], ^{
STRONGIFY(self);
if(!self) {
- secerror("octagon: received registration for released OctagonAPSReceiver");
+ ckkserror_global("octagonpush", "received registration for released OctagonAPSReceiver");
return;
}
[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];
}
- (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<NSString*>* 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) {
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];
}
[[CKKSAnalytics logger] setDateProperty:[NSDate date] forKey:CKKSAnalyticsLastCKKSPush];
// Find receiever in map
- id<CKKSZoneUpdateReceiver> recv = [self.zoneMap objectForKey:rznotification.recordZoneID.zoneName];
+ id<CKKSZoneUpdateReceiverProtocol> recv = self.zoneUpdateReceiver;
if(recv) {
[recv notifyZoneChange:rznotification];
} else {
- secerror("ckks: received push for unregistered zone: %@", rznotification);
- if(rznotification.recordZoneID) {
- NSMutableSet<CKRecordZoneNotification*>* 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);
}
}
*/
#import "RateLimiter.h"
-#import <utilities/debugging.h>
#import "sec_action.h"
+#import "keychain/ckks/CKKS.h"
#import <CoreFoundation/CFPreferences.h> // For clarity. Also included in debugging.h
@interface RateLimiter()
@implementation RateLimiter
- (instancetype)initWithConfig:(NSDictionary *)config {
- self = [super init];
- if (self) {
+ if ((self = [super init])) {
_config = config;
_assetType = nil;
[self reset];
if (!coder) {
return nil;
}
- self = [super init];
- if (self) {
+ if ((self = [super init])) {
_groups = [coder decodeObjectOfClasses:[NSSet setWithObjects: [NSArray class],
[NSMutableDictionary class],
[NSString class],
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);
// approved properties 'accessGroup' and 'uuid' and if the item doesn't have either it's sad times anyway.
// <rdar://problem/33434425> 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]
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],
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) {
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");
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;
- (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");
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");
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];
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");
// 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
// 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
// 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];
// 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]]);
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];
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");
+++ /dev/null
-/*
- * 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 <XCTest/XCTest.h>
-#import <CloudKit/CloudKit.h>
-#import <CloudKit/CloudKit_Private.h>
-
-#import <Security/SecureObjectSync/SOSViews.h>
-#import <utilities/SecFileLocations.h>
-#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"
-#import "keychain/ot/OTManager.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]];
-
- CKContainer* container = [CKKSViewManager makeCKContainer:SecCKKSContainerName usePCS:SecCKKSContainerUsePCS];
- CKKSAccountStateTracker* accountStateTracker = [[CKKSAccountStateTracker alloc] init:container
- nsnotificationCenterClass:cloudKitClassDependencies.nsnotificationCenterClass];
-
- CKKSLockStateTracker* lockStateTracker = [[CKKSLockStateTracker alloc] init];
-
- CKKSViewManager* manager = [[CKKSViewManager alloc] initWithContainer:container
- sosAdapter:nil
- accountStateTracker:accountStateTracker
- lockStateTracker:lockStateTracker
- cloudKitClassDependencies:cloudKitClassDependencies];
- // No longer a supported mechanism:
- //[CKKSViewManager resetManager:false setTo:manager];
- (void)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<CKRecord*>*)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<CKRecord *> *savedRecords,
- NSArray<CKRecordID *> *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
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>CFBundleDevelopmentRegion</key>
- <string>en</string>
- <key>CFBundleExecutable</key>
- <string>$(EXECUTABLE_NAME)</string>
- <key>CFBundleIdentifier</key>
- <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
- <key>CFBundleInfoDictionaryVersion</key>
- <string>6.0</string>
- <key>CFBundleName</key>
- <string>$(PRODUCT_NAME)</string>
- <key>CFBundlePackageType</key>
- <string>BNDL</string>
- <key>CFBundleShortVersionString</key>
- <string>1.0</string>
- <key>CFBundleVersion</key>
- <string>1</string>
-</dict>
-</plist>
#import <XCTest/XCTest.h>
#import <XCTest/XCTest.h>
#import "keychain/ckks/CKKSCondition.h"
-#import <utilities/debugging.h>
@interface CKKSConditionTests : XCTestCase
@end
[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");
[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
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");
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
[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<CKKSDeviceStateEntry*>* cdses = [CKKSDeviceStateEntry allInZone:self.keychainZoneID error:&error];
XCTAssertNil(error, "No error fetching CDSEs");
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);
[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]}
[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]}
[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);
}
} runBeforeFinished:^{}];
- // Trigger a notification (with hilariously fake data)
- [self.keychainView notifyZoneChange:nil];
-
+ [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil];
[self.keychainView waitForFetchAndIncomingQueueProcessing];
OCMVerifyAllWithDelay(self.mockDatabase, 20);
}
} runBeforeFinished:^{}];
- // Trigger a notification (with hilariously fake data)
- [self.keychainView notifyZoneChange:nil];
-
+ [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil];
[self.keychainView waitForFetchAndIncomingQueueProcessing];
OCMVerifyAllWithDelay(self.mockDatabase, 20);
}
} runBeforeFinished:^{}];
- // Trigger a notification (with hilariously fake data)
- [self.keychainView notifyZoneChange:nil];
-
+ [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil];
[self.keychainView waitForFetchAndIncomingQueueProcessing];
OCMVerifyAllWithDelay(self.mockDatabase, 20);
}];
// Trigger a notification (with hilariously fake data)
- [self.keychainView notifyZoneChange:nil];
+ [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil];
// Wait for both fetches....
OCMVerifyAllWithDelay(self.mockDatabase, 20);
[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]];
// 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];
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
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];
}
}
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");
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);
});
}
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);
}
}
- return YES;
+ return CKKSDatabaseTransactionCommit;
}];
return items;
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;
[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;
- (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
@property (nullable) NSError* selfPeerError;
@property (nullable) NSError* trustedPeersError;
+@property BOOL aksLocked;
+
@property bool excludeSelfPeerFromTrustSet;
@property SOSCCStatus circleStatus;
@property CKKSSOSSelfPeer* selfPeer;
@property NSMutableSet<id<CKKSSOSPeerProtocol>>* trustedPeers;
+@property BOOL safariViewEnabled;
+
+@property BOOL ckks4AllStatus;
+@property BOOL ckks4AllStatusIsSet;
+
@property (nullable) void (^updateOctagonKeySetListener)(id<CKKSSelfPeer>);
- (instancetype)initWithSelfPeer:(CKKSSOSSelfPeer*)selfPeer
_essential = essential;
_circleStatus = kSOSCCInCircle;
+ _safariViewEnabled = YES;
_excludeSelfPeerFromTrustSet = false;
_peerChangeListeners = [[CKKSListenerCollection alloc] initWithName:@"ckks-mock-sos"];
+ _ckks4AllStatus = NO;
+ _ckks4AllStatusIsSet = NO;
+
_selfPeer = selfPeer;
_trustedPeers = [trustedPeers mutableCopy];
}
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 {
- (NSSet<id<CKKSRemotePeerProtocol>> * _Nullable)fetchTrustedPeers:(NSError * _Nullable __autoreleasing * _Nullable)error
{
if(self.trustedPeersError) {
- if(*error) {
+ if(error) {
*error = self.trustedPeersError;
}
return nil;
}
}
-- (void)updateOctagonKeySetWithAccount:(nonnull id<CKKSSelfPeer>)currentSelfPeer error:(NSError *__autoreleasing _Nullable * _Nullable)error {
+- (BOOL)updateOctagonKeySetWithAccount:(nonnull id<CKKSSelfPeer>)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<CKKSPeerUpdateListener>)listener {
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<CKKSSelfPeer>)currentSelfPeer error:(NSError *__autoreleasing _Nullable * _Nullable)error {
+ // No-op
+ return YES;
+}
+
@end
XCTAssertFalse([group isPending], "group operation isn't pending, as it's cancelled");
}
+- (void)testResultOperationDeepDependencyChain {
+ NSMutableArray<CKKSResultOperation*>* 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<CKKSGroupOperation*>* 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
[self saveFakeKeyHierarchyToLocalDatabase:self.manateeZoneID];
[self saveTLKMaterialToKeychain:self.manateeZoneID];
+ [self startCKKSSubsystem];
+
NSDictionary* piggyTLKs = [self SOSPiggyBackCopyFromKeychain];
[self deleteTLKMaterialFromKeychain:self.manateeZoneID];
[self putFakeDeviceStatusesInCloudKit];
[self saveTLKsToKeychain];
+ [self startCKKSSubsystem];
+
NSDictionary* piggyTLKs = [self SOSPiggyBackCopyFromKeychain];
[self deleteTLKMaterialsFromKeychain];
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];
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");
/*
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<NSDictionary *> *tlks = @[
// 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");
XCTAssertEqual(errSecSuccess, SecItemCopyMatching((__bridge CFDictionaryRef)query, &result), "Found a syncable TLK");
XCTAssertNotNil((__bridge id) result, "Received a result from SecItemCopyMatching");
CFReleaseNull(result);
-
- return false;
}];
}
#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"
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 {
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");
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");
// 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");
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<CKKSIncomingQueueEntry*>* 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
changeToken:[@"nonsense" dataUsingEncoding:NSUTF8StringEncoding]
moreRecordsInCloudKit:YES
lastFetch:[NSDate date]
+ lastScan:[NSDate date]
lastFixup:CKKSCurrentFixupNumber
encodedRateLimiter:nil];
zse.rateLimiter = [[CKKSRateLimiter alloc] init];
changeToken:[@"nonsense" dataUsingEncoding:NSUTF8StringEncoding]
moreRecordsInCloudKit:YES
lastFetch:zse.lastFetchTime
+ lastScan:zse.lastLocalKeychainScanTime
lastFixup:CKKSCurrentFixupNumber
encodedRateLimiter:zse.encodedRateLimiter];
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");
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");
// 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 {
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];
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];
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]
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=="]
zoneID:self.testZoneID
encodedCKRecord:testCKRecord
currentkey:true];
- XCTAssertTrue([secondtlk saveToDatabase: &error], "Second TLK saved to database");
- XCTAssertNil(error, "no error saving TLK to database");
+ [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<CKKSKey*>* 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([selfWrapped3 count], 1ul, "Should have received one rows");
XCTAssertEqualObjects([selfWrapped3[0] uuid], secondUUID, "Should received second TLK UUID");
+
+ NSArray<CKKSKey*>* 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 {
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
[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
#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"
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];
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
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
// 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");
// 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");
NSArray<CKKSCurrentKeyPointer*>* currentkeys = [CKKSCurrentKeyPointer all:&error];
XCTAssertNil(error, "no error fetching current keys");
XCTAssertEqual(currentkeys.count, 3u, "Three current key pointers in local database");
-
- return false;
}];
}
// 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");
NSArray<CKKSCurrentKeyPointer*>* currentkeys = [CKKSCurrentKeyPointer all:&error];
XCTAssertNil(error, "no error fetching current keys");
XCTAssertEqual(currentkeys.count, 3u, "Three current key pointers in local database");
-
- return false;
}];
}
// 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");
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;
}];
}
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;
}];
}
[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");
[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");
}
}
- return true;
+ return CKKSDatabaseTransactionCommit;
}];
// Restart. We expect an upload of 3 TLK shares.
[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);
[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");
// 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 {
// 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
}];
[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");
NSMutableArray<CKKSResultOperation<CKKSKeySetProviderOperationProtocol>*>* 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
[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'");
// 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
[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++) {
[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
}];
[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.
[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,
// When the policy is loaded, the item should upload and the callback should fire
[self expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID];
- [self.injectedManager setSyncingViews:self.managedViewList sortingPolicy:self.viewSortingPolicyForManagedViewList];
+ [self.injectedManager setCurrentSyncingPolicy:self.viewSortingPolicyForManagedViewList];
self.keychainView = [self.injectedManager findView:self.keychainZoneID.zoneName];
[self.injectedManager beginCloudKitOperationOfAllViews];
[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.
[self.keychainZone addToZone: record];
// Trigger a notification
- [self.keychainView notifyZoneChange:nil];
+ [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil];
[self.keychainView waitForFetchAndIncomingQueueProcessing];
CFTypeRef item = NULL;
[self.keychainZone addToZone:[cipheritem CKRecordWithZoneID: recordID.zoneID]];
+ [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil];
[self.keychainView waitForFetchAndIncomingQueueProcessing];
NSDictionary* query = @{(id)kSecClass: (id)kSecClassGenericPassword,
[self.keychainZone addToZone:[cipheritem CKRecordWithZoneID: recordID.zoneID]];
+ [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil];
[self.keychainView waitForFetchAndIncomingQueueProcessing];
NSDictionary* query = @{(id)kSecClass: (id)kSecClassGenericPassword,
[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
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];
[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"
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];
[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"]];
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];
}];
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 {
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];
- XCTAssertTrue([outgoingOp isCancelled], "old stuck ProcessOutgoingQueue should be cancelled");
OCMVerifyAllWithDelay(self.mockDatabase, 20);
// And adding another item works too
expecting:errSecSuccess
message:@"Adding class A item"];
OCMVerifyAllWithDelay(self.mockDatabase, 20);
+
+ XCTAssertTrue([outgoingOp isFinished], "old ProcessOutgoingQueue should be finished");
}
/*
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
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];
- (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
[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
[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 expectCKModifyItemRecords:1 currentKeyPointerRecords:1 zoneID:self.keychainZoneID
+ checkItem:[self checkPasswordBlock:self.keychainZoneID account:account password:@"data_new_contents"]];
- [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.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
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"];
// 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];
keychainChanged = [self expectChangeForView:self.keychainZoneID.zoneName];
- [self.keychainView notifyZoneChange:nil];
+ [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil];
[self.keychainView waitForFetchAndIncomingQueueProcessing];
[self waitForExpectations:@[keychainChanged] timeout:8];
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];
// 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];
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:@"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID error:&error];
XCTAssertNotNil(ckme, "Received a ckme");
XCTAssertEqual(ckme.wasCurrent, 10u, "Properly received wasCurrent");
-
- return true;
}];
}
[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];
[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
--- /dev/null
+/*
+ * 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 <CloudKit/CloudKit.h>
+#import <XCTest/XCTest.h>
+#import <OCMock/OCMock.h>
+
+#import <TrustedPeers/TrustedPeers.h>
+#import <TrustedPeers/TPPBPolicyKeyViewMapping.h>
+#import <TrustedPeers/TPDictionaryMatchingRules.h>
+
+#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<TPPBPolicyKeyViewMapping*>* 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
+ 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]]
+ 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
--- /dev/null
+/*
+ * 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 <CloudKit/CloudKit.h>
+#import <XCTest/XCTest.h>
+#import <OCMock/OCMock.h>
+
+#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<CKKSOutgoingQueueEntry*>* 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<CKKSIncomingQueueEntry*>* 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
#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"
- (NSSet*)managedViewList {
NSMutableSet* parentSet = [[super managedViewList] mutableCopy];
- [parentSet addObject:@"SafariPasswords"];
+ [parentSet addObject:@"Passwords"];
return parentSet;
}
// Make a policy as normal for most views, but Passwords is special
-- (TPPolicy*)viewSortingPolicyForManagedViewList
+- (TPSyncingPolicy*)viewSortingPolicyForManagedViewList
{
NSMutableArray<TPPBPolicyKeyViewMapping*>* rules = [NSMutableArray array];
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:@"SafariPasswords"]) {
+ if([viewName isEqualToString:@"Passwords"]) {
mapping.matchingRule = [TPDictionaryMatchingRule fieldMatch:@"agrp"
fieldRegex:[NSString stringWithFormat:@"^com\\.apple\\.sbd$"]];
} else {
[rules addObject:mapping];
}
- TPPolicy* policy = [TPPolicy policyWithModelToCategory:@[]
- categoriesByView:@{}
- introducersByCategory:@{}
- keyViewMapping:rules
- unknownRedactions:NO
- version:[[TPPolicyVersion alloc] initWithVersion:1 hash:@"fake-policy-for-views"]];
+ NSSet<NSString*>* viewList = [self managedViewList];
+ TPSyncingPolicy* policy = [[TPSyncingPolicy alloc] initWithModel:@"test-policy"
+ version:[[TPPolicyVersion alloc] initWithVersion:1 hash:@"fake-policy-for-views"]
+ viewList:viewList
+ userControllableViews:[NSSet set]
+ syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_ENABLED
+ viewsToPiggybackTLKs:[viewList containsObject:@"Passwords"] ? [NSSet setWithObject:@"Passwords"] : [NSSet set]
+ keyViewMapping:rules];
return policy;
}
[self.ckksViews addObject:self.limitedView];
[self.ckksZones addObject:self.limitedZoneID];
- self.passwordsZoneID = [[CKRecordZoneID alloc] initWithZoneName:@"SafariPasswords" ownerName:CKCurrentUserDefaultName];
+ 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:@"SafariPasswords"];
+ 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];
// These tests, at least, will use the policy codepaths!
[self.injectedManager setOverrideCKKSViewsFromPolicy:YES];
- [self.injectedManager setSyncingViews:self.managedViewList sortingPolicy:self.viewSortingPolicyForManagedViewList];
+ [self.injectedManager setCurrentSyncingPolicy:self.viewSortingPolicyForManagedViewList];
}
+ (void)tearDown {
[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]) {
CFTypeRef item = NULL;
XCTAssertEqual(errSecSuccess, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should still exist");
- XCTAssertNotNil((__bridge id)item, "No item should have been found");
+ 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.passwordsView notifyZoneChange:nil];
+
+ [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil];
[self.passwordsView waitForFetchAndIncomingQueueProcessing];
XCTAssertEqual(errSecItemNotFound, SecItemCopyMatching((__bridge CFDictionaryRef) query, &item), "item should no longer exist");
[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];
XCTestExpectation* engramChanged = [self expectChangeForView:self.engramZoneID.zoneName];
XCTestExpectation* pcsChanged = [self expectChangeForView:@"PCS"];
+ self.silentFetchesAllowed = false;
+ [self expectCKFetch];
+
// Trigger a notification (with hilariously fake data)
- [self.engramView notifyZoneChange:nil];
+ [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil];
+ OCMVerifyAllWithDelay(self.mockDatabase, 20);
[self.engramView waitForFetchAndIncomingQueueProcessing];
+
[self findGenericPassword:@"account-delete-me" expecting:errSecSuccess];
[self waitForExpectations:@[engramChanged] timeout:1];
[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);
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];
}];
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];
}];
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.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);
#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"
#import "keychain/ckks/tests/MockCloudKit.h"
#import "keychain/ckks/tests/CKKSTests.h"
+#import "keychain/ot/ObjCImprovements.h"
#import <utilities/SecCoreAnalytics.h>
// break abstraction
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<NSString *,NSString *>* tlks = [[CKKSViewManager manager] activeTLKs];
+ NSError* localError = nil;
+ NSArray<CKKSKeychainBackedKey*>* tlks = [[CKKSViewManager manager] currentTLKsFilteredByPolicy:NO error:&localError];
+ XCTAssertNil(localError, "Should have no error fetching current TLKs");
+
+ XCTAssertEqual([tlks count], (NSUInteger)1, "Should have one TLK");
+ XCTAssertEqualObjects(tlks[0].zoneID.zoneName, @"keychain", "should have a TLK for keychain");
- XCTAssertEqual([tlks count], (NSUInteger)1, "One TLK");
- XCTAssertNotNil(tlks[@"keychain"], "keychain have a UUID");
+ 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<CKKSKeychainBackedKey*>* 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<CKKSKeychainBackedKey*>* 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.
[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);
}
// 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)
// 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.
// 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)
[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:@"50184A35-4480-E8BA-769B-567CF72F1EC0" zoneID:self.keychainZoneID];
[oqe saveToDatabase:&error];
XCTAssertNil(error, "Shouldn't error saving new OQE to database");
- return true;
+ return CKKSDatabaseTransactionCommit;
}];
NSError *error = NULL;
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";
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";
// 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);
}
[self.keychainView waitForOperationsOfClass:[CKKSOutgoingQueueOperation class]];
// Ensure nothing is in the outgoing queue
- [self.keychainView dispatchSync:^bool {
+ [self.keychainView dispatchSyncWithReadOnlySQLTransaction:^{
NSError* error = nil;
NSArray<NSString*>* 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];
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");
}
}
}
- // Trigger a notification (with hilariously fake data)
- [self.keychainView notifyZoneChange:nil];
-
+ [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil];
[self.keychainView waitForFetchAndIncomingQueueProcessing];
[self findGenericPassword: @"account0" expecting:errSecSuccess];
[self expectCKDeleteItemRecords:1 zoneID:self.keychainZoneID];
// 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<CKKSIncomingQueueEntry*>* 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 {
(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<NSString*>* 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 {
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");
[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];
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");
XCTAssertNotNil(iqes, "Could load IQEs");
XCTAssertEqual(iqes.count, 0u, "Incoming queue is empty");
- return false;
}];
}
[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<NSString*>* uuids = [CKKSOutgoingQueueEntry allUUIDs:self.keychainZoneID ?: [[CKRecordZoneID alloc] initWithZoneName:@"keychain"
ownerName:CKCurrentUserDefaultName]
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"];
[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<NSString*>* uuids = [CKKSOutgoingQueueEntry allUUIDs:self.keychainZoneID ?: [[CKRecordZoneID alloc] initWithZoneName:@"keychain"
ownerName:CKCurrentUserDefaultName]
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
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,
[self.keychainZone addToZone:[cipheritem CKRecordWithZoneID: recordID.zoneID]];
+ [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil];
[self.keychainView waitForFetchAndIncomingQueueProcessing];
NSDictionary* query = @{(id)kSecClass: (id)kSecClassGenericPassword,
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);
}
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)
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
[keysetOp waitUntilFinished];
XCTAssertNil(keysetOp.error, "Should be no error fetching keyset from CKKS");
- NSArray<CKRecord*>* records = [self putKeySetInCloudKit:keysetOp.keyset];
- [keyHierarchyRecords addObjectsFromArray:records];
- }
+ NSArray<CKRecord*>* records = [self putKeySetInCloudKit:keysetOp.keyset];
+ [keyHierarchyRecords addObjectsFromArray:records];
+ }
+
+ // Tell our views about our shiny new records!
+ for(CKKSKeychainView* view in self.ckksViews) {
+ [view receiveTLKUploadRecords: keyHierarchyRecords];
+ }
+ OCMVerifyAllWithDelay(self.mockDatabase, 20);
+
+ 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<CKKSResultOperation<CKKSKeySetProviderOperationProtocol>*>* keysetOps = [NSMutableArray array];
+
+ for(CKKSKeychainView* view in self.ckksViews) {
+ [keysetOps addObject:[view findKeySet:NO]];
+ }
+
+ for(CKKSResultOperation<CKKSKeySetProviderOperationProtocol>* 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<CKKSResultOperation<CKKSKeySetProviderOperationProtocol>*>* fetchedKeysetOps = [NSMutableArray array];
+
+ for(CKKSKeychainView* view in self.ckksViews) {
+ [fetchedKeysetOps addObject:[view findKeySet:YES]];
+ }
+
+ for(CKKSResultOperation<CKKSKeySetProviderOperationProtocol>* 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[SecCKKSZoneKeyStateWaitForTrust] wait:20*NSEC_PER_SEC], @"Key state should become 'waitfortrust'");
+
+ CKKSResultOperation<CKKSKeySetProviderOperationProtocol>* keysetOp = [self.keychainView findKeySet:NO];
+ [keysetOp timeout:20*NSEC_PER_SEC];
+ [keysetOp waitUntilFinished];
+
+ XCTAssertNil(keysetOp.error, "Should be no error fetching a keyset");
+}
+
+- (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<CKKSKeySetProviderOperationProtocol>* keysetOp = [self.keychainView findKeySet:YES];
+ [keysetOp timeout:20*NSEC_PER_SEC];
+ [keysetOp waitUntilFinished];
- // Tell our views about our shiny new records!
- for(CKKSKeychainView* view in self.ckksViews) {
- [view receiveTLKUploadRecords: keyHierarchyRecords];
- }
- OCMVerifyAllWithDelay(self.mockDatabase, 20);
+ XCTAssertNil(keysetOp.error, "Should be no error fetching a keyset");
- XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], @"key state should enter 'ready'");
+ OCMVerifyAllWithDelay(self.mockDatabase, 20);
}
-- (void)testProvideKeysetFromNoTrust {
+- (void)testProvideKeysetAfterReceivingTLKInNoTrust {
+ [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<CKKSKeySetProviderOperationProtocol>* keysetOp = [self.keychainView findKeySet];
+ // 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<CKKSKeySetProviderOperationProtocol>* 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");
}
-// This test no longer is very interesting, since Octagon needs to handle lock states, not CKKS...
- (void)testUploadInitialKeyHierarchyAfterLockedStart {
// 'Lock' the keybag
self.aksLockState = true;
[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<CKKSKeySetProviderOperationProtocol>* 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<CKRecord*>* 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"]];
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<CKKSKeySetProviderOperationProtocol>* 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<CKKSKeySetProviderOperationProtocol>* 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;
// 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;
[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);
}
[self putFakeDeviceStatusInCloudKit:self.keychainZoneID];
// Also, CKKS _should_ be able to return the key hierarchy if asked before it starts
- CKKSResultOperation<CKKSKeySetProviderOperationProtocol>* keysetOp = [self.keychainView findKeySet];
+ CKKSResultOperation<CKKSKeySetProviderOperationProtocol>* keysetOp = [self.keychainView findKeySet:NO];
NSDateComponents* offset = [[NSDateComponents alloc] init];
[offset setDay:-5];
// 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");
NSArray<CKKSCurrentKeyPointer*>* currentkeys = [CKKSCurrentKeyPointer all: &error];
XCTAssertNil(error, "no error fetching current keys");
XCTAssertEqual(currentkeys.count, 3u, "Three current key pointers in local database");
-
- return false;
}];
}
// 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");
NSArray<CKKSCurrentKeyPointer*>* currentkeys = [CKKSCurrentKeyPointer all: &error];
XCTAssertNil(error, "no error fetching current keys");
XCTAssertEqual(currentkeys.count, 3u, "Three current key pointers in local database");
-
- return false;
}];
}
[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];
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'");
[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");
[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");
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"];
[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"]];
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];
[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);
// 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.
// 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.
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;
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!)
[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];
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");
[iqe deleteFromDatabase: &error];
}
XCTAssertNil(error, "no error removing IQE");
- return true;
+ return CKKSDatabaseTransactionCommit;
}];
// For the second record, delete all traces of it from CloudKit.
[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;
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";
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];
[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];
[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");
ckme = [CKKSMirrorEntry tryFromDatabase:ckr.recordID.recordName zoneID:strongSelf.keychainZoneID error:&error];
XCTAssertNil(error);
XCTAssertNotNil(ckme);
- return true;
}];
}
[self startCKKSSubsystem];
OCMVerifyAllWithDelay(self.mockDatabase, 20);
[self waitForCKModifications];
+
+ [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil];
[self.keychainView waitForFetchAndIncomingQueueProcessing];
// Now, place an item in the outgoing queue
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
[self startCKKSSubsystem];
OCMVerifyAllWithDelay(self.mockDatabase, 20);
[self waitForCKModifications];
+
+ [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil];
[self.keychainView waitForFetchAndIncomingQueueProcessing];
[self.keychainView waitForOperationsOfClass:[CKKSScanLocalItemsOperation class]];
[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];
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;
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];
ckse.lastFetchTime = [NSDate distantPast];
[ckse saveToDatabase: &error];
XCTAssertNil(error, "no error saving to database");
- return true;
+ return CKKSDatabaseTransactionCommit;
}];
[self expectCKFetch];
[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 {
[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"];
}), @"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];
// 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];
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];
[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....
[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");
[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
[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];
// Say network is available
[self.reachabilityTracker setNetworkReachability:true];
+ [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil];
[self.keychainView waitForFetchAndIncomingQueueProcessing];
[self findGenericPassword:@"account-delete-me" expecting:errSecSuccess];
[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];
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];
[self expectCKFetch]; // and one to succeed
// Trigger a fake change notification
- [self.keychainView notifyZoneChange:nil];
+ [self.injectedManager.zoneChangeFetcher notifyZoneChange:nil];
OCMVerifyAllWithDelay(self.mockDatabase, 20);
[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]
[cdse saveToDatabase:&error];
XCTAssertNil(error, @"No error saving cdse to database");
- return true;
+ return CKKSDatabaseTransactionCommit;
}];
// Spin up CKKS subsystem.
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];
// 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];
// 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);
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;
[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)
[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];
[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)
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'");
[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)
[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;
// 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];
[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];
[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");
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
// 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'");
// 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);
// 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 {
[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 counting OQEs");
XCTAssertNil(error, "Should be no error counting OQEs");
XCTAssertEqual(0, currentOQEs.count, "Should be no OQEs");
- [self.injectedManager setSyncingViews:self.managedViewList sortingPolicy:self.viewSortingPolicyForManagedViewList];
+ [self.injectedManager setCurrentSyncingPolicy:self.viewSortingPolicyForManagedViewList];
self.keychainView = [self.injectedManager findView:self.keychainZoneID.zoneName];
// end of daemon restart
[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];
[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];
[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];
[self startCKKSSubsystem];
[self waitForExpectations: @[operationRun] timeout:20];
+ XCTAssertEqual(0, [self.keychainView.keyHierarchyConditions[SecCKKSZoneKeyStateReady] wait:20*NSEC_PER_SEC], "CKKS entered 'ready'");
}
- (void)testCKKSControlBringup {
}
[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;
}];
}];
}
[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");
- (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];
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];
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;
[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];
}
[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];
ckse.lastFixup = newFixup;
[ckse saveToDatabase: &error];
XCTAssertNil(error, "no error saving to database");
- return true;
+ return CKKSDatabaseTransactionCommit;
}];
}
[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];
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");
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;
}];
}
[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");
[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
// 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");
[cdse saveToDatabase:&error];
XCTAssertNil(error, "No error saving modified CDSE back to database");
- return true;
+ return CKKSDatabaseTransactionCommit;
}];
// Tear down the CKKS object
[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
#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"
@interface CloudKitKeychainSyncingMockXCTest : CloudKitMockXCTest
@property CKKSControl* ckksControl;
-@property OTCuttlefishAccountStateHolder *accountMetaDataStore;
@property (nullable) id mockCKKSKeychainBackedKey;
@property (nullable) NSError* keychainFetchError;
// 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<CKKSKeychainView*>* ckksViews;
@property NSMutableSet<CKRecordZoneID*>* ckksZones;
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
- (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;
#if OCTAGON
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wquoted-include-in-framework-header"
#import <OCMock/OCMock.h>
+#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"
self.suggestTLKUpload = OCMClassMock([CKKSNearFutureScheduler class]);
OCMStub([self.suggestTLKUpload trigger]);
+ 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];
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];
[self.mockCKKSKeychainBackedKey stopMocking];
self.mockCKKSKeychainBackedKey = nil;
- [((id)self.accountMetaDataStore) stopMocking];
-
self.remoteSOSOnlyPeer = nil;
}
[view beginCloudKitOperation];
}
- [view beginTrustedOperation:@[self.mockSOSAdapter] suggestTLKUpload:self.suggestTLKUpload];
+ [view beginTrustedOperation:@[self.mockSOSAdapter]
+ suggestTLKUpload:self.suggestTLKUpload
+ requestPolicyCheck:self.requestPolicyCheck];
}
- (void)endSOSTrustedOperationForAllViews {
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
}
- (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.tlk saveToDatabase:&error];
+ XCTAssertNil(error, "TLK saved to database successfully");
+
+ [zonekeys.classA saveToDatabase:&error];
+ XCTAssertNil(error, "Class A key saved to database successfully");
- [zonekeys.classA saveToDatabase:&error];
- XCTAssertNil(error, "Class A key saved to database successfully");
+ [zonekeys.classC saveToDatabase:&error];
+ XCTAssertNil(error, "Class C key saved to database successfully");
- [zonekeys.classC saveToDatabase:&error];
- XCTAssertNil(error, "Class C key saved to database successfully");
+ [zonekeys.currentTLKPointer saveToDatabase:&error];
+ XCTAssertNil(error, "Current TLK pointer saved to database successfully");
- [zonekeys.currentTLKPointer saveToDatabase:&error];
- XCTAssertNil(error, "Current TLK pointer saved to database successfully");
+ [zonekeys.currentClassAPointer saveToDatabase:&error];
+ XCTAssertNil(error, "Current Class A 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");
- [zonekeys.currentClassCPointer saveToDatabase:&error];
- XCTAssertNil(error, "Current Class C pointer saved to database successfully");
+ return CKKSDatabaseTransactionCommit;
+ }];
}
- (void)putFakeDeviceStatusInCloudKit:(CKRecordZoneID*)zoneID zonekeys:(ZoneKeys*)zonekeys {
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
CFReleaseNull(cferror);
return piggybackdata;
}
+
- (void)SOSPiggyBackAddToKeychain:(NSDictionary*)piggydata{
__block CFErrorRef cferror = NULL;
kc_with_dbt(true, &cferror, ^bool (SecDbConnectionRef dbt) {
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 {
- (void)checkNoCKKSData: (CKKSKeychainView*) view {
// Test that there are no items in the database
- [view dispatchSync:^bool{
+ [view dispatchSyncWithReadOnlySQLTransaction:^{
NSError* error = nil;
NSArray<CKKSMirrorEntry*>* ckmes = [CKKSMirrorEntry all: view.zoneID error:&error];
XCTAssertNil(error, "No error fetching CKMEs");
NSArray<CKKSDeviceStateEntry*>* 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;
}];
}
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];
}
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];
[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,
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;
}];
}
}
}
-- (OTAccountMetadataClassC*)loadOrCreateAccountMetadata:(NSError**)error
-{
- if(error) {
- *error = [NSError errorWithDomain:@"securityd" code:errSecInteractionNotAllowed userInfo:nil];
- }
- return nil;
-}
-
@end
#endif // OCTAGON
#define CloudKitKeychainSyncingTestsBase_h
#import <CloudKit/CloudKit.h>
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wquoted-include-in-framework-header"
#import <OCMock/OCMock.h>
+#pragma clang diagnostic pop
+
#import <XCTest/XCTest.h>
#include <Security/SecItemPriv.h>
#import "keychain/ckks/tests/MockCloudKit.h"
#import "keychain/ot/OTManager.h"
+#import "keychain/trust/TrustedPeers/TPSyncingPolicy.h"
NS_ASSUME_NONNULL_BEGIN
@class CKKSReachabilityTracker;
@class SOSCKKSPeerAdapter;
+@interface CKKSTestFailureLogger : NSObject <XCTestObservation>
+@end
+
@interface CloudKitMockXCTest : XCTestCase
@property CKRecordZoneID* testZoneID;
@property (nullable) CKKSMockOctagonAdapter *mockOctagonAdapter;
- (NSSet<NSString*>*)managedViewList;
-- (TPPolicy*)viewSortingPolicyForManagedViewList;
+- (TPSyncingPolicy*)viewSortingPolicyForManagedViewList;
+- (TPSyncingPolicy*)viewSortingPolicyForManagedViewListWithUserControllableViews:(NSSet<NSString*>*)ucv
+ syncUserControllableViews:(TPPBPeerStableInfo_UserControllableViewStatus)syncUserControllableViews;
@property (nullable) id mockCKKSViewManager;
@property (nullable) CKKSViewManager* injectedManager;
// 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
#import <CloudKit/CloudKit.h>
#import <CloudKit/CloudKit_Private.h>
#import <CloudKit/CKContainer_Private.h>
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wquoted-include-in-framework-header"
#import <OCMock/OCMock.h>
+#pragma clang diagnostic pop
+
#import <TrustedPeers/TrustedPeers.h>
#import <TrustedPeers/TPPBPolicyKeyViewMapping.h>
#import <TrustedPeers/TPDictionaryMatchingRules.h>
- (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,
+ (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
#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;
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]);
// 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:
OCMStub([self.mockCKKSViewManager syncBackupAndNotifyAboutSync]);
OCMStub([self.mockCKKSViewManager waitForTrustReady]).andReturn(YES);
- if(!self.disableConfigureCKKSViewManagerWithViews) {
- // Normally, the Octagon state machine calls this. But, since we won't be running that, help it out.
- [self.injectedManager setSyncingViews:[self managedViewList]
- sortingPolicy:[self viewSortingPolicyForManagedViewList]];
- }
-
// Lie and say network is available
[self.reachabilityTracker setNetworkReachability:true];
// 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
- (void)setAksLockState:(bool)aksLockState
{
-
+ ckksnotice_global("ckkstests", "Setting mock AKS lock state to: %@", (aksLockState ? @"locked" : @"unlocked"));
if(aksLockState) {
[SecMockAKS lockClassA];
+
+ self.mockSOSAdapter.aksLocked = YES;
} else {
[SecMockAKS unlockAllClasses];
+
+ self.mockSOSAdapter.aksLocked = NO;
}
_aksLockState = aksLockState;
}
return (NSSet*) CFBridgingRelease(SOSViewCopyViewSet(kViewSetCKKS));
}
-- (TPPolicy*)viewSortingPolicyForManagedViewList
+- (TPSyncingPolicy*)viewSortingPolicyForManagedViewList
+{
+ return [self viewSortingPolicyForManagedViewListWithUserControllableViews:[NSSet set]
+ syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_ENABLED];
+}
+
+- (TPSyncingPolicy*)viewSortingPolicyForManagedViewListWithUserControllableViews:(NSSet<NSString*>*)ucv
+ syncUserControllableViews:(TPPBPeerStableInfo_UserControllableViewStatus)syncUserControllableViews
{
NSMutableArray<TPPBPolicyKeyViewMapping*>* rules = [NSMutableArray array];
[rules addObject:mapping];
}
- TPPolicy* policy = [TPPolicy policyWithModelToCategory:@[]
- categoriesByView:@{}
- introducersByCategory:@{}
- keyViewMapping:rules
- unknownRedactions:NO
- version:[[TPPolicyVersion alloc] initWithVersion:1 hash:@"fake-policy-for-views"]];
-
+ TPSyncingPolicy* policy = [[TPSyncingPolicy alloc] initWithModel:@"test-policy"
+ version:[[TPPolicyVersion alloc] initWithVersion:1 hash:@"fake-policy-for-views"]
+ viewList:[self managedViewList]
+ userControllableViews:ucv
+ syncUserControllableViews:syncUserControllableViews
+ viewsToPiggybackTLKs:[NSSet set]
+ keyViewMapping:rules];
return policy;
}
-(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 {
-(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 {
-(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 {
-(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 {
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;
}
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;
}
// 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];
// 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
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;
}
if(!skipCreation) {
// Create the zone:
- secnotice("ckks", "Creating zone %@", zone);
+ ckksnotice_global("ckks", "Creating zone %@", zone);
ckdb[zone.zoneID] = [[FakeCKZone alloc] initZone: zone.zoneID];
}
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;
}
@synthesize recordZoneFetchCompletionBlock = _recordZoneFetchCompletionBlock;
@synthesize fetchRecordZoneChangesCompletionBlock = _fetchRecordZoneChangesCompletionBlock;
+@synthesize deviceIdentifier = _deviceIdentifier;
+
@synthesize operationID = _operationID;
@synthesize resolvedConfiguration = _resolvedConfiguration;
@synthesize group = _group;
_configurationsByRecordZoneID = configurationsByRecordZoneID;
_operationID = @"fake-operation-ID";
+ _deviceIdentifier = @"ckkstests";
}
return self;
}
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);
@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<NSString *> *)enabledTopics {
-}
-
-- (void)setDarkWakeTopics:(NSArray<NSString *> *)darkWakeTopics {
-}
-
@end
// Do literally nothing
- (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;
}
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];
}
}
#if OCTAGON
-@interface CKKSAPSNotificationReceiver : NSObject <CKKSZoneUpdateReceiver>
+@interface CKKSAPSNotificationReceiver : NSObject <CKKSZoneUpdateReceiverProtocol>
@property XCTestExpectation* expectation;
@property void (^block)(CKRecordZoneNotification* notification);
- (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");
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");
[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
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];
@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;
test_dictionary['WorkingDirectory'] = '/AppleInternal/XCTests/com.apple.security/'
test_command = Foundation.NSMutableArray.array()
- test_command.append('BATS_XCTEST_CMD -XCTest {} CKKSTests.xctest'.format(x))
+ test_command.append('BATS_XCTEST_CMD')
+ test_command.append('-XCTest')
+ test_command.append('{}'.format(x))
+ test_command.append('CKKSTests.xctest')
test_dictionary['Command'] = test_command
test_list.append(test_dictionary)
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>com.apple.application-identifier</key>
- <string>com.apple.security.KeychainEntitledTestRunner</string>
- <key>application-identifier</key>
- <string>com.apple.security.KeychainEntitledTestRunner</string>
- <key>com.apple.developer.icloud-services</key>
- <array>
- <string>CloudKit</string>
- </array>
- <key>com.apple.private.cloudkit.masquerade</key>
- <true/>
- <key>com.apple.private.cloudkit.customAccounts</key>
- <true/>
- <key>com.apple.developer.icloud-container-environment</key>
- <string>Development</string>
- <key>com.apple.private.aps-connection-initiate</key>
- <true/>
- <key>aps-connection-initiate</key>
- <true/>
- <key>aps-environment</key>
- <string>serverPreferred</string>
- <key>keychain-access-groups</key>
- <array>
- <string>com.apple.security.ckks</string>
- </array>
- <key>keychain-cloud-circle</key>
- <true/>
-</dict>
-</plist>
+++ /dev/null
-//
-// KeychainEntitledTestRunner.m
-// KeychainEntitledTestRunner
-//
-// Stolen from Mark Pauley / CDEntitledTestRunner who stole it from Drew Terry / MobileContainerManager
-// Copyright 2016-2017 Apple. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-#import <unistd.h>
-#import <XCTest/XCTest.h>
-
-@interface TestRunner : NSObject <XCTestObservation> {
- NSBundle *_bundle;
- XCTestSuite *_testSuite;
-}
-
-- (instancetype)initWithBundlePath:(NSString *)path andTestNames:(NSArray *)names;
-- (NSUInteger)runUnitTestSuite;
-
-- (void)testLogWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2);
-- (void)testLogWithFormat:(NSString *)format arguments:(va_list)arguments NS_FORMAT_FUNCTION(1,0);
-
-@end
-
-@implementation TestRunner
-- (instancetype)initWithBundlePath:(NSString *)path andTestNames:(NSArray *)names
-{
- self = [super init];
- if (self) {
- NSError *error = nil;
-
- _bundle = [NSBundle bundleWithPath:path];
- if (!_bundle) {
- [self testLogWithFormat:@"No bundle at location %@ (%s)\n", path, strerror(errno)];
- return nil;
- }
- if (![_bundle loadAndReturnError:&error]) {
- [self testLogWithFormat:@"Test Bundle at %@ didn't load: %@\n", path, error];
- return nil;
- }
-
- if(names) {
- XCTestSuite* testSuite = [[XCTestSuite alloc] initWithName:[[path lastPathComponent] stringByDeletingPathExtension]];
- XCTestSuite* loadedSuite = [XCTestSuite testSuiteForBundlePath:path];
- // Filter out only the tests that were named.
- [loadedSuite.tests enumerateObjectsUsingBlock:^(__kindof XCTest * _Nonnull test, NSUInteger __unused idx, BOOL * __unused _Nonnull stop) {
- [self testLogWithFormat:@"Checking test %@\n", test.name];
- if([names containsObject:test.name]) {
- [testSuite addTest:test];
- }
- }];
- _testSuite = testSuite;
- }
- else {
- _testSuite = [XCTestSuite testSuiteForBundlePath:path];
- }
- }
- return self;
-}
-
-- (NSUInteger)runUnitTestSuite
-{
- [[XCTestObservationCenter sharedTestObservationCenter] addTestObserver:self];
-
- [_testSuite runTest];
-
- XCTestRun *testRun = [_testSuite testRun];
-
- return testRun.totalFailureCount;
-}
-
-- (NSFileHandle *)logFileHandle
-{
- return [NSFileHandle fileHandleWithStandardOutput];
-}
-
-- (void)testLogWithFormat:(NSString *)format, ...
-{
- va_list ap;
- va_start(ap, format);
- [self testLogWithFormat:format arguments:ap];
- va_end(ap);
-}
-
-- (void)testLogWithFormat:(NSString *)format arguments:(va_list)arguments
-{
- NSString *message = [[NSString alloc] initWithFormat:format arguments:arguments];
- [self.logFileHandle writeData:[message dataUsingEncoding:NSUTF8StringEncoding]];
-}
-
-- (NSDateFormatter *)dateFormatter
-{
- static NSDateFormatter *dateFormatter;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- dateFormatter = [NSDateFormatter new];
- dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss.SSS";
- });
- return dateFormatter;
-}
-
-/* -testBundleWillStart: // exactly once per test bundle
- * -testSuiteWillStart: // exactly once per test suite
- * -testCaseWillStart: // exactly once per test case
- * -testCase:didFailWithDescription:... // zero or more times per test case, any time between test case start and finish
- * -testCaseDidFinish: // exactly once per test case
- * -testSuite:didFailWithDescription:... // zero or more times per test suite, any time between test suite start and finish
- * -testSuiteDidFinish: // exactly once per test suite
- * -testBundleDidFinish: // exactly once per test bundle
- */
-
-- (void)testSuiteWillStart:(XCTestSuite *)testSuite
-{
- [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 : @"<unknown>"), ((unsigned long)((nil != filePath) ? lineNumber : 0)), testSuite.name, description];
-}
-
-- (void)testSuiteDidFinish:(XCTestSuite *)testSuite
-{
- XCTestRun *testRun = testSuite.testRun;
- [self testLogWithFormat:@"Test Suite '%@' %s at %@.\n\t Executed %lu test%s, with %lu failure%s (%lu unexpected) in %.3f (%.3f) seconds\n",
- testSuite.name,
- (testRun.hasSucceeded ? "passed" : "failed"),
- [self.dateFormatter stringFromDate:testRun.stopDate],
- ((unsigned long)testRun.executionCount), (testRun.executionCount != 1 ? "s" : ""),
- ((unsigned long)testRun.totalFailureCount), (testRun.totalFailureCount != 1 ? "s" : ""),
- ((unsigned long)testRun.unexpectedExceptionCount),
- testRun.testDuration,
- testRun.totalDuration];
-}
-
-- (void)testCaseWillStart:(XCTestCase *)testCase
-{
- [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 : @"<unknown>"), ((unsigned long)((nil != filePath) ? lineNumber : 0)), testCase.name, description];
-}
-
-- (void)testCaseDidFinish:(XCTestCase *)testCase
-{
- [self testLogWithFormat:@"Test Case '%@' %s (%.3f seconds).\n", testCase.name, (testCase.testRun.hasSucceeded ? "passed" : "failed"), testCase.testRun.totalDuration];
-
-}
-@end
-
-
-
-
-static char* gTestBundleDir = "/AppleInternal/XCTests/com.apple.security";
-static char* gTestBundleName = "CKKSCloudKitTests";
-
-static NSMutableArray* gTestCaseNames = nil;
-
-static const char* opt_str = "d:t:c:h";
-
-static void usage(char*const binName, bool longUsage) {
- fprintf(stderr, "Usage: %s [-d <test_dir>] -t test_bundle_name [(-c test_case_name)*]\n", binName);
- if (longUsage) {
- fprintf(stderr, "-d: argument = path to directory where test bundles live\n");
- fprintf(stderr, "-t: argument = name of test bundle to be run (without extension)\n");
- fprintf(stderr, "-c: argument = name of test case to be run (multiple)\n");
- }
-}
-
-static void getOptions(int argc, char *const *argv) {
- int ch;
- while ( (ch = getopt(argc, argv, opt_str)) != -1 ) {
- switch(ch)
- {
- case 'd':
- gTestBundleDir = optarg;
- break;
- case 't':
- gTestBundleName = optarg;
- break;
- case 'c':
- if(!gTestCaseNames) {
- gTestCaseNames = [NSMutableArray new];
- }
- [gTestCaseNames addObject:@(optarg)];
- break;
- case 'h':
- case '?':
- default:
- usage(argv[0], true);
- exit(0);
- break;
- }
- }
-}
-
-int main (int argc, const char * argv[])
-{
- @autoreleasepool {
- getOptions(argc, (char*const*)argv);
- NSString *testBundleDir = [NSString stringWithCString:gTestBundleDir encoding:NSUTF8StringEncoding];
- NSString *testBundleName = [NSString stringWithCString:gTestBundleName encoding:NSUTF8StringEncoding];
- NSString *testBundlePath = [[testBundleDir stringByAppendingPathComponent:testBundleName] stringByAppendingPathExtension:@"xctest"];
-
- printf("Running unit tests %s at: %s\n", gTestCaseNames?gTestCaseNames.description.UTF8String:"[All]", testBundlePath.UTF8String);
-
- TestRunner *unitTest = [[TestRunner alloc] initWithBundlePath:testBundlePath andTestNames:gTestCaseNames];
- if (!unitTest) {
- fprintf(stderr, "Failed to load unit test runner at: %s\n", testBundlePath.UTF8String);
- return 1;
- }
-
- //runUnitTestSuite returns the number of failures. 0 = success, non-zero means failure. This complies with BATS testing standards.
- return (int)[unitTest runUnitTestSuite];
-
- return 0;
- }
-}
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);
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");
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]);
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) {
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;
}
flags:(nonnull OctagonFlags *)flags
pendingFlags:(nonnull id<OctagonStateOnqueuePendingFlagHandler>)pendingFlagHandler
{
+ dispatch_assert_queue(self.queue);
if([flags _onqueueContains:OctagonFlagEscrowRequestInformCloudServicesOperation]) {
[flags _onqueueRemoveFlag:OctagonFlagEscrowRequestInformCloudServicesOperation];
return [[EscrowRequestInformCloudServicesOperation alloc] initWithIntendedState:EscrowRequestStateNothingToDo
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
+#import <Security/SecXPCHelper.h>
#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<Class>* 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;
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,
//__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
/*
* 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 */
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 */
* - kSecAttrIsSensitive for private keys
* - kSecAttrIsExtractable by default
*/
-} SecItemImportExportKeyParameters API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac);
+} SecItemImportExportKeyParameters API_UNAVAILABLE(ios, watchos, tvos, bridgeos, macCatalyst);
/*
* 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()
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()
#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
*/
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
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));
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
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);
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.
@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.
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);
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_ */
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.
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
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
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
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
*/
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
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));
/*!
/*
- * Copyright (c) 2014-2016 Apple Inc. All Rights Reserved.
+ * Copyright (c) 2014-2020 Apple Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
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
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
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
@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__ */
deviceName:(nullable NSString*)deviceName
serialNumber:(NSString *)serialNumber
osVersion:(NSString *)osVersion
- policyVersion:(nullable TPPolicy *)policyVersion
+ policyVersion:(nullable TPPolicyVersion *)policyVersion
policySecrets:(nullable NSDictionary<NSString*,NSData*> *)policySecrets
+ syncUserControllableViews:(TPPBPeerStableInfo_UserControllableViewStatus)syncUserControllableViews
signingPrivKeyPersistentRef:(nullable NSData *)spkPr
encPrivKeyPersistentRef:(nullable NSData*)epkPr
reply:(void (^)(NSString * _Nullable peerID,
NSData * _Nullable permanentInfoSig,
NSData * _Nullable stableInfo,
NSData * _Nullable stableInfoSig,
- NSSet<NSString*>* syncingViews,
- TPPolicy* _Nullable syncingPolicy,
+ TPSyncingPolicy* _Nullable syncingPolicy,
NSError * _Nullable error))reply
{
__block int i = 0;
retry = true;
} else {
secerror("octagon: Can't talk with TrustedPeersHelper: %@", error);
- reply(nil, nil, nil, nil, nil, nil, nil, error);
+ reply(nil, nil, nil, nil, nil, nil, error);
}
++i;
}] prepareWithContainer:container
osVersion:osVersion
policyVersion:policyVersion
policySecrets:policySecrets
+ syncUserControllableViews:syncUserControllableViews
signingPrivKeyPersistentRef:spkPr
encPrivKeyPersistentRef:epkPr
reply:reply];
preapprovedKeys:(nullable NSArray<NSData*> *)preapprovedKeys
reply:(void (^)(NSString * _Nullable peerID,
NSArray<CKRecord*>* _Nullable keyHierarchyRecords,
+ TPSyncingPolicy* _Nullable syncingPolicy,
NSError * _Nullable error))reply
{
__block int i = 0;
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];
context:(nonnull NSString *)context
bottleID:(nonnull NSString *)bottleID
reply:(nonnull void (^)(NSString * _Nullable,
- NSSet<NSString*>* _Nullable peerSyncingViewList,
- TPPolicy * _Nullable peerSyncingPolicy,
+ TPSyncingPolicy* _Nullable peerSyncingPolicy,
+ BOOL refetchWasNeeded,
NSError * _Nullable))reply {
__block int i = 0;
__block bool retry;
retry = true;
} else {
secerror("octagon: Can't talk with TrustedPeersHelper: %@", error);
- reply(nil, nil, nil, error);
+ reply(nil, nil, false, error);
}
++i;
}] preflightVouchWithBottleWithContainer:container
recoveryKey:(NSString*)recoveryKey
salt:(NSString*)salt
reply:(nonnull void (^)(NSString * _Nullable,
- NSSet<NSString*>* _Nullable peerSyncingViewList,
- TPPolicy * _Nullable peerSyncingPolicy,
+ TPSyncingPolicy* _Nullable peerSyncingPolicy,
NSError * _Nullable))reply {
__block int i = 0;
__block bool retry;
retry = true;
} else {
secerror("octagon: Can't talk with TrustedPeersHelper: %@", error);
- reply(nil, nil, nil, error);
+ reply(nil, nil, error);
}
++i;
}] preflightVouchWithRecoveryKeyWithContainer:container
voucherSig:(NSData *)voucherSig
ckksKeys:(NSArray<CKKSKeychainBackedKeySet*> *)viewKeySets
tlkShares:(NSArray<CKKSTLKShare*> *)tlkShares
- preapprovedKeys:(NSArray<NSData*> *)preapprovedKeys
+ preapprovedKeys:(nullable NSArray<NSData*> *)preapprovedKeys
reply:(void (^)(NSString * _Nullable peerID,
NSArray<CKRecord*>* _Nullable keyHierarchyRecords,
- NSSet<NSString*>* _Nullable viewSet,
- TPPolicy* _Nullable syncingPolicy,
+ TPSyncingPolicy* _Nullable syncingPolicy,
NSError * _Nullable error))reply
{
__block int i = 0;
retry = true;
} else {
secerror("octagon: Can't talk with TrustedPeersHelper: %@", error);
- reply(nil, nil, 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];
- (void)preflightPreapprovedJoinWithContainer:(NSString *)container
context:(NSString *)context
+ preapprovedKeys:(nullable NSArray<NSData*> *)preapprovedKeys
reply:(void (^)(BOOL launchOkay,
NSError * _Nullable error))reply
{
reply(NO, error);
}
++i;
- }] preflightPreapprovedJoinWithContainer:container context:context reply:reply];
+ }] preflightPreapprovedJoinWithContainer:container context:context preapprovedKeys:preapprovedKeys reply:reply];
} while (retry);
}
context:(NSString *)context
ckksKeys:(NSArray<CKKSKeychainBackedKeySet*> *)ckksKeys
tlkShares:(NSArray<CKKSTLKShare*> *)tlkShares
- preapprovedKeys:(NSArray<NSData*> *)preapprovedKeys
+ preapprovedKeys:(nullable NSArray<NSData*> *)preapprovedKeys
reply:(void (^)(NSString * _Nullable peerID,
NSArray<CKRecord*>* _Nullable keyHierarchyRecords,
- NSSet<NSString*>* _Nullable syncingViewList,
- TPPolicy* _Nullable syncingPolicy,
+ TPSyncingPolicy* _Nullable syncingPolicy,
NSError * _Nullable error))reply
{
__block int i = 0;
retry = true;
} else {
secerror("octagon: Can't talk with TrustedPeersHelper: %@", error);
- reply(nil, nil, nil, nil, error);
+ reply(nil, nil, nil, error);
}
++i;
- }] attemptPreapprovedJoinWithContainer:container context:context ckksKeys:ckksKeys tlkShares:tlkShares preapprovedKeys:preapprovedKeys reply:reply];
+ }] attemptPreapprovedJoinWithContainer:container
+ context:context
+ ckksKeys:ckksKeys
+ tlkShares:tlkShares
+ preapprovedKeys:preapprovedKeys
+ reply:reply];
} while (retry);
}
osVersion:(nullable NSString *)osVersion
policyVersion:(nullable NSNumber *)policyVersion
policySecrets:(nullable NSDictionary<NSString*,NSData*> *)policySecrets
- reply:(void (^)(TrustedPeersHelperPeerState* _Nullable peerState, NSError * _Nullable error))reply
+ syncUserControllableViews:(nullable NSNumber *)syncUserControllableViews
+ reply:(void (^)(TrustedPeersHelperPeerState* _Nullable peerState, TPSyncingPolicy* _Nullable policy, NSError * _Nullable error))reply
{
__block int i = 0;
__block bool retry;
retry = true;
} else {
secerror("octagon: Can't talk with TrustedPeersHelper: %@", error);
- reply(nil, error);
+ reply(nil, nil, error);
}
++i;
- }] updateWithContainer:container context:context deviceName:deviceName serialNumber:serialNumber osVersion:osVersion policyVersion:policyVersion policySecrets:policySecrets reply:reply];
+ }] updateWithContainer:container
+ context:context
+ deviceName:deviceName
+ serialNumber:serialNumber
+ osVersion:osVersion
+ policyVersion:policyVersion
+ policySecrets:policySecrets
+ syncUserControllableViews:syncUserControllableViews
+ reply:reply];
} while (retry);
}
- (void)fetchCurrentPolicyWithContainer:(NSString*)container
context:(NSString*)context
- reply:(void (^)(NSSet<NSString*>* _Nullable viewList,
- TPPolicy * _Nullable policy,
+ modelIDOverride:(NSString* _Nullable)modelIDOverride
+ reply:(void (^)(TPSyncingPolicy* _Nullable syncingPolicy,
+ TPPBPeerStableInfo_UserControllableViewStatus userControllableViewStatusOfPeers,
NSError * _Nullable error))reply
{
__block int i = 0;
retry = true;
} else {
secerror("octagon: Can't talk with TrustedPeersHelper: %@", error);
- reply(nil, nil, error);
+ reply(nil,
+ TPPBPeerStableInfo_UserControllableViewStatus_UNKNOWN,
+ error);
}
++i;
- }] fetchCurrentPolicyWithContainer:container context:context reply:reply];
+ }] fetchCurrentPolicyWithContainer:container context:context modelIDOverride:modelIDOverride reply:reply];
} while (retry);
}
recoveryKey:(NSString *)recoveryKey
salt:(NSString *)salt
ckksKeys:(NSArray<CKKSKeychainBackedKeySet*> *)ckksKeys
- reply:(void (^)(NSError* _Nullable error))reply
+ reply:(void (^)(NSArray<CKRecord*>* _Nullable keyHierarchyRecords,
+ NSError* _Nullable error))reply
{
__block int i = 0;
__block bool retry;
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];
}
+- (void)fetchViableEscrowRecordsWithContainer:(nonnull NSString *)container context:(nonnull NSString *)context forceFetch:(BOOL)forceFetch reply:(nonnull void (^)(NSArray<NSData *> * _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);
+}
+
+
+
@end
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 {
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"
--- /dev/null
+
+#ifndef OTClique_Private_h
+#define OTClique_Private_h
+
+#import <Security/OTClique.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface OTClique(Private)
+
++ (NSArray<NSData*>* _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 */
#ifndef OTClique_h
#define OTClique_h
+#if __OBJC2__
+
+#import <Foundation/Foundation.h>
+#import <Security/SecureObjectSync/SOSCloudCircleInternal.h>
+#import <Security/SecureObjectSync/SOSPeerInfo.h>
+#import <Security/SecureObjectSync/SOSTypes.h>
+#import <Security/OTConstants.h>
+#import <Security/SecRecoveryKey.h>
+
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*/
CliqueStatusError = -1 /*unable to determine circle status, inspect CFError to find out why */
};
-#import <Security/SecRecoveryKey.h>
-
-#if __OBJC2__
-
-#import <Foundation/Foundation.h>
-#import <Security/SecureObjectSync/SOSCloudCircleInternal.h>
-#import <Security/SecureObjectSync/SOSPeerInfo.h>
-#import <Security/SecureObjectSync/SOSTypes.h>
-#import <Security/OTConstants.h>
-
typedef NS_ENUM(NSInteger, OTCDPStatus) {
OTCDPStatusUnknown = 0,
OTCDPStatusDisabled = 1,
@interface OTConfigurationContext : NSObject
@property (nonatomic, copy) NSString* context;
+@property (nonatomic, copy) NSString* containerName;
@property (nonatomic, copy, nullable) NSString* dsid;
@property (nonatomic, copy, nullable) NSString* altDSID;
-@property (nonatomic, strong, nullable) SFSignInAnalytics* analytics;
@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;
*/
- (instancetype)initWithContextData:(OTConfigurationContext *)ctx;
-/*
- * Much like initWithContextData, but might fail. There are currently no failures possible.
- */
-- (instancetype _Nullable)initWithContextData:(OTConfigurationContext *)ctx error:(NSError**)error __deprecated_msg("Use initWithContextData instead");
-
/* *
* @abstract Establish a new clique, reset protected data
* Reset the clique
*/
- (NSDictionary<NSString*,NSString*>* _Nullable)peerDeviceNamesByPeerID:(NSError * __autoreleasing *)error;
-
/*
* CDP bit handling
*/
+ (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;
- (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
#import <Foundation/Foundation.h>
#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"
#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"
@implementation OTConfigurationContext
+
- (OTControl* _Nullable)makeOTControl:(NSError**)error
{
#if OCTAGON
[self.defaults removeObjectForKey:OTDefaultsOctagonEnable];
}
-- (instancetype)initWithContextData:(OTConfigurationContext *)ctx error:(NSError * __autoreleasing *)error
-{
- return [self initWithContextData:ctx];
-}
-
- (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];
}
NSAssert(false, @"OTClique is not implemented on this platform");
// make the build analyzer happy
- self = [super init];
+ if ((self = [super init])) {
+ }
return self;
#endif // OCTAGON
}
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];
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");
} 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");
secnotice("clique-newfriends", "makeNewFriends complete");
subTaskSuccess = true;
- OctagonSignpostEnd(performEscrowRecoverySignpost, OctagonSignpostNameMakeNewFriends, OctagonSignpostNumber1(OctagonSignpostNameMakeNewFriends), (int)subTaskSuccess);
+ OctagonSignpostEnd(newFriendsSignpost, OctagonSignpostNameMakeNewFriends, OctagonSignpostNumber1(OctagonSignpostNameMakeNewFriends), (int)subTaskSuccess);
return clique;
#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;
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
}];
subTaskSuccess = (restoreBottleError == nil) ? true : false;
- OctagonSignpostEnd(bottleRecoverySignPost, OctagonSignpostNamePerformBottleRecovery, OctagonSignpostNumber1(OctagonSignpostNamePerformBottleRecovery), (int)subTaskSuccess);
+ OctagonSignpostEnd(bottleRecoverySignPost, OctagonSignpostNamePerformOctagonJoin, OctagonSignpostNumber1(OctagonSignpostNamePerformOctagonJoin), (int)subTaskSuccess);
if(restoreBottleError) {
if(error){
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");
}
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);
}
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 {
}
- (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);
}
}
+- (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<NSString*>* 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");
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 {
- (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];
+ 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);
- }
+ bool result = SOSCCViewSet((__bridge CFSetRef)enabledViews, (__bridge CFSetRef)disabledViews);
BOOL viewSetResult = result ? YES : NO;
subTaskSuccess = result;
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);
#endif // OCTAGON
if([OTClique platformSupportsSOS]) {
- NSData* analyticsData = nil;
CFErrorRef joinErrorRef = NULL;
- 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);
- }
-
+ result = SOSCCRequestToJoinCircle(&joinErrorRef);
secnotice("clique-legacy", "sos requestToJoinCircle complete: %d %@", result, joinErrorRef);
if (error) {
*error = (NSError*)CFBridgingRelease(joinErrorRef);
}
}
++ (NSArray<NSData*>* _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<NSData*>* 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<NSData *> * _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
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;
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;
+ (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) {
}
}
- //reset ckks
- CKKSControl* ckksControl = [data makeCKKSControl:&localError];
- [ckksControl rpcResetCloudKit:nil reason:@"clique-reset-protected-data" reply:^(NSError* resetError){
- localError = resetError;
- }];
-
- if(localError) {
- secerror("clique-reset-protected-data: ckks cloudkit reset failed: %@", localError);
- if(error) {
- *error = localError;
- }
- return nil;
- } else {
- secnotice("clique-reset-protected-data", "ckks cloudkit reset succeeded");
- }
-
return clique;
#else // !OCTAGON
if(error) {
#include <stdbool.h>
bool OctagonIsEnabled(void);
+bool SecErrorIsNestedErrorCappingEnabled(void);
#if __OBJC__
extern NSString* OTProtocolPiggybacking;
extern const char * OTTrustStatusChangeNotification;
+extern NSString* OTEscrowRecordPrefix;
BOOL OctagonPlatformSupportsSOS(void);
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,
CuttlefishResetReasonTestGenerated = 6,
};
+extern NSString* const CuttlefishErrorDomain;
+extern NSString* const CuttlefishErrorRetryAfterKey;
+
#endif // __OBJC__
#endif /* OTConstants_h */
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
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) {
{
if(OctagonSOSFeatureIsEnabledOverrideSet) {
secnotice("octagon", "SOS Feature is %@ (overridden)", OctagonSOSFeatureIsEnabledOverride ? @"enabled" : @"disabled");
- return OctagonSOSFeatureIsEnabledOverrideSet;
+ return OctagonSOSFeatureIsEnabledOverride;
}
static bool sosEnabled = true;
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;
+}
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;
contextID:(NSString*)contextID
reply:(void (^)(NSError* _Nullable error))reply;
+
+- (void)fetchEscrowRecords:(NSString * _Nullable)container
+ contextID:(NSString*)contextID
+ forceFetch:(BOOL)forceFetch
+ reply:(void (^)(NSArray<NSData*>* _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;
+
@end
NS_ASSUME_NONNULL_END
}] 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
}] getCDPStatus:containerName contextID:contextID reply:reply];
}
+- (void)fetchEscrowRecords:(NSString * _Nullable)container
+ contextID:(NSString*)contextID
+ forceFetch:(BOOL)forceFetch
+ reply:(void (^)(NSArray<NSData*>* _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];
+}
+
+ (OTControl*)controlObject:(NSError* __autoreleasing *)error {
return [OTControl controlObject:false error:error];
}
@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;
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;
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<NSData*>* _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;
@end
NSXPCInterface* OTSetupControlProtocol(NSXPCInterface* interface);
#import "keychain/ot/OTControlProtocol.h"
#import "keychain/ot/OTJoiningConfiguration.h"
#import <Security/SecXPCHelper.h>
-
-#if OCTAGON
-#import <CloudKit/CloudKit.h>
-#import <CloudKit/CloudKit_Private.h>
-#import <utilities/debugging.h>
-#include <dlfcn.h>
-#import <KeychainCircle/KeychainCircle.h>
-#import <SecurityFoundation/SFKey.h>
-#endif // OCTAGON
-
+#include <utilities/debugging.h>
NSXPCInterface* OTSetupControlProtocol(NSXPCInterface* interface) {
#if OCTAGON
NSSet<Class> *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: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];
}
@catch(NSException* e) {
secerror("OTSetupControlProtocol failed, continuing, but you might crash later: %@", e);
-#if DEBUG
@throw e;
-#endif
}
#endif
- (BOOL)persistNewTrustState:(OTAccountMetadataClassC_TrustState)newState
error:(NSError**)error;
-- (BOOL)persistNewEpoch:(uint64_t)epoch error:(NSError**)error;
-
- (BOOL)persistAccountChanges:(OTAccountMetadataClassC* _Nullable (^)(OTAccountMetadataClassC* metadata))makeChanges
error:(NSError**)error;
- (NSDate *)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
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 {
NSError* localError = nil;
} 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* _Nullable (^)(OTAccountMetadataClassC*))makeChanges
error:(NSError**)error
{
});
}
-
@end
NSString* _Nullable peerID,
NSDictionary<NSString*, NSNumber*>* _Nullable peerCountByModelID,
BOOL isExcluded,
+ BOOL isLocked,
NSError * _Nullable))reply;
- (void)rpcFetchDeviceNamesByPeerID:(void (^)(NSDictionary<NSString*, NSString*>* _Nullable peers, NSError* _Nullable error))reply;
-- (void)rpcFetchAllViableBottles:(void (^)(NSArray<NSString*>* _Nullable sortedBottleIDs, NSArray<NSString*>* _Nullable sortedPartialEscrowRecordIDs, NSError* _Nullable error))reply;
+- (void)rpcFetchAllViableBottles:(void (^)(NSArray<NSString*>* _Nullable sortedBottleIDs,
+ NSArray<NSString*>* _Nullable sortedPartialEscrowRecordIDs,
+ NSError* _Nullable error))reply;
+
+- (void)rpcFetchAllViableEscrowRecords:(BOOL)forceFetch reply:(void (^)(NSArray<NSData*>* _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,
- (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;
- (OTOperationDependencies*)operationDependencies;
-- (void)attemptSOSUpgrade:(void (^)(NSError* _Nullable error))reply;
-
- (void)waitForOctagonUpgrade:(void (^)(NSError* error))reply NS_SWIFT_NAME(waitForOctagonUpgrade(reply:));
- (BOOL)waitForReady:(int64_t)timeOffset;
-
// For testing.
- (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)clearCKKSViewManager;
// Octagon Health Check Helpers
- (void)checkOctagonHealth:(BOOL)skipRateLimitingCheck reply:(void (^)(NSError * _Nullable error))reply;
-- (BOOL)postRepairCFU:(NSError**)error;
-- (void)postConfirmPasscodeCFU:(NSError**)error;
// For reporting
- (BOOL)machineIDOnMemoizedList:(NSString*)machineID error:(NSError**)error NS_SWIFT_NOTHROW;
#import "keychain/TrustedPeersHelper/TrustedPeersHelperProtocol.h"
+#include "keychain/SecureObjectSync/SOSInternal.h"
#import "keychain/analytics/CKKSLaunchSequence.h"
#import "keychain/categories/NSError+UsefulConstructors.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/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"
@interface OTCuttlefishContext () <OTCuttlefishAccountStateHolderNotifier>
{
- NSData* _vouchData;
- NSData* _vouchSig;
NSString* _bottleID;
NSString* _bottleSalt;
NSData* _entropy;
@property CKKSCondition *cloudKitAccountStateKnown;
@property CKKSNearFutureScheduler* suggestTLKUploadNotifier;
+@property CKKSNearFutureScheduler* requestPolicyCheckNotifier;
+
+@property OctagonAPSReceiver* apsReceiver;
// Make writable
@property (nullable) CKKSViewManager* viewManager;
// Dependencies (for injection)
@property id<OTSOSAdapter> sosAdapter;
@property id<CKKSPeerProvider> octagonAdapter;
-@property (readonly) Class<OctagonAPSConnection> apsConnectionClass;
@property (readonly) Class<SecEscrowRequestable> escrowRequestClass;
@property (nonatomic) BOOL initialBecomeUntrustedPosted;
_containerName = containerName;
_contextID = contextID;
+ _apsReceiver = [OctagonAPSReceiver receiverForNamedDelegatePort:SecCKKSAPSNamedPort
+ apsConnectionClass:apsConnectionClass];
+ [_apsReceiver registerCuttlefishReceiver:self forContainerName:self.containerName];
+
_viewManager = viewManager;
_initialBecomeUntrustedPosted = NO;
- _apsConnectionClass = apsConnectionClass;
_launchSequence = [[CKKSLaunchSequence alloc] initWithRocketName:@"com.apple.octagon.launch"];
_queue = dispatch_queue_create("com.apple.security.otcuttlefishcontext", DISPATCH_QUEUE_SERIAL);
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];
+ }];
}
return self;
}
}
[self.stateMachine handleFlag:OctagonFlagAccountIsAvailable];
-
+
+ if(OctagonIsOptimizationEnabled()){
+ [self.stateMachine handleFlag:OctagonFlagWarmEscrowRecordCache];
+ }
+
if(localError) {
if(error) {
*error = localError;
- (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];
{
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,
}
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]) {
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!
}
}
+ 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");
if([currentState isEqualToString:OctagonStateDetermineiCloudAccountState]) {
secnotice("octagon", "Determine iCloud account status");
- // TODO replace with OTDetermineHSA2AccountStatusOperation in <rdar://problem/54094162> 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:OctagonStateEnsureConsistency]) {
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
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
epoch:1];
} else if([currentState isEqualToString:OctagonStateBottleJoinVouchWithBottle]) {
- // <rdar://problem/57768490> Octagon: ensure we use appropriate CKKS policy when joining octagon with future policy
- // When we join with a bottle, we need to be sure that we've found all the TLKShares that we can reasonably unpack via the bottle
-
- OTVouchWithBottleOperation* pendingOp = [[OTVouchWithBottleOperation alloc] initWithDependencies:self.operationDependencies
- intendedState:OctagonStateInitiatorSetCDPBit
- 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;
+ 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:OctagonStateInitiatorSetCDPBit
- errorState:OctagonStateBecomeUntrusted
- recoveryKey:_recoveryKey];
-
- 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;
+ return [[OTVouchWithRecoveryKeyOperation alloc] initWithDependencies:self.operationDependencies
+ intendedState:OctagonStateInitiatorSetCDPBit
+ errorState:OctagonStateBecomeUntrusted
+ recoveryKey:_recoveryKey
+ saveVoucher:YES];
} else if([currentState isEqualToString:OctagonStateInitiatorSetCDPBit]) {
return [[OTSetCDPBitOperation alloc] initWithDependencies:self.operationDependencies
return op;
} else if ([currentState isEqualToString:OctagonStateInitiatorJoin]){
- OTJoinWithVoucherOperation* op = [[OTJoinWithVoucherOperation alloc] initWithDependencies:self.operationDependencies
- intendedState:OctagonStateBecomeReady
- ckksConflictState:OctagonStateInitiatorJoinCKKSReset
- errorState:OctagonStateBecomeUntrusted
- voucherData:_vouchData
- voucherSig:_vouchSig];
- 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
} else if ([currentState isEqualToString:OctagonStateInitiatorJoinAfterCKKSReset]){
return [[OTJoinWithVoucherOperation alloc] initWithDependencies:self.operationDependencies
- intendedState:OctagonStateBecomeReady
+ intendedState:OctagonStateBottlePreloadOctagonKeysInSOS
ckksConflictState:OctagonStateBecomeUntrusted
- errorState:OctagonStateBecomeUntrusted
- voucherData:_vouchData
- voucherSig:_vouchSig];
+ errorState:OctagonStateBecomeUntrusted];
} else if([currentState isEqualToString:OctagonStateResetBecomeUntrusted]) {
return [self becomeUntrustedOperation:OctagonStateResetAndEstablish];
} else if([currentState isEqualToString:OctagonStateResetAnyMissingTLKCKKSViews]) {
return [[OTResetCKKSZonesLackingTLKsOperation alloc] initWithDependencies:self.operationDependencies
- intendedState:OctagonStateEstablishEnableCDPBit
- errorState:OctagonStateError];
+ intendedState:OctagonStateEstablishEnableCDPBit
+ errorState:OctagonStateError];
} else if([currentState isEqualToString:OctagonStateEstablishEnableCDPBit]) {
return [[OTSetCDPBitOperation 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];
return [[OTUploadNewCKKSTLKsOperation alloc] initWithDependencies:self.operationDependencies
intendedState:OctagonStateReady
ckksConflictState:OctagonStateAssistCKKSTLKUploadCKKSReset
+ peerMissingState:OctagonStateReadyUpdated
errorState:OctagonStateReady];
} else if([currentState isEqualToString:OctagonStateAssistCKKSTLKUploadCKKSReset]) {
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]) {
}
}
+ 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");
[flags _onqueueRemoveFlag:OctagonFlagCDPEnabled];
}
- secnotice("octagon", "Entering state ready");
[[CKKSAnalytics logger] setDateProperty:[NSDate date] forKey:OctagonAnalyticsLastKeystateReady];
[self.launchSequence launch];
return nil;
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;
}
// 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];
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) {
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");
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 {
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<OctagonStateTransitionOperationProtocol>* _Nullable)cloudKitAccountNewlyAvailableOperation
+- (CKKSResultOperation<OctagonStateTransitionOperationProtocol>* _Nullable)cloudKitAccountNewlyAvailableOperation:(OctagonFlag*)warmEscrowCache
{
WEAKIFY(self);
+
return [OctagonStateTransitionOperation named:@"octagon-icloud-account-available"
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<NSData *> *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);
} 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];
}
}];
NSString* egoPeerID,
NSDictionary<NSString*, NSNumber*>* _Nullable peerCountByModelID,
BOOL isExcluded,
+ BOOL isLocked,
NSError * _Nullable error) {
BOOL hasIdentity = egoPeerID != nil;
secnotice("octagon-health", "repairAccountIfTrustedByTPHWithIntendedState status: %ld, peerID: %@, isExcluded: %d error: %@", (long)status, egoPeerID, isExcluded, error);
return;
}
+ if (isLocked) {
+ secnotice("octagon-health", "device is locked");
+ nextState = OctagonStateWaitForUnlock;
+ return;
+ }
+
if(OctagonAuthoritativeTrustIsEnabled() && hasIdentity && status == CliqueStatusIn) {
secnotice("octagon-health", "TPH believes we're trusted, accepting ego peerID as %@", egoPeerID);
return nextState;
}
-- (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];
NSString* _Nullable egoPeerID,
NSDictionary<NSString*, NSNumber*>* _Nullable peerCountByModelID,
BOOL isExcluded,
+ BOOL isLocked,
NSError * _Nullable error) {
STRONGIFY(self);
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;
}
}
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
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, nil);
+ reply(status, NO, hasIdentity, isLocked, nil);
return;
} else if(circleError) {
} else if(sosStatus == kSOSCCInCircle) {
secnotice("octagon", "SOS is InCircle, not posting CFU");
- reply(status, NO, hasIdentity, nil);
+ 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;
}];
}
[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;
[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
*/
__block NSString* peerID = nil;
NSError* localError = nil;
- __block NSSet<NSString*>* viewList = nil;
- __block TPPolicy* policy = nil;
+ __block TPSyncingPolicy* policy = nil;
[self.accountMetadataStore persistAccountChanges:^OTAccountMetadataClassC * _Nullable(OTAccountMetadataClassC * _Nonnull metadata) {
peerID = metadata.peerID;
- viewList = metadata.syncingViews.count > 0 ? [NSSet setWithArray:metadata.syncingViews] : nil;
- policy = metadata.hasSyncingPolicy ? [metadata getTPPolicy] : nil;
+
+ policy = metadata.hasSyncingPolicy ? [metadata getTPSyncingPolicy] : nil;
if(metadata.attemptedJoin == OTAccountMetadataClassC_AttemptedAJoinState_ATTEMPTED) {
return nil;
if(!peerID || localError) {
secerror("octagon-ckks: No peer ID to pass to CKKS. Syncing will be disabled.");
- } else if(!viewList || !policy) {
+ } else if(!policy) {
secerror("octagon-ckks: No memoized CKKS policy, re-fetching");
op.nextState = OctagonStateRefetchCKKSPolicy;
return;
} else {
- secnotice("octagon-ckks", "Initializing CKKS views with view list %@ and policy %@", viewList, policy);
- [self.viewManager setSyncingViews:viewList
- sortingPolicy:policy];
+ 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
+ OctagonPendingFlag* pendingFlag = [[OctagonPendingFlag alloc] initWithFlag:OctagonFlagAttemptUserControllableViewStatusUpgrade
+ conditions:OctagonPendingConditionsDeviceUnlocked];
+ [self.stateMachine handlePendingFlag:pendingFlag];
+ } 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);
+ }
+ }
+ }
+
+ secnotice("octagon-ckks", "Initializing CKKS views with policy %@: %@", policy, policy.viewList);
- OctagonCKKSPeerAdapter* octagonAdapter = [[OctagonCKKSPeerAdapter alloc] initWithPeerID:peerID operationDependencies:[self operationDependencies]];
+ [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;
}
[view beginTrustedOperation:peerProviders
- suggestTLKUpload:self.suggestTLKUploadNotifier];
+ suggestTLKUpload:self.suggestTLKUploadNotifier
+ requestPolicyCheck:self.requestPolicyCheckNotifier];
}
}
[self notifyTrustChanged:OTAccountMetadataClassC_TrustState_TRUSTED];
}
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;
}
if(accountMetadata.lastHealthCheckup == 0) {
return nil;
}
- return [[NSDate alloc] initWithTimeIntervalSince1970: accountMetadata.lastHealthCheckup];
+ return [[NSDate alloc] initWithTimeIntervalSince1970: ((NSTimeInterval)accountMetadata.lastHealthCheckup) / 1000.0];
}
- (void)requestTrustedDeviceListRefresh
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;
}
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;
return @{
OctagonStateInitiatorSetCDPBit: @{
OctagonStateInitiatorUpdateDeviceList: @{
- OctagonStateInitiatorJoin: @{
- OctagonStateBecomeReady: @{
- OctagonStateReady: [OctagonStateTransitionPathStep success],
- },
-
- OctagonStateInitiatorJoinCKKSReset: @{
- OctagonStateInitiatorJoinAfterCKKSReset: @{
- OctagonStateBecomeReady: @{
- OctagonStateReady: [OctagonStateTransitionPathStep success]
+ OctagonStateInitiatorJoin: @{
+ OctagonStateBottlePreloadOctagonKeysInSOS: @{
+ OctagonStateBecomeReady: @{
+ OctagonStateReady: [OctagonStateTransitionPathStep success],
+ },
+ },
+ OctagonStateInitiatorJoinCKKSReset: @{
+ OctagonStateInitiatorJoinAfterCKKSReset: @{
+ OctagonStateBottlePreloadOctagonKeysInSOS: @{
+ OctagonStateBecomeReady: @{
+ OctagonStateReady: [OctagonStateTransitionPathStep success]
+ },
+ },
+ },
},
- },
},
- },
},
},
};
reply:(void (^)(NSError * _Nullable error))reply
{
- _vouchData = vouchData;
- _vouchSig = vouchSig;
-
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]];
}
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
NSString* egoPeerID,
NSDictionary<NSString*, NSNumber*>* _Nullable peerCountByModelID,
BOOL isExcluded,
+ BOOL isLocked,
NSError *error))reply
{
CliqueStatus status = CliqueStatusAbsent;
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);
}
NSString* _Nullable peerID,
NSDictionary<NSString*, NSNumber*>* _Nullable peerCountByModelID,
BOOL isExcluded,
+ BOOL isLocked,
NSError *error))reply
{
__block NSError* localError = nil;
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;
}
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");
__block NSDictionary<NSString*, NSNumber*>* peerModelCounts = nil;
__block BOOL excluded = NO;
__block CliqueStatus trustStatus = CliqueStatusError;
+ __block BOOL isLocked = NO;
[self.cuttlefishXPCWrapper trustStatusWithContainer:self.containerName
context:self.contextID
peerID = egoStatus.egoPeerID;
excluded = egoStatus.isExcluded;
peerModelCounts = egoStatus.viablePeerCountsByModelID;
+ isLocked = egoStatus.isLocked;
localError = xpcError;
if(xpcError) {
}
}];
- reply(trustStatus, peerID, peerModelCounts, excluded, localError);
+ reply(trustStatus, peerID, peerModelCounts, excluded, isLocked, localError);
}
- (void)rpcFetchAllViableBottles:(void (^)(NSArray<NSString*>* _Nullable sortedBottleIDs, NSArray<NSString*>* _Nullable sortedPartialEscrowRecordIDs, NSError* _Nullable error))reply
}];
}
+- (void)rpcFetchAllViableEscrowRecords:(BOOL)forceFetch reply:(void (^)(NSArray<NSData*>* _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<NSData *> * _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,
reply:reply];
}
-#pragma mark --- Testing
-- (void) setAccountStateHolder:(OTCuttlefishAccountStateHolder*)accountMetadataStore
+- (void)rpcFetchUserControllableViewsSyncingStatus:(void (^)(BOOL areSyncing, NSError* _Nullable error))reply
+{
+ 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
{
- self.accountMetadataStore = accountMetadataStore;
+#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
return YES;
}
-- (void)postConfirmPasscodeCFU:(NSError**)error
+- (BOOL)postConfirmPasscodeCFU:(NSError**)error
{
+ BOOL ret = NO;
NSError* localError = nil;
- [self.followupHandler postFollowUp:OTFollowupContextTypeOfflinePasscodeChange error:&localError];
+ ret = [self.followupHandler postFollowUp:OTFollowupContextTypeOfflinePasscodeChange error:&localError];
if(localError){
secerror("octagon-health: CoreCDP offline passcode change failed: %@", localError);
*error = localError;
}
- else{
- secnotice("octagon-health", "CoreCDP offline passcode change success");
- }
+ return ret;
}
- (void)checkOctagonHealth:(BOOL)skipRateLimitingCheck reply:(void (^)(NSError * _Nullable error))reply
OctagonStateHealthCheckReset: [OctagonStateTransitionPathStep success],
OctagonStateHealthCheckLeaveClique: [OctagonStateTransitionPathStep success],
},
+ OctagonStateWaitForUnlock: [OctagonStateTransitionPathStep success],
},
},
OctagonStateWaitForCDP: [OctagonStateTransitionPathStep success],
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
- policyOverride:self.policyOverride];
-
- OctagonStateTransitionRequest<OTSOSUpgradeOperation*>* 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]) {
}
}
- 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],
+ },
},
},
}];
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,
OTAuthKitMachineIDMissing = 46,
OTAuthKitPrimaryAccountHaveNoDSID = 47,
OTErrorFailedToLeaveClique = 48,
+ OTErrorSyncPolicyMissing = 49,
};
#define OTMasterSecretLength 72
TrustedPeersHelperErrorNoPeersPreapprovePreparedIdentity = 14,
TrustedPeersHelperErrorCodeUntrustedRecoveryKeys = 32,
TrustedPeersHelperErrorCodeNotEnrolled = 34,
+ TrustedPeersHelperErrorNoPeersPreapprovedBySelf = 47,
};
// See cuttlefish/CuttlefishService/Sources/CuttlefishService/CuttlefishError.swift
CuttlefishErrorPreflightGraphValidationError = 1022,
CuttlefishErrorKeyHierarchyAlreadyExists = 1033,
CuttlefishErrorDuplicatePeerIdUnderConsideration = 1034,
+ CuttlefishErrorIneligibleExclusionDenied = 1035,
+ CuttlefishErrorMultiplePreapprovedJoinDenied = 1036,
+ CuttlefishErrorUpdateTrustPeerNotFound = 1037,
};
NS_ASSUME_NONNULL_END
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";
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 = OctagonStateWaitForUnlock;
+ self.nextState = OctagonStateWaitForClassCUnlock;
return;
}
- (NSString*)osVersion;
/* Returns the serial number as a string. */
-- (NSString*)serialNumber;
+- (NSString* _Nullable)serialNumber;
/* register for deviceName updates */
- (void)registerForDeviceNameUpdates:(id<OTDeviceInformationNameUpdateListener>)listener;
#else
-- (NSString*)serialNumber
+- (NSString* _Nullable)serialNumber
{
io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"));
if (platformExpert == MACH_PORT_NULL) {
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;
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;
[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"
ckksKeys:viewKeySets
tlkShares:pendingTLKShares
preapprovedKeys:publicSigningSPKIs
- reply:^(NSString * _Nullable peerID, NSArray<CKRecord*>* _Nullable keyHierarchyRecords, NSError * _Nullable error) {
+ reply:^(NSString * _Nullable peerID,
+ NSArray<CKRecord*>* _Nullable keyHierarchyRecords,
+ TPSyncingPolicy* _Nullable syncingPolicy,
+ NSError * _Nullable error) {
STRONGIFY(self);
[[CKKSAnalytics logger] logResultForEvent:OctagonEventEstablishIdentity hardFailure:true result:error];
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;
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];
#if OCTAGON
#import <Foundation/Foundation.h>
+#import <dispatch/dispatch.h>
#import "keychain/ckks/CKKSGroupOperation.h"
#import "keychain/ckks/CKKSKeychainBackedKey.h"
// Any new TLKShares that CKKS suggested we upload along with this keyset
@property NSArray<CKKSTLKShare*>* pendingTLKShares;
-- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies;
+// Any views that didn't provide a keyset within time
+@property NSSet<NSString*>* 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<CKKSKeychainView*>*)views;
@end
@interface OTFetchCKKSKeysOperation ()
@property NSSet<CKKSKeychainView*>* views;
@property CKKSViewManager* manager;
+
+@property BOOL fetchBeforeGettingKeyset;
@end
@implementation OTFetchCKKSKeysOperation
- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies
+ refetchNeeded:(BOOL)refetchNeeded
{
if((self = [super init])) {
_manager = dependencies.viewManager;
_tlkShares = @[];
_pendingTLKShares = @[];
_incompleteKeySets = @[];
+
+ _desiredTimeout = SecCKKSTestsEnabled() ? 5*NSEC_PER_SEC : 15*NSEC_PER_SEC;
+
+ _fetchBeforeGettingKeyset = refetchNeeded;
+
+ _viewsTimedOutWithoutKeysets = [NSSet set];
}
return self;
}
_tlkShares = @[];
_pendingTLKShares = @[];
_incompleteKeySets = @[];
+
+ _desiredTimeout = SecCKKSTestsEnabled() ? 5*NSEC_PER_SEC : 15*NSEC_PER_SEC;
+
+ _fetchBeforeGettingKeyset = NO;
+
+ _viewsTimedOutWithoutKeysets = [NSSet set];
}
return self;
}
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);
-
- NSMutableArray<CKKSKeychainBackedKeySet*>* viewKeySets = [NSMutableArray array];
- NSMutableArray<CKKSCurrentKeySet*>* ckksBrokenKeySets = [NSMutableArray array];
- NSMutableArray<CKKSTLKShare*>* tlkShares = [NSMutableArray array];
- NSMutableArray<CKKSTLKShare*>* pendingTLKShares = [NSMutableArray array];
-
- for(CKKSResultOperation<CKKSKeySetProviderOperationProtocol>* op in keyOps) {
- if(op.error) {
- secnotice("octagon-ckks", "No keys for zone %@: %@", op.zoneName, op.error);
- continue;
- }
-
- NSError* localerror = nil;
- CKKSKeychainBackedKeySet* keyset = [op.keyset asKeychainBackedSet:&localerror];
-
- 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];
- }
- }
-
- for(CKKSTLKShareRecord* tlkShareRecord in op.keyset.tlkShares) {
- [tlkShares addObject:tlkShareRecord.share];
- }
- secnotice("octagon-ckks", "Have %u tlk shares", (uint32_t)op.keyset.tlkShares.count);
-
- 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);
- }
-
- self.viewKeySets = viewKeySets;
- self.incompleteKeySets = ckksBrokenKeySets;
- self.tlkShares = tlkShares;
- self.pendingTLKShares = pendingTLKShares;
-
- secnotice("octagon-ckks", "Fetched %d key sets, %d broken key sets, %d tlk shares, and %d pendingTLKShares",
- (int)self.viewKeySets.count,
- (int)self.incompleteKeySets.count,
- (int)self.tlkShares.count,
- (int)self.pendingTLKShares.count);
- }];
+ STRONGIFY(self);
+
+ NSMutableArray<CKKSKeychainBackedKeySet*>* viewKeySets = [NSMutableArray array];
+ NSMutableArray<CKKSCurrentKeySet*>* ckksBrokenKeySets = [NSMutableArray array];
+ NSMutableArray<CKKSTLKShare*>* tlkShares = [NSMutableArray array];
+ NSMutableArray<CKKSTLKShare*>* pendingTLKShares = [NSMutableArray array];
+
+ NSMutableSet<NSString*>* viewsMIA = [NSMutableSet set];
+
+ for(CKKSResultOperation<CKKSKeySetProviderOperationProtocol>* op in keyOps) {
+ if(op.error) {
+ secnotice("octagon-ckks", "No keys for zone %@: %@", op.zoneName, op.error);
+
+ if([op.error.domain isEqualToString:CKKSResultErrorDomain] && op.error.code == CKKSResultTimedOut) {
+ [viewsMIA addObject:op.zoneName];
+ }
+ continue;
+ }
+
+ NSError* localerror = nil;
+ CKKSCurrentKeySet* keyset = op.keyset;
+ CKKSKeychainBackedKeySet* keychainBackedKeyset = [keyset asKeychainBackedSet:&localerror];
+
+ 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];
+ }
+ }
+
+ for(CKKSTLKShareRecord* tlkShareRecord in op.keyset.tlkShares) {
+ [tlkShares addObject:tlkShareRecord.share];
+ }
+
+ 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<CKKSKeySetProviderOperationProtocol>* op in keyOps) {
[proceedWithKeys addDependency: op];
WEAKIFY(self);
[self.deps.cuttlefishXPCWrapper fetchCurrentPolicyWithContainer:self.deps.containerName
context:self.deps.contextID
- reply:^(NSSet<NSString*>* _Nullable viewList,
- TPPolicy* _Nullable policy,
+ modelIDOverride:nil
+ reply:^(TPSyncingPolicy* _Nullable syncingPolicy,
+ TPPBPeerStableInfo_UserControllableViewStatus userControllableViewStatusOfPeers,
NSError* _Nullable error) {
STRONGIFY(self);
[[CKKSAnalytics logger] logResultForEvent:OctagonEventFetchViews hardFailure:true result:error];
return;
}
- secnotice("octagon-ckks", "Received policy %@ with view list: %@", policy, viewList);
+ secnotice("octagon-ckks", "Received syncing policy %@ with view list: %@", syncingPolicy, syncingPolicy.viewList);
// Write them down before continuing
NSError* stateError = nil;
[self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nullable(OTAccountMetadataClassC * _Nonnull metadata) {
- metadata.syncingViews = [viewList mutableCopy];
- [metadata setTPPolicy:policy];
+ [metadata setTPSyncingPolicy:syncingPolicy];
return metadata;
} error:&stateError];
return;
}
- [self.deps.viewManager setSyncingViews:viewList sortingPolicy:policy];
+ [self.deps.viewManager setCurrentSyncingPolicy:syncingPolicy];
self.nextState = self.intendedState;
}];
- (BOOL)clearFollowUp:(OTFollowupContextType)contextType
error:(NSError **)error;
-- (NSDictionary *)sysdiagnoseStatus;
+- (NSDictionary *_Nullable)sysdiagnoseStatus;
- (NSDictionary<NSString*,NSNumber*> *)sfaStatus;
@end
}
-- (NSDictionary *)sysdiagnoseStatus
+- (NSDictionary *_Nullable)sysdiagnoseStatus
{
NSMutableDictionary *pendingCFUs = nil;
- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies
intendedState:(OctagonState*)intendedState
ckksConflictState:(OctagonState*)ckksConflictState
- errorState:(OctagonState*)errorState
- voucherData:(NSData*)voucherData
- voucherSig:(NSData*)voucherSig;
+ errorState:(OctagonState*)errorState;
-@property (nonatomic) NSData* voucherData;
-@property (nonatomic) NSData* voucherSig;
+@property (nullable) NSData* voucherData;
+@property (nullable) NSData* voucherSig;
-@property (nonatomic) NSString* peerID;
+@property (nullable) NSString* peerID;
@end
intendedState:(OctagonState*)intendedState
ckksConflictState:(OctagonState*)ckksConflictState
errorState:(OctagonState*)errorState
- voucherData:(NSData*)voucherData
- voucherSig:(NSData*)voucherSig
{
if((self = [super init])) {
_deps = dependencies;
_nextState = errorState;
_ckksConflictState = ckksConflictState;
- _voucherData = voucherData;
- _voucherSig = voucherSig;
+ _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"
preapprovedKeys:publicSigningSPKIs
reply:^(NSString * _Nullable peerID,
NSArray<CKRecord*>* keyHierarchyRecords,
- NSSet<NSString*>* _Nullable syncingViews,
- TPPolicy* _Nullable syncingPolicy,
+ TPSyncingPolicy* _Nullable syncingPolicy,
NSError * _Nullable error) {
STRONGIFY(self);
if(error){
[[CKKSAnalytics logger] logSuccessForEventNamed:OctagonEventJoinWithVoucher];
- [self.deps.viewManager setSyncingViews:syncingViews sortingPolicy:syncingPolicy];
+ [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.syncingViews = [syncingViews mutableCopy];
- [metadata setTPPolicy:syncingPolicy];
+
+ metadata.voucher = nil;
+ metadata.voucherSignature = nil;
+
+ [metadata setTPSyncingPolicy:syncingPolicy];
return metadata;
} error:&localError];
if(!persisted || localError) {
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;
}
- (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"];
#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 <OctagonStateTransitionOperationProtocol>
-- (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
#import "utilities/debugging.h"
@interface OTLocalResetOperation ()
-@property NSString* containerName;
-@property NSString* contextID;
-@property CuttlefishXPCWrapper* cuttlefishXPCWrapper;
+@property OTOperationDependencies* deps;
+
@property NSOperation* finishedOp;
@end
@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;
}
[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];
- (instancetype)initWithSOSAdapter:(id<OTSOSAdapter>)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
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];
}
NSString * _Nullable peerID,
NSDictionary<NSString *,NSNumber *> * _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;
NSString* egoPeerID,
NSDictionary<NSString *,NSNumber *> * _Nullable peerCountByModelID,
BOOL isExcluded,
+ BOOL isLocked,
NSError * _Nullable error) {
reply(status, error);
}];
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]);
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);
[cfshContext joinWithRecoveryKey:recoveryKey reply:^(NSError *error) {
if ((error.code == TrustedPeersHelperErrorCodeNotEnrolled || error.code == TrustedPeersHelperErrorCodeUntrustedRecoveryKeys)
&& [error.domain isEqualToString:TrustedPeersHelperErrorDomain]){
- // If we hit either of these errors, let's reset and establish octagon then enroll this recovery key in the new circle
+ // 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];
} 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 {
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];
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];
}];
}
-
- (void)getCDPStatus:(NSString * _Nullable)containerName
contextID:(nonnull NSString *)contextID
reply:(nonnull void (^)(OTCDPStatus, NSError * _Nullable))reply {
reply(localError);
}
+- (void)fetchEscrowRecords:(NSString * _Nullable)containerName
+ contextID:(NSString*)contextID
+ forceFetch:(BOOL)forceFetch
+ reply:(nonnull void (^)(NSArray<NSData *> * _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<NSData *> * _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;
+ }
+
+ secerror("octagon-user-controllable-views: succesfully fetched status as: %@", areSyncing ? @"enabled" : @"paused");
+ reply(areSyncing, nil);
+ }];
+}
+
@end
#endif
--- /dev/null
+/*
+ * 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 <Foundation/Foundation.h>
+
+#import "keychain/ckks/CKKSGroupOperation.h"
+#import "keychain/ot/OTOperationDependencies.h"
+#import "keychain/ot/OTOperationDependencies.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface OTModifyUserControllableViewStatusOperation : CKKSGroupOperation <OctagonStateTransitionOperationProtocol>
+
+// 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
--- /dev/null
+/*
+ * 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 <TrustedPeers/TrustedPeers.h>
+#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
--- /dev/null
+/*
+ * 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 <Foundation/Foundation.h>
+
+#import "keychain/ckks/CKKSGroupOperation.h"
+#import "keychain/ot/OctagonStateMachineHelpers.h"
+#import "keychain/ot/OTOperationDependencies.h"
+
+@class OTCuttlefishContext;
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface OTPreloadOctagonKeysOperation : CKKSGroupOperation <OctagonStateTransitionOperationProtocol>
+@property OctagonState* nextState;
+- (instancetype)init NS_UNAVAILABLE;
+- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies
+ intendedState:(OctagonState*)intendedState
+ errorState:(OctagonState*)errorState;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // OCTAGON
--- /dev/null
+/*
+ * 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 <utilities/debugging.h>
+
+#import <SecurityFoundation/SecurityFoundation.h>
+#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 <Security/SecKey.h>
+#import <Security/SecKeyPriv.h>
+
+#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<CKKSSelfPeer> 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
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
osVersion:self.deviceInfo.osVersion
policyVersion:self.policyOverride
policySecrets:nil
+ syncUserControllableViews:TPPBPeerStableInfo_UserControllableViewStatus_FOLLOWING
signingPrivKeyPersistentRef:signingKeyPersistRef
encPrivKeyPersistentRef:encryptionKeyPersistRef
reply:^(NSString * _Nullable peerID,
NSData * _Nullable permanentInfoSig,
NSData * _Nullable stableInfo,
NSData * _Nullable stableInfoSig,
- NSSet<NSString*>* _Nullable syncingViews,
- TPPolicy* _Nullable syncingPolicy,
+ TPSyncingPolicy* _Nullable syncingPolicy,
NSError * _Nullable error) {
STRONGIFY(self);
[[CKKSAnalytics logger] logResultForEvent:OctagonEventPrepareIdentity hardFailure:true result:error];
NSError* localError = nil;
- secnotice("octagon-ckks", "New syncing policy: %@ views: %@", syncingPolicy, syncingViews);
+ 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.syncingViews = [syncingViews mutableCopy];
- [metadata setTPPolicy:syncingPolicy];
+ [metadata setTPSyncingPolicy:syncingPolicy];
return metadata;
} error:&localError];
}
// Let CKKS know of the new policy, so it can spin up
- [self.deps.viewManager setSyncingViews:syncingViews sortingPolicy:syncingPolicy];
+ [self.deps.viewManager setCurrentSyncingPolicy:syncingPolicy];
self.nextState = self.intendedState;
[self runBeforeGroupFinished:self.finishedOp];
fetchRecordRecordsOperationClass:(Class<CKKSFetchRecordsOperation>) fetchRecordRecordsOperationClass
{
- self = [super init];
- if(self){
+ if ((self = [super init])) {
_container = container;
_recordName = [recordName copy];
_localSettingName = [localSettingName copy];
}];
[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"
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);
// 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];
- (SOSCCStatus)circleStatus:(NSError**)error;
- (id<CKKSSelfPeer> _Nullable)currentSOSSelf:(NSError**)error;
- (NSSet<id<CKKSRemotePeerProtocol>>* _Nullable)fetchTrustedPeers:(NSError**)error;
-- (void)updateOctagonKeySetWithAccount:(id<CKKSSelfPeer>)currentSelfPeer error:(NSError**)error;
+- (BOOL)updateOctagonKeySetWithAccount:(id<CKKSSelfPeer>)currentSelfPeer error:(NSError**)error;
+- (BOOL)preloadOctagonKeySetOnAccount:(id<CKKSSelfPeer>)currentSelfPeer error:(NSError**)error;
+- (BOOL)updateCKKS4AllStatus:(BOOL)status error:(NSError**)error;
+
+- (BOOL)safariViewSyncingEnabled:(NSError**)error __attribute__((swift_error(nonnull_error)));
@end
@interface OTSOSActualAdapter : NSObject <OTSOSAdapter>
return peerSet;
}
-- (void)updateOctagonKeySetWithAccount:(id<CKKSSelfPeer>)currentSelfPeer error:(NSError**)error {
+
+- (BOOL)preloadOctagonKeySetOnAccount:(id<CKKSSelfPeer>)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<CKKSSelfPeer>)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);
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);
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<CKKSPeerUpdateListener>)listener {
return result;
}
+
+- (BOOL)safariViewSyncingEnabled:(NSError**)error
+{
+ CFErrorRef viewCFError = NULL;
+ SOSViewResultCode result = SOSCCView(kSOSViewAutofillPasswords, kSOSCCViewQuery, &viewCFError);
+
+ if(viewCFError) {
+ if(error) {
+ *error = CFBridgingRelease(viewCFError);
+ } else {
+ CFReleaseNull(viewCFError);
+ }
+ return NO;
+ }
+
+ return result == kSOSCCViewMember;
+}
@end
@implementation OTSOSMissingAdapter
return nil;
}
-- (void)updateOctagonKeySetWithAccount:(nonnull id<CKKSSelfPeer>)currentSelfPeer error:(NSError *__autoreleasing _Nullable * _Nullable)error {
+- (BOOL)updateOctagonKeySetWithAccount:(nonnull id<CKKSSelfPeer>)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
trustedPeersError:unimplementedError];
}
+- (BOOL)safariViewSyncingEnabled:(NSError**)error
+{
+ return NO;
+}
+
+- (BOOL)preloadOctagonKeySetOnAccount:(nonnull id<CKKSSelfPeer>)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
@property NSOperation* finishedOp;
@property OTUpdateTrustedDeviceListOperation* updateOp;
+
+@property (nullable) NSArray<NSData*>* peerPreapprovedSPKIs;
@end
@implementation OTSOSUpgradeOperation
fatal = true;
}
+ if([self.error.domain isEqualToString:TrustedPeersHelperErrorDomain] && self.error.code == TrustedPeersHelperErrorNoPeersPreapprovedBySelf) {
+ secnotice("octagon-sos", "SOS upgrade error is 'we don't preapprove anyone'; retrying immediately is useless: %@", self.error);
+ fatal = true;
+ }
+
if(!fatal) {
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
}];
[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;
}
}
+ 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
osVersion:self.deviceInfo.osVersion
policyVersion:self.policyOverride
policySecrets:nil
+ syncUserControllableViews:safariViewEnabled ?
+ TPPBPeerStableInfo_UserControllableViewStatus_ENABLED :
+ TPPBPeerStableInfo_UserControllableViewStatus_DISABLED
signingPrivKeyPersistentRef:signingKeyPersistRef
encPrivKeyPersistentRef:encryptionKeyPersistRef
reply:^(NSString * _Nullable peerID,
NSData * _Nullable permanentInfoSig,
NSData * _Nullable stableInfo,
NSData * _Nullable stableInfoSig,
- NSSet<NSString*>* syncingViews,
- TPPolicy* _Nullable syncingPolicy,
+ TPSyncingPolicy* _Nullable syncingPolicy,
NSError * _Nullable error) {
STRONGIFY(self);
NSError* localError = nil;
BOOL persisted = [self.deps.stateHolder persistAccountChanges:^OTAccountMetadataClassC * _Nullable(OTAccountMetadataClassC * _Nonnull metadata) {
- metadata.syncingViews = [syncingViews mutableCopy];
- [metadata setTPPolicy:syncingPolicy];
+ [metadata setTPSyncingPolicy:syncingPolicy];
return metadata;
} error:&localError];
return;
}
- [self.deps.viewManager setSyncingViews:syncingViews sortingPolicy:syncingPolicy];
+ [self.deps.viewManager setCurrentSyncingPolicy:syncingPolicy];
[self afterPrepare];
}];
WEAKIFY(self);
[self.deps.cuttlefishXPCWrapper preflightPreapprovedJoinWithContainer:self.deps.containerName
context:self.deps.contextID
+ preapprovedKeys:self.peerPreapprovedSPKIs
reply:^(BOOL launchOkay, NSError * _Nullable error) {
STRONGIFY(self);
- // Preflight preapprovedjoin should return the policy used by the peers we eventually will trust
- // <rdar://problem/57768490> Octagon: ensure we use appropriate CKKS policy when joining octagon with future policy
-
[[CKKSAnalytics logger] logResultForEvent:OctagonEventUpgradePreflightPreapprovedJoin hardFailure:true result:error];
if(error) {
secerror("octagon-sos: preflightPreapprovedJoin failed: %@", error);
{
WEAKIFY(self);
- OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps];
+ OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps
+ refetchNeeded:NO];
[self runBeforeGroupFinished:fetchKeysOp];
secnotice("octagon-sos", "Fetching keys from CKKS");
{
WEAKIFY(self);
- secnotice("octagon-sos", "Fetching trusted peers from SOS");
-
- NSArray<NSData*>* 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");
- }
-
- secnotice("octagon-sos", "Beginning SOS upgrade with %d key sets and %d SOS peers", (int)viewKeySets.count, (int)publicSigningSPKIs.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
+ preapprovedKeys:self.peerPreapprovedSPKIs
reply:^(NSString * _Nullable peerID,
NSArray<CKRecord*>* keyHierarchyRecords,
- NSSet<NSString*>* _Nullable syncingViewList,
- TPPolicy* _Nullable syncingPolicy,
+ TPSyncingPolicy* _Nullable syncingPolicy,
NSError * _Nullable error) {
STRONGIFY(self);
[self requestSilentEscrowUpdate];
secerror("octagon-sos: attemptPreapprovedJoin succeded");
- [self.deps.viewManager setSyncingViews:syncingViewList sortingPolicy:syncingPolicy];
+ [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.syncingViews = [syncingViewList mutableCopy];
- [metadata setTPPolicy:syncingPolicy];
+ [metadata setTPSyncingPolicy:syncingPolicy];
return metadata;
} error:&localError];
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"
recoveryKey:self.recoveryKey
salt:salt
ckksKeys:viewKeySets
- reply:^(NSError * _Nullable setError) {
+ reply:^(NSArray<CKRecord*>* _Nullable keyHierarchyRecords,
+ NSError * _Nullable setError) {
STRONGIFY(self);
if(setError){
[[CKKSAnalytics logger] logResultForEvent:OctagonEventSetRecoveryKey hardFailure:true result:setError];
[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];
}
}];
// 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;
// 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;
/* used for join with bottle */
extern OctagonState* const OctagonStateBottleJoinCreateIdentity;
+extern OctagonState* const OctagonStateBottlePreloadOctagonKeysInSOS;
/* used for join with recovery key */
extern OctagonState* const OctagonStateCreateIdentityForRecoveryKey;
extern OctagonState* const OctagonStateError;
extern OctagonState* const OctagonStateDisabled;
+extern OctagonState* const OctagonStateAttemptSOSUpgradeDetermineCDPState;
extern OctagonState* const OctagonStateAttemptSOSUpgrade;
extern OctagonState* const OctagonStateSOSUpgradeCKKSReset;
extern OctagonState* const OctagonStateSOSUpgradeAfterCKKSReset;
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);
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
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 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 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";
OctagonState* const OctagonStateNoAccountDoReset = (OctagonState*) @"no_account_do_reset";
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";
OctagonStateCDPHealthCheck: @58U,
OctagonStateHealthCheckLeaveClique: @59U,
OctagonStateRefetchCKKSPolicy: @60U,
+ OctagonStateEnableUserControllableViews: @61U,
+ OctagonStateDisableUserControllableViews: @62U,
+ OctagonStateSetUserControllableViewsToPeerConsensus: @63U,
+ OctagonStateWaitForClassCUnlock: @64U,
+ OctagonStateBottlePreloadOctagonKeysInSOS: @65U,
+ OctagonStateAttemptSOSUpgradeDetermineCDPState: @66U,
};
});
return map;
[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;
// 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 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<OctagonFlag *>* 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:OctagonFlagUnlocked];
[flags addObject:OctagonFlagAttemptSOSUpdatePreapprovals];
[flags addObject:OctagonFlagAttemptSOSConsistency];
+ [flags addObject:OctagonFlagWarmEscrowRecordCache];
+ [flags addObject:OctagonFlagAttemptUserControllableViewStatusUpgrade];
+ [flags addObject:OctagonFlagAttemptBottleTLKExtraction];
+ [flags addObject:OctagonFlagAttemptRecoveryKeyTLKExtraction];
f = flags;
});
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
- // <rdar://problem/50190005> 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
+ // <rdar://problem/50190005> 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!");
[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 '%@''", peerState.peerID, self.peerUnknownState);
- self.nextState = self.peerUnknownState;
-
+ 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;
}
[self.deps.authKitAdapter fetchCurrentDeviceList:^(NSSet<NSString *> * _Nullable machineIDs, NSError * _Nullable error) {
STRONGIFY(self);
- if(!machineIDs || error) {
+
+ if (error) {
secerror("octagon-authkit: Unable to fetch machine ID list: %@", error);
+ [self fetchCurrentDeviceListAfterCuttlefishUpdate:isAccountDemo];
+ } else if (!machineIDs) {
+ secerror("octagon-authkit: empty machine id list");
if (self.logForUpgrade) {
[[CKKSAnalytics logger] logRecoverableError:error
forEvent:OctagonEventUpgradeFetchDeviceIDs
}];
}
+- (void)fetchCurrentDeviceListAfterCuttlefishUpdate:(BOOL)isAccountDemo
+{
+ secnotice("octagon-authkit", "beginning update trust fetch");
+
+ WEAKIFY(self);
+ [self.deps.cuttlefishXPCWrapper updateWithContainer:self.deps.containerName
+ context:self.deps.contextID
+ deviceName:nil
+ serialNumber:nil
+ osVersion:nil
+ policyVersion:nil
+ policySecrets:nil
+ syncUserControllableViews:nil
+ reply:^(TrustedPeersHelperPeerState* peerState, TPSyncingPolicy* syncingPolicy, NSError* error) {
+ STRONGIFY(self);
+ if(error) {
+ secerror("octagon-authkit: fetching updates from cuttlefish failed: %@", error);
+ self.error = error;
+
+ if([self.deps.lockStateTracker isLockedError:self.error]) {
+ secnotice("octagon-authkit", "Feching changes from Cuttlefish failed because of lock state, will retry once unlocked: %@", self.error);
+ OctagonPendingFlag* pendingFlag = [[OctagonPendingFlag alloc] initWithFlag:OctagonFlagFetchAuthKitMachineIDList
+ conditions:OctagonPendingConditionsDeviceUnlocked];
+
+ [self.deps.flagHandler handlePendingFlag:pendingFlag];
+ }
+
+ [self runBeforeGroupFinished:self.finishedOp];
+ return;
+ }
+ secnotice("octagon-authkit", "re-attempting fetching current device list");
+
+ [self.deps.authKitAdapter fetchCurrentDeviceList:^(NSSet<NSString *> * _Nullable machineIDs, NSError * _Nullable error) {
+ STRONGIFY(self);
+ if(!machineIDs || error) {
+ secerror("octagon-authkit: STILL unable to fetch machine ID list: %@", error);
+ if (self.logForUpgrade) {
+ [[CKKSAnalytics logger] logRecoverableError:error
+ forEvent:OctagonEventUpgradeFetchDeviceIDs
+ withAttributes:NULL];
+ }
+ self.error = error;
+ [self runBeforeGroupFinished:self.finishedOp];
+
+ } else {
+ if (self.logForUpgrade) {
+ [[CKKSAnalytics logger] logSuccessForEventNamed:OctagonEventUpgradeFetchDeviceIDs];
+ }
+ [self afterAuthKitFetch:machineIDs accountIsDemo:isAccountDemo];
+ }
+ }];
+ }];
+}
+
- (void)afterAuthKitFetch:(NSSet<NSString *>*)allowedMachineIDs accountIsDemo:(BOOL)accountIsDemo
{
WEAKIFY(self);
- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies
intendedState:(OctagonState*)intendedState
ckksConflictState:(OctagonState*)ckksConflictState
+ peerMissingState:(OctagonState*)peerMissingState
errorState:(OctagonState*)errorState;
@property OctagonState* nextState;
#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"
@property OTOperationDependencies* deps;
@property OctagonState* ckksConflictState;
+@property OctagonState* peerMissingState;
@property NSOperation* finishedOp;
@end
- (instancetype)initWithDependencies:(OTOperationDependencies*)dependencies
intendedState:(OctagonState*)intendedState
ckksConflictState:(OctagonState*)ckksConflictState
+ peerMissingState:(OctagonState*)peerMissingState
errorState:(OctagonState*)errorState
{
if((self = [super init])) {
_intendedState = intendedState;
_ckksConflictState = ckksConflictState;
+ _peerMissingState = peerMissingState;
_nextState = errorState;
}
return self;
- (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);
// One (or more) of our sub-CKKSes believes it needs to upload new TLKs.
CKKSViewManager* viewManager = self.deps.viewManager;
for(CKKSKeychainView* view in viewManager.currentViews) {
- if([view.keyHierarchyState isEqualToString:SecCKKSZoneKeyStateWaitForTLKUpload] ||
- [view.keyHierarchyState isEqualToString:SecCKKSZoneKeyStateWaitForTLKCreation]) {
+ if([view requiresTLKUpload]) {
secnotice("octagon-ckks", "CKKS view %@ needs TLK uploads!", view);
[viewsToUpload addObject: view];
}
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;
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;
@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
#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"
bottleID:(NSString*)bottleID
entropy:(NSData*)entropy
bottleSalt:(NSString*)bottleSalt
+ saveVoucher:(BOOL)saveVoucher
{
if((self = [super init])) {
_deps = dependencies;
_bottleID = bottleID;
_entropy = entropy;
_bottleSalt = bottleSalt;
+
+ _saveVoucher = saveVoucher;
}
return self;
}
context:self.deps.contextID
bottleID:self.bottleID
reply:^(NSString * _Nullable peerID,
- NSSet<NSString*>* peerSyncingViews,
- TPPolicy* peerSyncingPolicy,
+ TPSyncingPolicy* peerSyncingPolicy,
+ BOOL refetchWasNeeded,
NSError * _Nullable error) {
STRONGIFY(self);
[[CKKSAnalytics logger] logResultForEvent:OctagonEventPreflightVouchWithBottle hardFailure:true result:error];
// 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 setSyncingViews:peerSyncingViews sortingPolicy:peerSyncingPolicy];
+ [self.deps.viewManager setCurrentSyncingPolicy:peerSyncingPolicy];
- [self proceedWithPeerID:peerID];
+ [self proceedWithPeerID:peerID refetchWasNeeded:refetchWasNeeded];
}];
}
-- (void)proceedWithPeerID:(NSString*)peerID
+- (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];
+ OTFetchCKKSKeysOperation* fetchKeysOp = [[OTFetchCKKSKeysOperation alloc] initWithDependencies:self.deps
+ refetchNeeded:refetchWasNeeded];
[self runBeforeGroupFinished:fetchKeysOp];
CKKSResultOperation* proceedWithKeys = [CKKSResultOperation named:@"bottle-tlks"
}
}
+ 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];
}];
}
[self noteMetric:OctagonAnalyticsBottledTLKUniqueViewCount count:views.count];
- secnotice("octagon", "Received bottle voucher");
-
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];
}];
- (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) 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
#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"
intendedState:(OctagonState*)intendedState
errorState:(OctagonState*)errorState
recoveryKey:(NSString*)recoveryKey
+ saveVoucher:(BOOL)saveVoucher
{
if((self = [super init])) {
_deps = dependencies;
_nextState = errorState;
_recoveryKey = recoveryKey;
+
+ _saveVoucher = saveVoucher;
}
return self;
}
recoveryKey:self.recoveryKey
salt:self.salt
reply:^(NSString * _Nullable recoveryKeyID,
- NSSet<NSString*>* peerSyncingViews,
- TPPolicy* peerSyncingPolicy,
+ TPSyncingPolicy* _Nullable peerSyncingPolicy,
NSError * _Nullable error) {
STRONGIFY(self);
[[CKKSAnalytics logger] logResultForEvent:OctagonEventPreflightVouchWithRecoveryKey hardFailure:true result:error];
// 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 setSyncingViews:peerSyncingViews sortingPolicy:peerSyncingPolicy];
+ [self.deps.viewManager setCurrentSyncingPolicy:peerSyncingPolicy];
[self proceedWithRecoveryKeyID: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"
}
}
+ 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];
}];
}
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];
}];
#if OCTAGON
#import <Foundation/Foundation.h>
-#import "keychain/ot/OTOperationDependencies.h"
#import "keychain/ckks/CKKSPeer.h"
+#import "keychain/ckks/CKKSPeerProvider.h"
+#import "keychain/ot/CuttlefishXPCWrapper.h"
NS_ASSUME_NONNULL_BEGIN
@interface OctagonCKKSPeerAdapter : NSObject <CKKSPeerProvider>
@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
@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"];
__block NSMutableSet<id<CKKSRemotePeerProtocol>> * peers = nil;
WEAKIFY(self);
- [self.deps.cuttlefishXPCWrapper fetchTrustStateWithContainer:self.deps.containerName
- context:self.deps.contextID
- reply:^(TrustedPeersHelperPeerState * _Nullable selfPeerState,
- NSArray<TrustedPeersHelperPeer *> * _Nullable trustedPeers,
- NSError * _Nullable operror) {
+ [self.cuttlefishXPCWrapper fetchTrustStateWithContainer:self.containerName
+ context:self.contextID
+ reply:^(TrustedPeersHelperPeerState * _Nullable selfPeerState,
+ NSArray<TrustedPeersHelperPeer *> * _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 {
encryptionPublicKey:encryptionKey
signingPublicKey:signingKey
viewList:peer.viewList];
- secnotice("octagon", "Have trusted peer %@", ckkspeer);
-
[peers addObject:ckkspeer];
}
}
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;
}
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;
}
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];
_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;
}
@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;
@end
NS_ASSUME_NONNULL_END
if ((self = [super init])) {
_flag = flag;
_fireTime = [NSDate dateWithTimeIntervalSinceNow:delay];
+ _afterOperation = nil;
_conditions = 0;
}
return self;
if ((self = [super init])) {
_flag = flag;
_fireTime = nil;
+ _afterOperation = nil;
_conditions = conditions;
}
return self;
}
+- (instancetype)initWithFlag:(OctagonFlag*)flag after:(NSOperation*)op
+{
+ if ((self = [super init])) {
+ _flag = flag;
+ _fireTime = nil;
+ _afterOperation = op;
+ _conditions = 0;
+ }
+ return self;
+}
+
- (NSString*)description {
if(self.fireTime) {
return [NSString stringWithFormat:@"<OctagonPendingFlag: %@: %@>", self.flag, self.fireTime];
+ } else if(self.afterOperation) {
+ return [NSString stringWithFormat:@"<OctagonPendingFlag: %@: %@>", self.flag, self.afterOperation];
} else {
return [NSString stringWithFormat:@"<OctagonPendingFlag: %@: %@>", self.flag, OctagonPendingConditionsToString(self.conditions)];
}
@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 <OctagonStateFlagHandler, OctagonStateOnqueuePendingFlagHandler>
// 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;
- (void)disablePendingFlags;
- (void)handleExternalRequest:(OctagonStateTransitionRequest<CKKSResultOperation<OctagonStateTransitionOperationProtocol>*>*)request;
+
- (void)registerStateTransitionWatcher:(OctagonStateTransitionWatcher*)watcher;
+- (void)registerMultiStateArrivalWatcher:(OctagonStateMultiStateArrivalWatcher*)watcher;
- (void)doSimpleStateMachineRPC:(NSString*)name
op:(CKKSResultOperation<OctagonStateTransitionOperationProtocol>*)op
sourceStates:(NSSet<OctagonState*>*)sourceStates
reply:(nonnull void (^)(NSError * _Nullable))reply;
-- (void)doWatchedStateMachineRPC:(NSString*)name
- sourceStates:(NSSet<OctagonState*>*)sourceStates
- path:(OctagonStateTransitionPath*)path
- reply:(nonnull void (^)(NSError *error))reply;
+- (CKKSResultOperation*)doWatchedStateMachineRPC:(NSString*)name
+ sourceStates:(NSSet<OctagonState*>*)sourceStates
+ path:(OctagonStateTransitionPath*)path
+ reply:(nonnull void (^)(NSError *error))reply;
- (void)setWatcherTimeout:(uint64_t)timeout;
- (BOOL)isPaused;
@property (nullable) CKKSResultOperation* nextStateMachineCycleOperation;
@property NSMutableArray<OctagonStateTransitionRequest<CKKSResultOperation<OctagonStateTransitionOperationProtocol>*>*>* stateMachineRequests;
-@property NSMutableArray<OctagonStateTransitionWatcher*>* stateMachineWatchers;
+@property NSMutableArray<id<OctagonStateTransitionWatcherProtocol>>* stateMachineWatchers;
@property BOOL halted;
@property bool allowPendingFlags;
op,
op.error ?: @"(no error)");
- for(OctagonStateTransitionWatcher* watcher in self.stateMachineWatchers) {
+ for(id<OctagonStateTransitionWatcherProtocol> watcher in self.stateMachineWatchers) {
statemachinelog("state", "notifying watcher: %@", watcher);
[watcher onqueueHandleTransition:op];
}
- (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];
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];
}
}
}
+ 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) {
});
}
+
- (void)registerStateTransitionWatcher:(OctagonStateTransitionWatcher*)watcher
{
dispatch_sync(self.queue, ^{
});
}
+- (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
self.timeout = timeout;
}
-- (void)doWatchedStateMachineRPC:(NSString*)name
- sourceStates:(NSSet<OctagonState*>*)sourceStates
- path:(OctagonStateTransitionPath*)path
- reply:(nonnull void (^)(NSError *error))reply
+- (CKKSResultOperation*)doWatchedStateMachineRPC:(NSString*)name
+ sourceStates:(NSSet<OctagonState*>*)sourceStates
+ path:(OctagonStateTransitionPath*)path
+ reply:(nonnull void (^)(NSError *error))reply
{
statemachinelog("state-rpc", "Beginning a '%@' rpc", name);
[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
#import <Foundation/Foundation.h>
#import "keychain/ckks/CKKSResultOperation.h"
+#import "keychain/ckks/CKKSGroupOperation.h"
#import "keychain/ckks/CKKSAnalytics.h"
NS_ASSUME_NONNULL_BEGIN
entering:(OctagonState*)intendedState NS_SWIFT_NAME(init(name:entering:));
@end
+// Just like OctagonStateTransitionOperation, but as a Group Operation
+@interface OctagonStateTransitionGroupOperation : CKKSGroupOperation <OctagonStateTransitionOperationProtocol>
+@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<OctagonStateTransitionOperationProtocol>*> : NSObject
@property (readonly) NSString* name;
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
{
@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:@"<OctagonStateTransitionGroupOperation(%@): intended:%@ actual:%@>", 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;
- (NSString*)description
{
- return [NSString stringWithFormat:@"<OctagonStateTransitionRequest: %@ %@ %@>", self.name, self.transitionOperation, self.sourceStates];
+ return [NSString stringWithFormat:@"<OctagonStateTransitionRequest: %@ %@ sources:%d>", self.name, self.transitionOperation, (unsigned int)[self.sourceStates count]];
}
- (CKKSResultOperation<OctagonStateTransitionOperationProtocol>* _Nullable)_onqueueStart
@end
-@interface OctagonStateTransitionWatcher : NSObject
+
+@protocol OctagonStateTransitionWatcherProtocol
+@property (readonly) CKKSResultOperation* result;
+- (void)onqueueHandleTransition:(CKKSResultOperation<OctagonStateTransitionOperationProtocol>*)attempt;
+@end
+
+@interface OctagonStateTransitionWatcher : NSObject <OctagonStateTransitionWatcherProtocol>
@property (readonly) NSString* name;
@property (readonly) CKKSResultOperation* result;
@property (readonly) OctagonStateTransitionPath* intendedPath;
- (instancetype)timeout:(dispatch_time_t)timeout;
-- (void)onqueueHandleTransition:(CKKSResultOperation<OctagonStateTransitionOperationProtocol>*)attempt;
+@end
+
+// Reports on if any of the given states are entered
+@interface OctagonStateMultiStateArrivalWatcher : NSObject <OctagonStateTransitionWatcherProtocol>
+@property (readonly) NSString* name;
+@property (readonly) CKKSResultOperation* result;
+@property (readonly) NSSet<OctagonState*>* states;
+
+- (instancetype)initNamed:(NSString*)name
+ serialQueue:(dispatch_queue_t)queue
+ states:(NSSet<OctagonState*>*)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
@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<OctagonState*>*)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<OctagonStateTransitionOperationProtocol>*)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
+ (OTAccountMetadataClassC* _Nullable)loadFromKeychainForContainer:(NSString*)containerName contextID:(NSString*)contextID error:(NSError**)error;
@end
-@class TPPolicy;
+@class TPSyncingPolicy;
@interface OTAccountMetadataClassC (NSSecureCodingSupport)
-- (void)setTPPolicy:(TPPolicy* _Nullable)policy;
-- (TPPolicy* _Nullable)getTPPolicy;
+- (void)setTPSyncingPolicy:(TPSyncingPolicy* _Nullable)policy;
+- (TPSyncingPolicy* _Nullable)getTPSyncingPolicy;
@end
NS_ASSUME_NONNULL_END
#import "keychain/ot/OTDefines.h"
#import "keychain/ot/OTConstants.h"
-#import <TrustedPeers/TPPolicy.h>
+#import <TrustedPeers/TPSyncingPolicy.h>
@implementation OTAccountMetadataClassC (KeychainSupport)
#pragma mark - Field Coding support
-- (void)setTPPolicy:(TPPolicy*)policy
+- (void)setTPSyncingPolicy:(TPSyncingPolicy*)policy
{
if(policy) {
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES];
}
}
-- (TPPolicy* _Nullable)getTPPolicy
+- (TPSyncingPolicy* _Nullable)getTPSyncingPolicy
{
NSKeyedUnarchiver *coder = [[NSKeyedUnarchiver alloc] initForReadingFromData:self.syncingPolicy error:nil];
- TPPolicy* policy = [[TPPolicy alloc] initWithCoder:coder];
+ TPSyncingPolicy* policy = [[TPSyncingPolicy alloc] initWithCoder:coder];
[coder finishDecoding];
return policy;
#ifndef OctagonEscrowRecoverer_h
#define OctagonEscrowRecoverer_h
-#import <CloudServices/SecureBackup.h>
-
@protocol OctagonEscrowRecovererPrococol <NSObject>
- (NSError*)recoverWithInfo:(NSDictionary*)info results:(NSDictionary**)results;
+- (NSError *)getAccountInfoWithInfo:(NSDictionary *)info results:(NSDictionary**)results;
- (NSError *)disableWithInfo:(NSDictionary *)info;
@end
-@interface SecureBackup (OctagonProtocolConformance) <OctagonEscrowRecovererPrococol>
-@end
-
#endif /* OctagonEscrowRecoverer_h */
#endif // OCTAGON
optional CDPState cdpState = 8;
- // These store the current policy and view list, so that we don't need to re-ask TPH every time
- optional bytes syncingPolicy = 9;
- repeated string syncingView = 10;
+ // 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;
}
--- /dev/null
+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;
+}
--- /dev/null
+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;
+}
package OT;
+enum SupportType {
+ unknown = 0;
+ supported = 1;
+ not_supported = 2;
+}
+
+message supportSOSMessage {
+ optional SupportType supported = 1;
+}
+
+message supportOctagonMessage {
+ optional SupportType supported = 1;
+}
message SponsorToApplicantRound1M2 {
optional uint64 epoch = 1;
optional SponsorToApplicantRound2M2 voucher = 3;
// <rdar://problem/55465193> reserved is not a keyword (it should be)
// reserved 4;
+ optional supportOctagonMessage supportsOctagon = 5;
+ optional supportSOSMessage supportsSOS = 6;
}
OTAccountMetadataClassC_AccountState _icloudAccountState;
NSString *_peerID;
NSData *_syncingPolicy;
- NSMutableArray<NSString *> *_syncingViews;
OTAccountMetadataClassC_TrustState _trustState;
+ NSData *_voucher;
+ NSData *_voucherSignature;
struct {
int epoch:1;
int lastHealthCheckup:1;
- (OTAccountMetadataClassC_CDPState)StringAsCdpState:(NSString *)str;
@property (nonatomic, readonly) BOOL hasSyncingPolicy;
-/** These store the current policy and view list, so that we don't need to re-ask TPH every time */
+/**
+ * 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, retain) NSMutableArray<NSString *> *syncingViews;
-- (void)clearSyncingViews;
-- (void)addSyncingView:(NSString *)i;
-- (NSUInteger)syncingViewsCount;
-- (NSString *)syncingViewAtIndex:(NSUInteger)idx;
-+ (Class)syncingViewType;
+@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;
return _syncingPolicy != nil;
}
@synthesize syncingPolicy = _syncingPolicy;
-@synthesize syncingViews = _syncingViews;
-- (void)clearSyncingViews
+- (BOOL)hasVoucher
{
- [_syncingViews removeAllObjects];
+ return _voucher != nil;
}
-- (void)addSyncingView:(NSString *)i
+@synthesize voucher = _voucher;
+- (BOOL)hasVoucherSignature
{
- if (!_syncingViews)
- {
- _syncingViews = [[NSMutableArray alloc] init];
- }
- [_syncingViews addObject:i];
-}
-- (NSUInteger)syncingViewsCount
-{
- return [_syncingViews count];
-}
-- (NSString *)syncingViewAtIndex:(NSUInteger)idx
-{
- return [_syncingViews objectAtIndex:idx];
-}
-+ (Class)syncingViewType
-{
- return [NSString class];
+ return _voucherSignature != nil;
}
+@synthesize voucherSignature = _voucherSignature;
- (NSString *)description
{
{
[dict setObject:self->_syncingPolicy forKey:@"syncingPolicy"];
}
- if (self->_syncingViews)
+ if (self->_voucher)
+ {
+ [dict setObject:self->_voucher forKey:@"voucher"];
+ }
+ if (self->_voucherSignature)
{
- [dict setObject:self->_syncingViews forKey:@"syncingView"];
+ [dict setObject:self->_voucherSignature forKey:@"voucherSignature"];
}
return dict;
}
self->_cdpState = PBReaderReadInt32(reader);
}
break;
- case 9 /* syncingPolicy */:
+ case 11 /* syncingPolicy */:
{
NSData *new_syncingPolicy = PBReaderReadData(reader);
self->_syncingPolicy = new_syncingPolicy;
}
break;
- case 10 /* syncingViews */:
+ case 12 /* voucher */:
{
- NSString *new_syncingViews = PBReaderReadString(reader);
- if (new_syncingViews)
- {
- [self addSyncingView:new_syncingViews];
- }
+ 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 (self->_syncingPolicy)
{
- PBDataWriterWriteDataField(writer, self->_syncingPolicy, 9);
+ PBDataWriterWriteDataField(writer, self->_syncingPolicy, 11);
}
}
- /* syncingViews */
+ /* voucher */
{
- for (NSString *s_syncingViews in self->_syncingViews)
+ if (self->_voucher)
{
- PBDataWriterWriteStringField(writer, s_syncingViews, 10);
+ PBDataWriterWriteDataField(writer, self->_voucher, 12);
+ }
+ }
+ /* voucherSignature */
+ {
+ if (self->_voucherSignature)
+ {
+ PBDataWriterWriteDataField(writer, self->_voucherSignature, 13);
}
}
}
{
other.syncingPolicy = _syncingPolicy;
}
- if ([self syncingViewsCount])
+ if (_voucher)
{
- [other clearSyncingViews];
- NSUInteger syncingViewsCnt = [self syncingViewsCount];
- for (NSUInteger i = 0; i < syncingViewsCnt; i++)
- {
- [other addSyncingView:[self syncingViewAtIndex:i]];
- }
+ other.voucher = _voucher;
+ }
+ if (_voucherSignature)
+ {
+ other.voucherSignature = _voucherSignature;
}
}
copy->_has.cdpState = YES;
}
copy->_syncingPolicy = [_syncingPolicy copyWithZone:zone];
- for (NSString *v in _syncingViews)
- {
- NSString *vCopy = [v copyWithZone:zone];
- [copy addSyncingView:vCopy];
- }
+ copy->_voucher = [_voucher copyWithZone:zone];
+ copy->_voucherSignature = [_voucherSignature copyWithZone:zone];
return copy;
}
&&
((!self->_syncingPolicy && !other->_syncingPolicy) || [self->_syncingPolicy isEqual:other->_syncingPolicy])
&&
- ((!self->_syncingViews && !other->_syncingViews) || [self->_syncingViews isEqual:other->_syncingViews])
+ ((!self->_voucher && !other->_voucher) || [self->_voucher isEqual:other->_voucher])
+ &&
+ ((!self->_voucherSignature && !other->_voucherSignature) || [self->_voucherSignature isEqual:other->_voucherSignature])
;
}
^
[self->_syncingPolicy hash]
^
- [self->_syncingViews hash]
+ [self->_voucher hash]
+ ^
+ [self->_voucherSignature hash]
;
}
{
[self setSyncingPolicy:other->_syncingPolicy];
}
- for (NSString *iter_syncingViews in other->_syncingViews)
+ if (other->_voucher)
+ {
+ [self setVoucher:other->_voucher];
+ }
+ if (other->_voucherSignature)
{
- [self addSyncingView:iter_syncingViews];
+ [self setVoucherSignature:other->_voucherSignature];
}
}
--- /dev/null
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from OTCDPRecoveryInformation.proto
+
+#import <Foundation/Foundation.h>
+#import <ProtocolBuffer/PBCodable.h>
+
+#ifdef __cplusplus
+#define OTCDPRECOVERYINFORMATION_FUNCTION extern "C"
+#else
+#define OTCDPRECOVERYINFORMATION_FUNCTION extern
+#endif
+
+@interface OTCDPRecoveryInformation : PBCodable <NSCopying>
+{
+ 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
+
--- /dev/null
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from OTCDPRecoveryInformation.proto
+
+#import "OTCDPRecoveryInformation.h"
+#import <ProtocolBuffer/PBConstants.h>
+#import <ProtocolBuffer/PBHashUtil.h>
+#import <ProtocolBuffer/PBDataReader.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 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
+
--- /dev/null
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from OTCDPRecoveryInformation.proto
+
+#import <Foundation/Foundation.h>
+#import <ProtocolBuffer/PBCodable.h>
+
+#ifdef __cplusplus
+#define OTESCROWAUTHENTICATIONINFORMATION_FUNCTION extern "C"
+#else
+#define OTESCROWAUTHENTICATIONINFORMATION_FUNCTION extern
+#endif
+
+@interface OTEscrowAuthenticationInformation : PBCodable <NSCopying>
+{
+ 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
+
--- /dev/null
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from OTCDPRecoveryInformation.proto
+
+#import "OTEscrowAuthenticationInformation.h"
+#import <ProtocolBuffer/PBConstants.h>
+#import <ProtocolBuffer/PBHashUtil.h>
+#import <ProtocolBuffer/PBDataReader.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 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
+
--- /dev/null
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from OTEscrowRecord.proto
+
+#import <Foundation/Foundation.h>
+#import <ProtocolBuffer/PBCodable.h>
+
+@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 <NSCopying>
+{
+ uint64_t _coolOffEnd;
+ uint64_t _creationDate;
+ uint64_t _remainingAttempts;
+ uint64_t _silentAttemptAllowed;
+ OTEscrowRecordMetadata *_escrowInformationMetadata;
+ 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;
+
+// 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
+
--- /dev/null
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from OTEscrowRecord.proto
+
+#import "OTEscrowRecord.h"
+#import <ProtocolBuffer/PBConstants.h>
+#import <ProtocolBuffer/PBHashUtil.h>
+#import <ProtocolBuffer/PBDataReader.h>
+
+#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);
+}
+
+- (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"];
+ }
+ 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;
+ 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);
+ }
+ }
+}
+
+- (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;
+ }
+}
+
+- (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;
+ }
+ 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))
+ ;
+}
+
+- (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)
+ ;
+}
+
+- (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;
+ }
+}
+
+@end
+
--- /dev/null
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from OTEscrowRecord.proto
+
+#import <Foundation/Foundation.h>
+#import <ProtocolBuffer/PBCodable.h>
+
+@class OTEscrowRecordMetadataClientMetadata;
+
+#ifdef __cplusplus
+#define OTESCROWRECORDMETADATA_FUNCTION extern "C"
+#else
+#define OTESCROWRECORDMETADATA_FUNCTION extern
+#endif
+
+@interface OTEscrowRecordMetadata : PBCodable <NSCopying>
+{
+ 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
+
--- /dev/null
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from OTEscrowRecord.proto
+
+#import "OTEscrowRecordMetadata.h"
+#import <ProtocolBuffer/PBConstants.h>
+#import <ProtocolBuffer/PBHashUtil.h>
+#import <ProtocolBuffer/PBDataReader.h>
+
+#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
+
--- /dev/null
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from OTEscrowRecord.proto
+
+#import <Foundation/Foundation.h>
+#import <ProtocolBuffer/PBCodable.h>
+
+#ifdef __cplusplus
+#define OTESCROWRECORDMETADATACLIENTMETADATA_FUNCTION extern "C"
+#else
+#define OTESCROWRECORDMETADATACLIENTMETADATA_FUNCTION extern
+#endif
+
+@interface OTEscrowRecordMetadataClientMetadata : PBCodable <NSCopying>
+{
+ 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
+
--- /dev/null
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from OTEscrowRecord.proto
+
+#import "OTEscrowRecordMetadataClientMetadata.h"
+#import <ProtocolBuffer/PBConstants.h>
+#import <ProtocolBuffer/PBHashUtil.h>
+#import <ProtocolBuffer/PBDataReader.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 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
+
--- /dev/null
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from OTPairingMessage.proto
+
+#include <stdint.h>
+#ifdef __OBJC__
+#include <Foundation/Foundation.h>
+#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__ */
--- /dev/null
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from OTCDPRecoveryInformation.proto
+
+#import <Foundation/Foundation.h>
+#import <ProtocolBuffer/PBCodable.h>
+
+@class OTCDPRecoveryInformation;
+@class OTEscrowAuthenticationInformation;
+
+#ifdef __cplusplus
+#define OTICDPRECORDCONTEXT_FUNCTION extern "C"
+#else
+#define OTICDPRECORDCONTEXT_FUNCTION extern
+#endif
+
+@interface OTICDPRecordContext : PBCodable <NSCopying>
+{
+ 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
+
--- /dev/null
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from OTCDPRecoveryInformation.proto
+
+#import "OTICDPRecordContext.h"
+#import <ProtocolBuffer/PBConstants.h>
+#import <ProtocolBuffer/PBHashUtil.h>
+#import <ProtocolBuffer/PBDataReader.h>
+
+#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
+
--- /dev/null
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from OTCDPRecoveryInformation.proto
+
+#import <Foundation/Foundation.h>
+#import <ProtocolBuffer/PBCodable.h>
+
+@class OTCDPRecoveryInformation;
+@class OTEscrowAuthenticationInformation;
+
+#ifdef __cplusplus
+#define OTICDPRECORDSILENTCONTEXT_FUNCTION extern "C"
+#else
+#define OTICDPRECORDSILENTCONTEXT_FUNCTION extern
+#endif
+
+@interface OTICDPRecordSilentContext : PBCodable <NSCopying>
+{
+ 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
+
--- /dev/null
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from OTCDPRecoveryInformation.proto
+
+#import "OTICDPRecordSilentContext.h"
+#import <ProtocolBuffer/PBConstants.h>
+#import <ProtocolBuffer/PBHashUtil.h>
+#import <ProtocolBuffer/PBDataReader.h>
+
+#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
+
#import <Foundation/Foundation.h>
#import <ProtocolBuffer/PBCodable.h>
-@class OTSponsorToApplicantRound1M2;
@class OTApplicantToSponsorRound2M1;
+@class OTSponsorToApplicantRound1M2;
@class OTSponsorToApplicantRound2M2;
+@class OTSupportOctagonMessage;
+@class OTSupportSOSMessage;
#ifdef __cplusplus
#define OTPAIRINGMESSAGE_FUNCTION extern "C" __attribute__((visibility("hidden")))
{
OTSponsorToApplicantRound1M2 *_epoch;
OTApplicantToSponsorRound2M1 *_prepare;
+ OTSupportOctagonMessage *_supportsOctagon;
+ OTSupportSOSMessage *_supportsSOS;
OTSponsorToApplicantRound2M2 *_voucher;
}
@property (nonatomic, readonly) BOOL hasVoucher;
@property (nonatomic, retain) OTSponsorToApplicantRound2M2 *voucher;
+@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;
#import "OTApplicantToSponsorRound2M1.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.
return _voucher != nil;
}
@synthesize voucher = _voucher;
+- (BOOL)hasSupportsOctagon
+{
+ return _supportsOctagon != nil;
+}
+@synthesize supportsOctagon = _supportsOctagon;
+- (BOOL)hasSupportsSOS
+{
+ return _supportsSOS != nil;
+}
+@synthesize supportsSOS = _supportsSOS;
- (NSString *)description
{
{
[dict setObject:[_voucher dictionaryRepresentation] forKey:@"voucher"];
}
+ if (self->_supportsOctagon)
+ {
+ [dict setObject:[_supportsOctagon dictionaryRepresentation] forKey:@"supportsOctagon"];
+ }
+ if (self->_supportsSOS)
+ {
+ [dict setObject:[_supportsSOS dictionaryRepresentation] forKey:@"supportsSOS"];
+ }
return dict;
}
PBReaderRecallMark(reader, &mark_voucher);
}
break;
+ case 5 /* supportsOctagon */:
+ {
+ 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 = !OTSupportOctagonMessageReadFrom(new_supportsOctagon, reader);
+ if (inError)
+ {
+ return NO;
+ }
+ 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:
if (!PBReaderSkipValueWithTag(reader, tag, aType))
return NO;
PBDataWriterWriteSubmessage(writer, self->_voucher, 3);
}
}
+ /* supportsOctagon */
+ {
+ if (self->_supportsOctagon != nil)
+ {
+ PBDataWriterWriteSubmessage(writer, self->_supportsOctagon, 5);
+ }
+ }
+ /* supportsSOS */
+ {
+ if (self->_supportsSOS != nil)
+ {
+ PBDataWriterWriteSubmessage(writer, self->_supportsSOS, 6);
+ }
+ }
}
- (void)copyTo:(OTPairingMessage *)other
{
other.voucher = _voucher;
}
+ if (_supportsOctagon)
+ {
+ other.supportsOctagon = _supportsOctagon;
+ }
+ if (_supportsSOS)
+ {
+ other.supportsSOS = _supportsSOS;
+ }
}
- (id)copyWithZone:(NSZone *)zone
copy->_epoch = [_epoch copyWithZone:zone];
copy->_prepare = [_prepare copyWithZone:zone];
copy->_voucher = [_voucher copyWithZone:zone];
+ copy->_supportsOctagon = [_supportsOctagon copyWithZone:zone];
+ copy->_supportsSOS = [_supportsSOS copyWithZone:zone];
return copy;
}
((!self->_prepare && !other->_prepare) || [self->_prepare isEqual:other->_prepare])
&&
((!self->_voucher && !other->_voucher) || [self->_voucher isEqual:other->_voucher])
+ &&
+ ((!self->_supportsOctagon && !other->_supportsOctagon) || [self->_supportsOctagon isEqual:other->_supportsOctagon])
+ &&
+ ((!self->_supportsSOS && !other->_supportsSOS) || [self->_supportsSOS isEqual:other->_supportsSOS])
;
}
[self->_prepare hash]
^
[self->_voucher hash]
+ ^
+ [self->_supportsOctagon hash]
+ ^
+ [self->_supportsSOS hash]
;
}
{
[self setVoucher:other->_voucher];
}
+ if (self->_supportsOctagon && other->_supportsOctagon)
+ {
+ [self->_supportsOctagon mergeFrom:other->_supportsOctagon];
+ }
+ else if (!self->_supportsOctagon && other->_supportsOctagon)
+ {
+ [self setSupportsOctagon:other->_supportsOctagon];
+ }
+ if (self->_supportsSOS && other->_supportsSOS)
+ {
+ [self->_supportsSOS mergeFrom:other->_supportsSOS];
+ }
+ else if (!self->_supportsSOS && other->_supportsSOS)
+ {
+ [self setSupportsSOS:other->_supportsSOS];
+ }
}
@end
}
- (BOOL)hasEpoch
{
- return _has.epoch;
+ return _has.epoch != 0;
}
- (NSString *)description
--- /dev/null
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from OTPairingMessage.proto
+
+#import <Foundation/Foundation.h>
+#import <ProtocolBuffer/PBCodable.h>
+
+#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 <NSCopying>
+{
+ 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
+
--- /dev/null
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from OTPairingMessage.proto
+
+#import "OTSupportOctagonMessage.h"
+#import <ProtocolBuffer/PBConstants.h>
+#import <ProtocolBuffer/PBHashUtil.h>
+#import <ProtocolBuffer/PBDataReader.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 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
+
--- /dev/null
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from OTPairingMessage.proto
+
+#import <Foundation/Foundation.h>
+#import <ProtocolBuffer/PBCodable.h>
+
+#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 <NSCopying>
+{
+ 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
+
--- /dev/null
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from OTPairingMessage.proto
+
+#import "OTSupportSOSMessage.h"
+#import <ProtocolBuffer/PBConstants.h>
+#import <ProtocolBuffer/PBHashUtil.h>
+#import <ProtocolBuffer/PBDataReader.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 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
+
+++ /dev/null
-// This file was automatically generated by protocompiler
-// DO NOT EDIT!
-// Compiled from OTPairingMessage.proto
-
-#import <Foundation/Foundation.h>
-#import <ProtocolBuffer/PBCodable.h>
-
-#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 <NSCopying>
-{
- 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
-
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)
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)
disabled_rules:
- force_cast
- force_try
+ - implicitly_unwrapped_optional
#if OCTAGON
class OctagonAccountMetadataClassCPersistenceTests: CloudKitKeychainSyncingMockXCTest {
-
override static func setUp() {
super.setUp()
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 {
--- /dev/null
+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")
+ }
+ }
+}
super.init()
}
- func recover(withInfo info: [AnyHashable: Any]!,
- results: AutoreleasingUnsafeMutablePointer<NSDictionary?>!) -> Error! {
+ func recover(withInfo info: [AnyHashable: Any]?,
+ results: AutoreleasingUnsafeMutablePointer<NSDictionary?>?) -> 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],
func disable(withInfo info: [AnyHashable: Any]!) -> Error? {
return nil
}
+
+ @objc func getAccountInfo(withInfo info: [AnyHashable: Any]!, results: AutoreleasingUnsafeMutablePointer<NSDictionary?>!) -> 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 {
self.wait(for: [quiescentExpectation], timeout: 10)
- // CKKS should also be logged out, since Octagon believes there's no account
- self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateLoggedOut, within: 10 * NSEC_PER_SEC)
+ // 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.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()
//check trust status
let checkTrustExpectation = self.expectation(description: "checkTrustExpectation callback occurs")
let configuration = OTOperationConfiguration()
- self.cuttlefishContext.rpcTrustStatus(configuration) { _, _, _, _, _ in
+ self.cuttlefishContext.rpcTrustStatus(configuration) { _, _, _, _, _, _ in
checkTrustExpectation.fulfill()
}
self.wait(for: [checkTrustExpectation], timeout: 10)
}
self.wait(for: [joinWithBottleExpectation], timeout: 3)
}
-
}
#endif
#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()
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 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)
+ }
}
#endif // OCTAGON
class OctagonCKKSConfigurationTestsPolicyEnabled: OctagonTestsBase {
override func setUp() {
-
if self.mockDeviceInfo == nil {
let actualDeviceAdapter = OTDeviceInformationActualAdapter()
self.mockDeviceInfo = OTMockDeviceInfoAdapter(modelID: actualDeviceAdapter.modelID(),
CKRecordZone.ID(zoneName: "ApplePay"),
CKRecordZone.ID(zoneName: "Applications"),
CKRecordZone.ID(zoneName: "AutoUnlock"),
- // <rdar://problem/57771098> Octagon: create final policy for CKKS4All
- // CKRecordZone.ID(zoneName: "Backstop"),
- // <rdar://problem/57810109> Cuttlefish: remove Safari prefix from view names
- CKRecordZone.ID(zoneName: "SafariCreditCards"),
+ 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"),
- // <rdar://problem/57810109> Cuttlefish: remove Safari prefix from view names
- CKRecordZone.ID(zoneName: "SafariPasswords"),
+ CKRecordZone.ID(zoneName: "Passwords"),
CKRecordZone.ID(zoneName: "ProtectedCloudStorage"),
CKRecordZone.ID(zoneName: "SecureObjectSync"),
CKRecordZone.ID(zoneName: "WiFi"),
#if !os(tvOS)
let expected = Set<String>([
- "ApplePay",
- "Applications",
- "AutoUnlock",
- // <rdar://problem/57771098> Octagon: create final policy for CKKS4All
- //"Backstop",
- // <rdar://problem/57810109> Cuttlefish: remove Safari prefix from view names
- "SafariCreditCards",
- "DevicePairing",
- "Engram",
- "Health",
- "Home",
- "LimitedPeersAllowed",
- "Manatee",
- // <rdar://problem/57810109> Cuttlefish: remove Safari prefix from view names
- "SafariPasswords",
- "ProtectedCloudStorage",
- "SecureObjectSync",
- "WiFi",
- ])
+ "ApplePay",
+ "Applications",
+ "AutoUnlock",
+ "Backstop",
+ "CreditCards",
+ "DevicePairing",
+ "Engram",
+ "Health",
+ "Home",
+ "LimitedPeersAllowed",
+ "Manatee",
+ "Passwords",
+ "ProtectedCloudStorage",
+ "SecureObjectSync",
+ "WiFi",
+ ])
#else
let expected = Set<String>(["LimitedPeersAllowed",
"Home",
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
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
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 {
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)
- self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateLoggedOut, within: 10 * NSEC_PER_SEC)
+ XCTAssertEqual(self.injectedManager!.views.count, 0, "Should have no CKKS views")
}
func testStatusRPCsWithUnknownCloudKitAccount() throws {
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, _, _, _, _, _ in
XCTAssertTrue([.absent].contains(egoStatus), "Self peer should be in the 'absent' state")
statusexpectation.fulfill()
}
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)
}
}
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")
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")
// Since SOS isn't around to help, Octagon should post a CFU
#if os(tvOS)
- XCTAssertEqual(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), 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.followupHandler.hasPosted(.stateRepair), "should have posted an repair CFU, as SOS can't help")
#endif
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")
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")
// 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")
self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateWaitForTLKCreation, within: 10 * NSEC_PER_SEC)
#if os(tvOS)
- XCTAssertEqual(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), 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.followupHandler.hasPosted(.stateRepair), "should have posted an repair CFU, as SOS can't help")
#endif
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")
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 {
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")
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(),
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 {
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
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(),
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
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,
//
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")
try! container.moc.save()
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")
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")
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(),
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")
}
+ static func makeAuthKitError(code: Int) -> NSError {
+ let authkitError = CKPrettyError(domain: AKAppleIDAuthenticationErrorDomain,
+ code: code,
+ userInfo: nil)
+
+ return authkitError
+ }
+
+ 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)
+ 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. Peer 1 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")
+
+ self.assertEnters(context: joiningContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC)
+
+ //peer2 attempts to update trusted device list but hits an authkit error
+ //try bottle restore again
+ joiningContext.startOctagonStateMachine()
+
+ let sponsorPeerID = try self.cuttlefishContext.accountMetadataStore.loadOrCreateAccountMetadata().peerID
+ XCTAssertNotNil(sponsorPeerID, "sponsorPeerID should not be nil")
+ let entropy = try self.loadSecret(label: sponsorPeerID!)
+ XCTAssertNotNil(entropy, "entropy should not be nil")
+
+ let altDSID = try joiningContext.authKitAdapter.primaryiCloudAccountAltDSID()
+ XCTAssertNotNil(altDSID, "Should have an altDSID")
+
+ let bottles = self.fakeCuttlefishServer.state.bottles.filter { $0.peerID == sponsorPeerID }
+ XCTAssertEqual(bottles.count, 1, "Should have a single bottle for the approving peer")
+ let bottle = bottles[0]
+
+ let joinWithBottleExpectation = self.expectation(description: "joinWithBottle callback occurs")
+ joiningContext.join(withBottle: bottle.bottleID, entropy: entropy!, bottleSalt: altDSID) { error in
+ XCTAssertNil(error, "error should be nil")
+ joinWithBottleExpectation.fulfill()
+ }
+
+ self.assertEnters(context: joiningContext, state: OctagonStateInitiatorUpdateDeviceList, within: 10 * NSEC_PER_SEC)
+
+ let authKitError = OctagonDeviceListTests.makeAuthKitError(code: -7026)
+ self.mockAuthKit2.machineIDFetchErrors = [authKitError]
+ let updateTrustExpectationPeer2 = self.expectation(description: "updateTrustPeer2")
+ self.fakeCuttlefishServer.fetchChangesListener = { request in
+ self.mockAuthKit2.machineIDFetchErrors = []
+ updateTrustExpectationPeer2.fulfill()
+ self.fakeCuttlefishServer.fetchChangesListener = nil
+ return nil
+ }
+ self.wait(for: [updateTrustExpectationPeer2], timeout: 10)
+
+ self.wait(for: [joinWithBottleExpectation], timeout: 10)
+
+ self.assertConsidersSelfTrusted(context: joiningContext)
+
+ self.assertEnters(context: joiningContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC)
+ }
}
#endif
#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 = { [unowned self] request in
self.fakeCuttlefishServer.establishListener = nil
- self.fakeCuttlefishServer.establish(request) {
- response, error in
+ 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
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()
var t0 = Date.distantPast
- self.fakeCuttlefishServer.establishListener = { [unowned self] request in
+ self.fakeCuttlefishServer.establishListener = { [unowned self] request in
self.fakeCuttlefishServer.establishListener = nil
establishExpectation.fulfill()
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)
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)
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
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.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
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
--- /dev/null
+#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)
+
+ 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)
+
+ //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
+ 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
+ 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)
+
+ //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
+ 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
+ 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
+ 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)
+
+ //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
+ 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
+ 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)
+
+ // 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
+ 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
+ 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
+ let legacy = container.containerMO.legacyEscrowRecords as! Set<EscrowRecordMO>
+ let partial = container.containerMO.partiallyViableEscrowRecords as! Set<EscrowRecordMO>
+ let full = container.containerMO.fullyViableEscrowRecords as! Set<EscrowRecordMO>
+
+ 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(container.containerMO.legacyEscrowRecords as? Set<EscrowRecordMO>, [], "legacy escrowRecords should be empty")
+ XCTAssertEqual(container.containerMO.partiallyViableEscrowRecords as? Set<EscrowRecordMO>, [], "partially viable escrowRecords should be empty")
+ XCTAssertEqual(container.containerMO.fullyViableEscrowRecords as? Set<EscrowRecordMO>, [], "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)
+
+ let fetchViableBottlesAfterExpiredTimeoutExpectation = self.expectation(description: "fetch Cached ViableBottles expectaiton after timeout")
+
+ self.fakeCuttlefishServer.fetchViableBottlesListener = { request in
+ self.fakeCuttlefishServer.fetchViableBottlesListener = nil
+ container.moc.performAndWait {
+ XCTAssertEqual(container.containerMO.legacyEscrowRecords as? Set<EscrowRecordMO>, [], "legacy escrowRecords should be empty")
+ XCTAssertEqual(container.containerMO.partiallyViableEscrowRecords as? Set<EscrowRecordMO>, [], "partially viable escrowRecords should be empty")
+ XCTAssertEqual(container.containerMO.fullyViableEscrowRecords as? Set<EscrowRecordMO>, [], "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<EscrowRecordMO>, [], "legacy escrowRecords should be empty")
+ XCTAssertEqual(container.containerMO.partiallyViableEscrowRecords as? Set<EscrowRecordMO>, [], "partially viable escrowRecords should be empty")
+ XCTAssertEqual(container.containerMO.fullyViableEscrowRecords as? Set<EscrowRecordMO>, [], "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)
+
+ 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(container.containerMO.legacyEscrowRecords as? Set<EscrowRecordMO>, [], "legacy escrowRecords should be empty")
+ XCTAssertEqual(container.containerMO.partiallyViableEscrowRecords as? Set<EscrowRecordMO>, [], "partially viable escrowRecords should be empty")
+ XCTAssertEqual(container.containerMO.fullyViableEscrowRecords as? Set<EscrowRecordMO>, [], "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
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.assertAllCKKSViewsUpload(tlkShares: 1)
-
// Before you call joinWithBottle, you need to call fetchViableBottles.
let fetchViableExpectation = self.expectation(description: "fetchViableBottles callback occurs")
self.cuttlefishContext.rpcFetchAllViableBottles { viable, _, error in
joinWithBottleExpectation.fulfill()
}
- sleep(1)
- self.releaseCloudKitFetchHold()
-
self.wait(for: [joinWithBottleExpectation], timeout: 100)
let dumpCallback = self.expectation(description: "dumpCallback callback occurs")
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 {
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()
}
restoreContext.join(withBottle: bottle.bottleID,
entropy: entropy!,
bottleSalt: self.otcliqueContext.altDSID!) { error in
- XCTAssertNil(error, "error should be nil")
- restoreExpectation.fulfill()
+ XCTAssertNil(error, "error should be nil")
+ restoreExpectation.fulfill()
}
self.wait(for: [restoreExpectation], timeout: 10)
// 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)
fetchEscrowContentsException.fulfill()
}
self.wait(for: [fetchEscrowContentsException], timeout: 10)
-
} catch {
XCTFail("failed to reset clique: \(error)")
}
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()
}
func testCachedBottleFetch() throws {
+ OctagonSetOptimizationEnabled(false)
let initiatorContextID = "initiator-context-id"
let bottlerContext = self.makeInitiatorContext(contextID: initiatorContextID)
let bottle = self.fakeCuttlefishServer.state.bottles[0]
- 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.assertAllCKKSViewsUpload(tlkShares: 1)
+ 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
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")
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)
}
func testViableBottleCachingAfterJoin() throws {
+ OctagonSetOptimizationEnabled(false)
let initiatorContextID = "initiator-context-id"
let bottlerContext = self.makeInitiatorContext(contextID: initiatorContextID)
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.assertAllCKKSViewsUpload(tlkShares: 1)
-
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()
}
- sleep(1)
- self.releaseCloudKitFetchHold()
-
self.wait(for: [joinWithBottleExpectation], timeout: 100)
let dumpCallback = self.expectation(description: "dumpCallback callback occurs")
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")
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.assertAllCKKSViewsUpload(tlkShares: 1)
-
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()
}
- sleep(1)
- self.releaseCloudKitFetchHold()
-
self.wait(for: [joinWithBottleExpectation], timeout: 100)
var egoPeerID: String?
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?
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
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 tto itself and the other
+ // 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.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")
+ "noShares should trust allShares")
XCTAssertTrue(self.fakeCuttlefishServer.assertCuttlefishState(FakeCuttlefishAssertion(peer: noSelfSharesPeerID, opinion: .trusts, target: noSelfSharesPeerID)),
"No shares should trust itself")
try self.putSelfTLKSharesInCloudKit(context: allSharesContext)
try self.putAllTLKSharesInCloudKit(to: noSelfSharesContext, from: allSharesContext)
- try self.ckksZones.forEach { zone in
- XCTAssertFalse(try self.tlkShareInCloudKit(receiverPeerID: noSelfSharesPeerID, senderPeerID: noSelfSharesPeerID, zoneID: zone as! CKRecordZone.ID), "Should not have self shares for noSelfShares")
- XCTAssertTrue(try self.tlkShareInCloudKit(receiverPeerID: noSelfSharesPeerID, senderPeerID: allSharesPeerID, zoneID: zone as! CKRecordZone.ID), "Should have a share for noSelfShares from allShares")
+ 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.assertAllCKKSViewsUpload(tlkShares: 1)
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)
}
}
--- /dev/null
+#if OCTAGON
+
+ let accountInfoWithInfoSample = """
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>SecureBackupAccountIsHighSecurity</key>
+ <false/>
+ <key>SecureBackupAlliCDPRecords</key>
+ <array>
+ <dict>
+ <key>SecureBackupEscrowDate</key>
+ <date>2020-01-31T03:07:40Z</date>
+ <key>SecureBackupRemainingAttempts</key>
+ <integer>10</integer>
+ <key>encodedMetadata</key>
+ <string>YnBsaXN0MDDZAQIDBAUGBwgJCgsMDQ4PECYgVnNlcmlhbF8QEkJhY2t1cEtleWJhZ0RpZ2VzdFVidWlsZFhwZWVySW5mb18QIGNvbS5hcHBsZS5zZWN1cmViYWNrdXAudGltZXN0YW1wWGJvdHRsZUlEXkNsaWVudE1ldGFkYXRhXGVzY3Jvd2VkU1BLSV8QHVNlY3VyZUJhY2t1cFVzZXNNdWx0aXBsZWlDU0NzXEMzOVYyMDlBSjlMNU8QFMhRrcsWNmcw7dI/9uhpDUpq4FZ2VjE4QTIxNE8RBLIwggSuMYIEYTAUDA9Db25mbGljdFZlcnNpb24CAQMwKwwPQXBwbGljYXRpb25EYXRlBBgYFjIwMjAwMTMwMjI0MTI2LjI4MDA1N1owVQwQUHVibGljU2lnbmluZ0tleQRBBOW+fXyAnCMa6by/cKGf1iHkcz9VEsa6rocBXgrLGVSb7Dy4XzT7fa1jf+X2co6ZTrXr3Vt56TBJZx8X6YNMY+swWAwPQXBwbGljYXRpb25Vc2lnBEUwQwIgY4hdZ7zcWd+Ue77JKF2OK99No8MUe9f5Fg2AzLviJKcCH04d5DOYNyFk6LTzWVuHD/2uMR7zASajNdfXbpFQ578wcAwNRGV2aWNlR2VzdGFsdDFfMBMMCU1vZGVsTmFtZQwGaVBob25lMBMMCU9TVmVyc2lvbgwGMThBMjE0MBYMDENvbXB1dGVyTmFtZQwGaVBob25lMBsMFk1lc3NhZ2VQcm90b2NvbFZlcnNpb24CAQAwfAwXT2N0YWdvblB1YmxpY1NpZ25pbmdLZXkEYQSguiFhjcalFK/bQBPruMsnWzZ0qv7VtPwmhjbdCQJ4mCMY1v6+60RCEsWMs+wQ200Tv40DvCBpzRABcsM70f8tuk1Q/wMXVDQ2kVfgmIVmobzvqNLwcSBHpU44nOEnNRkwfwwaT2N0YWdvblB1YmxpY0VuY3J5cHRpb25LZXkEYQQNGdKw9D+ZMSXl2YwRidBiFyb2GI/MGdDSCFDNvvRq5ig9sJHGMKgbswKltv7gkYzgvvg51slkltO0d5nQm0Juqj3dnIh9QtbPXfUew7LGjBNJIj3IOI8DJdnPqdGee+cwggH4DBBWMkRpY3Rpb25hcnlEYXRhBIIB4jGCAd4wEAwMRXNjcm93UmVjb3JkBQAwHAwMU2VyaWFsTnVtYmVyDAxDMzlWMjA5QUo5TDUwLQwJQmFja3VwS2V5BCBmWfEWzk0k71iVH/hINYf572sP/4l/uVZaMyhNb36frzBgDAxNYWNoaW5lSURLZXkMUHlXbkk4dmROZzZFV2F5ZVcvRlA0Y0RaUnNlM0xNbjhQeGcveC9zUHpaSklTNWNzM1JLbzQvc3RPVzQ2blE5OGlObHBTSHJuUjBrZnNiUjNYMIIBGQwFVmlld3PRggEODAdBcHBsZVRWDAdIb21lS2l0DAdQQ1MtRkRFDAlQQ1MtTm90ZXMMClBDUy1CYWNrdXAMClBDUy1Fc2Nyb3cMClBDUy1QaG90b3MMC0JhY2t1cEJhZ1YwDAtQQ1MtU2hhcmluZwwMTmFub1JlZ2lzdHJ5DAxQQ1MtQ2xvdWRLaXQMDFBDUy1GZWxkc3BhcgwMUENTLU1haWxkcm9wDAxQQ1MtaU1lc3NhZ2UMDVBDUy1NYXN0ZXJLZXkMDldhdGNoTWlncmF0aW9uDA5pQ2xvdWRJZGVudGl0eQwPUENTLWlDbG91ZERyaXZlDBBBY2Nlc3NvcnlQYWlyaW5nDBBDb250aW51aXR5VW5sb2NrBEcwRQIgRLmiTIo/hgxmoOMgZEygsTzdJiHOMTI68Y8DQGgXpWICIQCHr913nsr4kFaYZd3i/ioYQum8B5KOpxFR90u1CPgPEl8QEzIwMjAtMDEtMzEgMDM6MDc6NDBfECRERDVFM0Y5Ri0zNzAyLTQ3ODktOEFDRi0yRDI4QkM4NkE5NEPcERITFBUWFxgZGhscHQ4eHR8gISIjICMlXxAWZGV2aWNlX2VuY2xvc3VyZV9jb2xvcl8QHVNlY3VyZUJhY2t1cE1ldGFkYXRhVGltZXN0YW1wXxAPZGV2aWNlX3BsYXRmb3JtXGRldmljZV9jb2xvcl8QI1NlY3VyZUJhY2t1cE51bWVyaWNQYXNzcGhyYXNlTGVuZ3RoXxAhU2VjdXJlQmFja3VwVXNlc0NvbXBsZXhQYXNzcGhyYXNlWmRldmljZV9taWRfEBRkZXZpY2VfbW9kZWxfdmVyc2lvbltkZXZpY2VfbmFtZV8QIVNlY3VyZUJhY2t1cFVzZXNOdW1lcmljUGFzc3BocmFzZV8QEmRldmljZV9tb2RlbF9jbGFzc1xkZXZpY2VfbW9kZWxRMRQAAAAAAAAAAAAAAAAAAAABEAYJXxBQeVduSTh2ZE5nNkVXYXllVy9GUDRjRFpSc2UzTE1uOFB4Zy94L3NQelpKSVM1Y3MzUktvNC9zdE9XNDZuUTk4aU5scFNIcm5SMGtmc2JSM1haaVBob25lMTAsNVZpUGhvbmUJXWlQaG9uZSA4IFBsdXNPEHgwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATIde8QFJDJYQJa6NrxP5WDLEhPNga9732ZGyoVoKi0RnxT6aIlb/LBrRvnrdZFyGUMlSYGSY3GIgrLz3YJ0A0W4BN6YKMtsgGCDONSD5/KHRzTEAE5e3Yp26nshhMavOcJAAgAGwAiADcAPQBGAGkAcgCBAI4ArgC7ANIA2QWPBaUFzAXlBf4GHgYwBj0GYwaHBpIGqQa1BtkG7gb7Bv0HDgcQBxEHZAdvB3YHdweFCAAAAAAAAAACAQAAAAAAAAAoAAAAAAAAAAAAAAAAAAAIAQ==</string>
+ <key>label</key>
+ <string>com.apple.icdp.record</string>
+ <key>metadata</key>
+ <dict>
+ <key>BackupKeybagDigest</key>
+ <data>
+ yFGtyxY2ZzDt0j/26GkNSmrgVnY=
+ </data>
+ <key>ClientMetadata</key>
+ <dict>
+ <key>SecureBackupMetadataTimestamp</key>
+ <string>2020-01-31 03:07:40</string>
+ <key>SecureBackupNumericPassphraseLength</key>
+ <integer>6</integer>
+ <key>SecureBackupUsesComplexPassphrase</key>
+ <true/>
+ <key>SecureBackupUsesNumericPassphrase</key>
+ <true/>
+ <key>device_color</key>
+ <string>1</string>
+ <key>device_enclosure_color</key>
+ <string>1</string>
+ <key>device_mid</key>
+ <string>yWnI8vdNg6EWayeW/FP4cDZRse3LMn8Pxg/x/sPzZJIS5cs3RKo4/stOW46nQ98iNlpSHrnR0kfsbR3X</string>
+ <key>device_model</key>
+ <string>iPhone 8 Plus</string>
+ <key>device_model_class</key>
+ <string>iPhone</string>
+ <key>device_model_version</key>
+ <string>iPhone10,5</string>
+ <key>device_name</key>
+ <string>iPhone</string>
+ <key>device_platform</key>
+ <integer>1</integer>
+ </dict>
+ <key>SecureBackupUsesMultipleiCSCs</key>
+ <true/>
+ <key>bottleID</key>
+ <string>DD5E3F9F-3702-4789-8ACF-2D28BC86A94C</string>
+ <key>build</key>
+ <string>18A214</string>
+ <key>com.apple.securebackup.timestamp</key>
+ <string>2020-01-31 03:07:40</string>
+ <key>escrowedSPKI</key>
+ <data>
+ MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEyHXvEBSQyWEC
+ Wuja8T+VgyxITzYGve99mRsqFaCotEZ8U+miJW/ywa0b
+ 563WRchlDJUmBkmNxiIKy892CdANFuATemCjLbIBggzj
+ Ug+fyh0c0xABOXt2Kdup7IYTGrzn
+ </data>
+ <key>peerInfo</key>
+ <data>
+ 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=
+ </data>
+ <key>serial</key>
+ <string>C39V209AJ9L5</string>
+ </dict>
+ <key>osVersion</key>
+ <string>18A214</string>
+ <key>peerInfoSerialNumber</key>
+ <string>C39V209AJ9L5</string>
+ <key>recordID</key>
+ <string>sNs6voV0N35D/T91SuGmJnGO29</string>
+ <key>recordStatus</key>
+ <string>valid</string>
+ <key>silentAttemptAllowed</key>
+ <true/>
+ </dict>
+ </array>
+ <key>SecureBackupContainsiCloudIdentity</key>
+ <true/>
+ <key>SecureBackupEnabled</key>
+ <true/>
+ <key>SecureBackupEscrowTrustStatus</key>
+ <integer>0</integer>
+ <key>SecureBackupRecoveryRequiresVerificationToken</key>
+ <false/>
+ <key>SecureBackupStingrayMetadata</key>
+ <dict>
+ <key>BackupKeybagDigest</key>
+ <data>
+ LTrJHVHFZ5vQO59wUih1MEgg1qI=
+ </data>
+ <key>ClientMetadata</key>
+ <dict>
+ <key>SecureBackupClientVersion</key>
+ <string>iPhone OS;18A214</string>
+ <key>SecureBackupKeyRegistry</key>
+ <dict>
+ <key>AccessibilityVOPronunciation2</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYH5MIH2AgE0AgEBBCDeXT460rcv
+ jIDp8aJE+uDw1JKyosrd5OaCN/Ke
+ QJy+kqBlMGMwCgIBAwQFMAMCAQAw
+ JwIBBgQiBCAownsDFvISVYfCbbD/
+ 50T51ZSZzt04daIl5fdJpmI89jAs
+ AgEBBCcwJaAQDA5NYWMgT1MgWDsx
+ N0Q0N6ERGA8yMDE4MDkyODE5NDUz
+ MFqhZTBjBBQBooabXxCiCkCbBNbv
+ ACGlyp96aAIBAQRIMEYCIQDOAegi
+ 450wm5Yk2Qtu7sSf4/jGWzCWU0a4
+ FPRQSCgCUwIhANpyPSOc/yiCIIfd
+ YULrKwcZ0dm710etKYFNitrv8VRx
+ </data>
+ </array>
+ </dict>
+ <key>AccessibilityVOPronunciation3</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGSMIGPAgE1AgEBBCAmObm/AMsh
+ CPishw7Zj5VqF7pxEz7WPYFQoTdN
+ WC6PkqFlMGMEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEgwRgIhAKUc
+ sWDKPbwQt2TLHm2bzDWTVg2rOYrb
+ o+4sGs0sT5alAiEAv3x1jY/E/xXN
+ Jbex7oy7x0dLq4FGmNJFHWLQrDQd
+ GRw=
+ </data>
+ </array>
+ </dict>
+ <key>AccountData</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGRMIGOAgEmAgEBBCApjqgrPqZL
+ BVUo4ShL7VlQX14zLBzgjiiVP6ke
+ WE57G6FkMGIEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEcwRQIgaaOc
+ o1aiL8bKLKXv4WmWg6kRwTFQjdZM
+ S+GRIJmxe1oCIQDAdSxG+N8iojUF
+ dRAMlGqgzMZMVxKZDiviyf7O0YOR
+ 9Q==
+ </data>
+ </array>
+ </dict>
+ <key>Activities</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGRMIGOAgEOAgEBBCDXTpaU32V/
+ ljxo71s2tcojaFlrzWTu93dunzeY
+ 6K5TK6FkMGIEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEcwRQIhAMxT
+ 7l56PjtGjLM/rK1TLAeJmg5QkgIt
+ Mo77FSHyMHH/AiBjR6GOatFE+CtQ
+ uaz7uL+JNEoF0R0+1MykoHRSHqPI
+ pQ==
+ </data>
+ </array>
+ </dict>
+ <key>BTAnnouncement</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGQMIGNAgETAgEBBCD0zBfXeZOJ
+ FS8oXM/hL8rH9HaMyKBeHoOKMdfw
+ MtAo9qFjMGEEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEYwRAIgb/2S
+ ceDq75L07mzvNa3IgnlUh8hvlAAs
+ TJPyGtgFJNwCIGNWkSlYNNQEGUQZ
+ R9GHVgIWMD8ccRKjz17kMtdoJSkI
+ </data>
+ </array>
+ </dict>
+ <key>BTPairing</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGRMIGOAgESAgEBBCBsRs9WTIBy
+ 92mIMVd6URteSUxiAwRpHEKiT1ky
+ 0MZPOqFkMGIEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEcwRQIgQDg5
+ 9S8sDoDS4OkFJKCCOIo/0gkLy7ol
+ bA0ebbRqbOcCIQCONcU18leu/dVG
+ clWNgN4FPWIHMX3Xs6QD4h+hpJFs
+ 9g==
+ </data>
+ </array>
+ </dict>
+ <key>Backup</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGRMIGOAgEIAgEBBCBezDIWdM56
+ G/KBXahejdDg+W06PIZORqx808HB
+ k+J2dqFkMGIEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEcwRQIhAPF5
+ A/HcSV4gftgp/JNJt3YncN6UaO7W
+ fN2uLJpFVbtMAiBdbyb1R/79q4An
+ Mv+DFCsR274j/nc4TBJl52libm+i
+ 9g==
+ </data>
+ </array>
+ </dict>
+ <key>BluetoothCloudPairing2</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYH5MIH2AgEyAgEBBCClfvDzGvfD
+ bRAjpecc9+7M+if4wO/tdWQ8vOb1
+ 1L1+pKBlMGMwCgIBAwQFMAMCAQAw
+ JwIBBgQiBCAownsDFvISVYfCbbD/
+ 50T51ZSZzt04daIl5fdJpmI89jAs
+ AgEBBCcwJaAQDA5NYWMgT1MgWDsx
+ N0Q0N6ERGA8yMDE4MDkyODE5NDUz
+ MFqhZTBjBBQBooabXxCiCkCbBNbv
+ ACGlyp96aAIBAQRIMEYCIQD+DnMw
+ WzcKXCpNN7vODSoCFnuMeHrQV3Hd
+ E7W6PtJ7WwIhAPNmAa/o0hGaVoZQ
+ QMDMDy6x4aILZSev+q+H1SzxFU9P
+ </data>
+ </array>
+ </dict>
+ <key>BulkMail</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGRMIGOAgERAgEBBCCI3XoOP4Ko
+ su3w8M+ECPTMCnjbM3nLmjK/6WlJ
+ OUoIgaFkMGIEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEcwRQIhAIgz
+ I2bYHyqRHAQpYq3liI6jtn8ZT1ve
+ /Pz6euQP4NAuAiBB2dIbtiuwSxgV
+ IkqI699bhauRROHjO9r48FrjrTJl
+ cA==
+ </data>
+ </array>
+ </dict>
+ <key>CloudKit</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGSMIGPAgEEAgEBBCDX4Lqi2liR
+ QKhXA2QYm0l7edIQPhVLwuk/TWLl
+ yAT9PaFlMGMEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEgwRgIhAL2u
+ oy74rk2RNImZA2BlpEt1lbYXDjQD
+ LVWFl48ZiGflAiEArkFMxuEWlWOH
+ BtNjjZ44fmxKxWsZi8+NGAHfBCd+
+ IAU=
+ </data>
+ </array>
+ </dict>
+ <key>CloudKitApple</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGRMIGOAgEXAgEBBCAjsVTQ0pZm
+ rzPCJAdrUjU8RDTgE57XNKIyvXPY
+ 0HkVhqFkMGIEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEcwRQIgfrBi
+ TRmWf4KPF+HN26p3jCAjdIeTIySY
+ CHoXSYnuDxMCIQDPm8w+aF9D5f8n
+ ZdPGAJgZGf7IfYYej7uksgAfWpiv
+ 6Q==
+ </data>
+ </array>
+ </dict>
+ <key>Continuity</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGRMIGOAgEVAgEBBCAACkc0AMRb
+ cY8hsM3mTlgYJovohPSj6QIjo2tB
+ hGJGoaFkMGIEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEcwRQIgHKPo
+ mEfyG4Y5oqrUXC3ILH97fFYNLXT/
+ vxnypm4m3NACIQDO3uZEcTXfDXT7
+ 7iJlctPPnWtskWaGZdxaKSEdQ1Ga
+ BQ==
+ </data>
+ </array>
+ </dict>
+ <key>CoreSuggestionsPseudoEvents2</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYH3MIH0AgEzAgEBBCCvNPJB1xx7
+ x/4UOr+5IH/0UzVKX+QpvmqX7ODO
+ leMkrKBlMGMwCgIBAwQFMAMCAQAw
+ JwIBBgQiBCAownsDFvISVYfCbbD/
+ 50T51ZSZzt04daIl5fdJpmI89jAs
+ AgEBBCcwJaAQDA5NYWMgT1MgWDsx
+ N0Q0N6ERGA8yMDE4MDkyODE5NDUz
+ MFqhYzBhBBQBooabXxCiCkCbBNbv
+ ACGlyp96aAIBAQRGMEQCIGfKKUNL
+ wZhpIi9OIrEtkrsB7rzpdPRx/nc+
+ pd53aepmAiArIUBx0EAPslG1TrYH
+ SLNo0XCtF4C0ihTQfaJPBAiyqA==
+ </data>
+ </array>
+ </dict>
+ <key>Gaming</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGQMIGNAgEPAgEBBCDJbjy/eQN5
+ 71Uz8wPWukKE0SZY/QvIlA4GfkVy
+ 102fBqFjMGEEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEYwRAIgSrBW
+ Rcxox1/CdtChoDYXmabj8Y4vZYBS
+ LOgHMdIwKQoCIEkq6KImjlvmlWBk
+ ewyK0jUwqSyhtuJuJtXux0TUKIpa
+ </data>
+ </array>
+ </dict>
+ <key>KeyboardServices</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGSMIGPAgENAgEBBCAZ2Mqr74uD
+ cAkMedabKkMBE1YVv3r9BY+ZQxiz
+ tbxuOaFlMGMEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEgwRgIhAJSI
+ 7dsRXpoxNc7bFCtPFSDwUrWlwNbN
+ oa+j9VpBg/nqAiEAuj1iKHKO5ixZ
+ 92iBCwS6tta9CNYL8DZMMoJYhrkg
+ LSA=
+ </data>
+ </array>
+ </dict>
+ <key>Maildrop</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGQMIGNAgEHAgEBBCChFkKqgrWz
+ OfMgBCCorBsVT8hy+zmWs15UbouB
+ PzHsGKFjMGEEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEYwRAIgJUhO
+ SBsTLydtk7Xu0V2PP7A+Q3VoDsDr
+ JTGWbd8z01wCIE03dzox48zVifu5
+ Uo5LPTqD5n1HxwNX21flE1bs+W8Y
+ </data>
+ </array>
+ </dict>
+ <key>MapsSync</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGQMIGNAgEoAgEBBCADagtpAora
+ 2dL8YgDGudGGs9SNDfTdlEkAmFcE
+ DYVR76FjMGEEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEYwRAIgYIZn
+ OdcURVO0mg3mLmB3McpFItiTlpsv
+ 0fhSNluJZHYCIEX2PE8he+N4PSLE
+ q4HDjL2NVwGPX7mfXhQR/mrdrD+l
+ </data>
+ </array>
+ </dict>
+ <key>MasterKey</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYHDMIHAAgEBAgEBBCDBd3m4WFN5
+ LsrHxCmPrmepRrZHDyx66Xo8SFTT
+ 8u9bpqAwMC4wLAIBAQQnMCWgEAwO
+ TWFjIE9TIFg7MTdENDehERgPMjAx
+ ODA5MjgxOTQ1MjVaoWQwYgQUAaKG
+ m18QogpAmwTW7wAhpcqfemgCAQEE
+ RzBFAiB9fOTaJMlRDK+FkotvzkJu
+ jB1quh9OBx3CqmLNpiry1wIhAOJ4
+ wV3ckIwdzk/YNkGZLoSP9GhxsoY3
+ 0yQKPqkZzQEQ
+ </data>
+ </array>
+ </dict>
+ <key>Messages2</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYH3MIH0AgEpAgEBBCC/q5CztxOc
+ zrhN7w5PxTq2sWqTTdIRGht/2++h
+ NuGp36BlMGMwCgIBAwQFMAMCAQAw
+ JwIBBgQiBCAownsDFvISVYfCbbD/
+ 50T51ZSZzt04daIl5fdJpmI89jAs
+ AgEBBCcwJaAQDA5NYWMgT1MgWDsx
+ N0Q0N6ERGA8yMDE4MDkyODE5NDUz
+ MFqhYzBhBBQBooabXxCiCkCbBNbv
+ ACGlyp96aAIBAQRGMEQCIECcCDJY
+ COrM8qBndA7BeEQh8i70wcFIk34v
+ 0hyC1VEcAiAdpGuOYOq8iCydXCrZ
+ kUOOCLK97fcO89AxaaDQ49r2KA==
+ </data>
+ </array>
+ </dict>
+ <key>News</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGSMIGPAgELAgEBBCA3ZmHh5Ky4
+ vX3DShRnlUuRPEIL1k/g4tvJJbkF
+ 5IfVWaFlMGMEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEgwRgIhAMeT
+ 2qHhhVTbb/0mF5IMLllOCL4wljRT
+ TVKzc2tDhdVKAiEAgJVLdcM90d+3
+ j16ZxlF195knpfHs/9dor1wEIixd
+ EjY=
+ </data>
+ </array>
+ </dict>
+ <key>Notes</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGRMIGOAgEJAgEBBCCKIp/yJqTm
+ 4Iuf/SWj8j1YQa6azRmpCY/bKq/g
+ iO6aZqFkMGIEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEcwRQIhAOF5
+ JxJkSDXw6hNSF9eJkwt5cKRsMMV3
+ JuDJK/fBGW1lAiABjZZ1U+XzytGp
+ 5i1A6YgE7VVpR9btI6/QQi2iZbFA
+ Ag==
+ </data>
+ </array>
+ </dict>
+ <key>Photos</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGQMIGNAgEDAgEBBCCcav3S7T1z
+ VLM9B88tyXLT6Y5GjRD2jCzDdlKs
+ YdfhsaFjMGEEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEYwRAIgPwDW
+ JNcSN2+zAN47Hg0UcbnzPRbHJBR3
+ JrDpBOEn7pYCICtNOoLuVEwfqX7j
+ A2fX7soQVUfT4j/y34C5CPrIbKxL
+ </data>
+ </array>
+ </dict>
+ <key>Rawhide</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYH4MIH1AgE2AgEBBCAO/9RLJMcH
+ o3qhFeFb3qanoK8t49rSDrm9ilPv
+ AeiKJ6BlMGMwCgIBAwQFMAMCAQAw
+ JwIBBgQiBCAownsDFvISVYfCbbD/
+ 50T51ZSZzt04daIl5fdJpmI89jAs
+ AgEBBCcwJaAQDA5NYWMgT1MgWDsx
+ N0Q0N6ERGA8yMDE4MDkyODE5NDUz
+ MFqhZDBiBBQBooabXxCiCkCbBNbv
+ ACGlyp96aAIBAQRHMEUCIEqa4Rq2
+ iCw3ULDe3577bLpHuUyRvUDtEKE0
+ rS7H4IIGAiEA4yG/enWyQuz+TacB
+ Vbe3U0cZ8mNarFnCWvjagNZ/BU4=
+ </data>
+ </array>
+ </dict>
+ <key>Rawhide3</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYH4MIH1AgE4AgEBBCDfi1Ny5x/R
+ aYdLHWW+xFbNw90R5XCc5isHN6ud
+ qaGyKqBlMGMwCgIBAwQFMAMCAQAw
+ JwIBBgQiBCAownsDFvISVYfCbbD/
+ 50T51ZSZzt04daIl5fdJpmI89jAs
+ AgEBBCcwJaAQDA5NYWMgT1MgWDsx
+ N0Q0N6ERGA8yMDE4MDkyODE5NDUz
+ MFqhZDBiBBQBooabXxCiCkCbBNbv
+ ACGlyp96aAIBAQRHMEUCIQClF2jC
+ dx76r4x23i8sBLm6syiQYYhvPmC2
+ bEvnxPkxagIgUg/wLELGQMoReD12
+ SiiQglIgKNtzSuCgRfdUjAYB7fY=
+ </data>
+ </array>
+ </dict>
+ <key>Safari</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGRMIGOAgEWAgEBBCBqKP7jb+TP
+ nhhTpvziH9LG4aDa6i1IDLJmtFBl
+ 7u7AXKFkMGIEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEcwRQIgYT1t
+ a5nB5G1GRccSzXyo84mvxb3xTeqS
+ V0HNw3zP9uUCIQDnoAU+3LtXDkVK
+ 4n51tfLXr3XZIVEwPGImBB/p2qGx
+ QQ==
+ </data>
+ </array>
+ </dict>
+ <key>Sharing</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGRMIGOAgEMAgEBBCCeimmOmppn
+ EufS9uArUm8PTZ8AQfV1cAszCMD8
+ uJoN9qFkMGIEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEcwRQIgIyyv
+ XdIJY2RRQcBHo7Uf8qzZwq3GYHqK
+ yCbh3voiR2gCIQD/cgaeToE5Z7be
+ wD6evPVSPSXwBc7OH0FJFy+1iqCc
+ Og==
+ </data>
+ </array>
+ </dict>
+ <key>TTYCallHistory</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGRMIGOAgEUAgEBBCCNrMVagA0+
+ ttQkY4NGtYqj49b4PHHV7YFaAHyV
+ d9vodqFkMGIEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEcwRQIgAUD9
+ nE+lBkcEnXyL0pcE/LE4diyBd/Ub
+ osjHyB5j22wCIQCUcJfgxHVChg8A
+ e6FjMuYjf7cVoyNf0YmuUEWkmwvo
+ Ig==
+ </data>
+ </array>
+ </dict>
+ <key>com.apple.health.sync2</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYH3MIH0AgEsAgEBBCBC9NWuZFgs
+ rkDeXFDLnakWgoI4L/cXyz+m43lC
+ 2JWUJKBlMGMwCgIBAwQFMAMCAQAw
+ JwIBBgQiBCAownsDFvISVYfCbbD/
+ 50T51ZSZzt04daIl5fdJpmI89jAs
+ AgEBBCcwJaAQDA5NYWMgT1MgWDsx
+ N0Q0N6ERGA8yMDE4MDkyODE5NDUz
+ MFqhYzBhBBQBooabXxCiCkCbBNbv
+ ACGlyp96aAIBAQRGMEQCIGo37UsM
+ Xb7GaLeBwYfg302TWGv0xbM6XDuo
+ xi/RX09VAiBOSD4os5NX+GTYqLdR
+ erCTQ5dEVScIWaR6n45SATDuRg==
+ </data>
+ </array>
+ </dict>
+ <key>com.apple.icloud-appleid.privacy</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGRMIGOAgE/AgEBBCDyKeoxY5kg
+ 0jXZokvw9XIZk/dXsLybRdeGyOhC
+ RXTz/6FkMGIEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEcwRQIhANGl
+ TEY7KpACQHm7qcSuuS/j63P5/AHu
+ M/CFNtpxHPs2AiBB4iFuMmexGzcA
+ dxjD8AweXzf3BuT2eAMPveTum/As
+ YQ==
+ </data>
+ </array>
+ </dict>
+ <key>com.apple.knowledgestore2</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYH3MIH0AgEvAgEBBCBbIpT6tptz
+ 5puJ0XdYbcQiOBT9JDtH4o1W9en3
+ P4hJPqBlMGMwCgIBAwQFMAMCAQAw
+ JwIBBgQiBCAownsDFvISVYfCbbD/
+ 50T51ZSZzt04daIl5fdJpmI89jAs
+ AgEBBCcwJaAQDA5NYWMgT1MgWDsx
+ N0Q0N6ERGA8yMDE4MDkyODE5NDUz
+ MFqhYzBhBBQBooabXxCiCkCbBNbv
+ ACGlyp96aAIBAQRGMEQCIBEFJhmK
+ SW5huLbY39W2AuOZ7sMzOwTka/Bl
+ aOYDw/qNAiBNsupg44L53rbTy0+J
+ ItQBOKQPFMyS4ggM+38xEh1o/w==
+ </data>
+ </array>
+ </dict>
+ <key>com.apple.news.private.secure2</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYH3MIH0AgExAgEBBCBjOqSZoGDw
+ ScKt5ncrZEkl/5e43V/wCItiOI3f
+ fCu3XaBlMGMwCgIBAwQFMAMCAQAw
+ JwIBBgQiBCAownsDFvISVYfCbbD/
+ 50T51ZSZzt04daIl5fdJpmI89jAs
+ AgEBBCcwJaAQDA5NYWMgT1MgWDsx
+ N0Q0N6ERGA8yMDE4MDkyODE5NDUz
+ MFqhYzBhBBQBooabXxCiCkCbBNbv
+ ACGlyp96aAIBAQRGMEQCIBbcBuay
+ kWaCE1IFXL/4nmckm8tSDLnSLUje
+ T2YtgVB6AiA7S+NREY9sOh3WrB5p
+ VpmZfhd3Blv6JbeHkBsMjWDCUg==
+ </data>
+ </array>
+ </dict>
+ <key>com.apple.routined2</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYH4MIH1AgErAgEBBCCO6YXL9f4P
+ kkoFCTOYTejP548/+n2QYLyev/v9
+ 60tVSKBlMGMwCgIBAwQFMAMCAQAw
+ JwIBBgQiBCAownsDFvISVYfCbbD/
+ 50T51ZSZzt04daIl5fdJpmI89jAs
+ AgEBBCcwJaAQDA5NYWMgT1MgWDsx
+ N0Q0N6ERGA8yMDE4MDkyODE5NDUz
+ MFqhZDBiBBQBooabXxCiCkCbBNbv
+ ACGlyp96aAIBAQRHMEUCIG1WEsAe
+ upMhR1v7+1RxWB5AosnbhgnLueM0
+ FT4xIYFgAiEAokT0B7qa+pQMJgVi
+ Jy48mJOwTbFTVcN9Csz1cbxD6+w=
+ </data>
+ </array>
+ </dict>
+ <key>com.apple.siri.knowledge2</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYH5MIH2AgEuAgEBBCCM34oVJt4n
+ 8zzP2NzHDaKADwE6BqMEvWbXPXnG
+ LiJfzaBlMGMwCgIBAwQFMAMCAQAw
+ JwIBBgQiBCAownsDFvISVYfCbbD/
+ 50T51ZSZzt04daIl5fdJpmI89jAs
+ AgEBBCcwJaAQDA5NYWMgT1MgWDsx
+ N0Q0N6ERGA8yMDE4MDkyODE5NDUz
+ MFqhZTBjBBQBooabXxCiCkCbBNbv
+ ACGlyp96aAIBAQRIMEYCIQD+HNJz
+ cwUhn+8nGbYmaXsYgjUN5IGBuhwG
+ kkws3W66pAIhAIHSbuQ7n6p/Rkjs
+ KOeVOq25ZcL+3hibiJJZIvNEqtSU
+ </data>
+ </array>
+ </dict>
+ <key>com.apple.siri.profile2</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYH3MIH0AgEtAgEBBCCOKC4GWP07
+ MXtnJuAXpyVkRwrXBhFMf1fEv1EN
+ L2HFGKBlMGMwCgIBAwQFMAMCAQAw
+ JwIBBgQiBCAownsDFvISVYfCbbD/
+ 50T51ZSZzt04daIl5fdJpmI89jAs
+ AgEBBCcwJaAQDA5NYWMgT1MgWDsx
+ N0Q0N6ERGA8yMDE4MDkyODE5NDUz
+ MFqhYzBhBBQBooabXxCiCkCbBNbv
+ ACGlyp96aAIBAQRGMEQCID6kHeWN
+ nKA2CRiHtOssTg7KKMONOf5K8wnO
+ spBk+d9vAiBKRpXkBbHzObbc9Sz6
+ 3WEfAi+2Z6iOZ+vVDVirAbFr/A==
+ </data>
+ </array>
+ </dict>
+ <key>com.apple.textinput.KeyboardServices.Secure2</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYH4MIH1AgEqAgEBBCDtVL0VIeP3
+ V7gD9jkiaWu4xwxe215t3PammS0L
+ No2WIaBlMGMwCgIBAwQFMAMCAQAw
+ JwIBBgQiBCAownsDFvISVYfCbbD/
+ 50T51ZSZzt04daIl5fdJpmI89jAs
+ AgEBBCcwJaAQDA5NYWMgT1MgWDsx
+ N0Q0N6ERGA8yMDE4MDkyODE5NDUz
+ MFqhZDBiBBQBooabXxCiCkCbBNbv
+ ACGlyp96aAIBAQRHMEUCIQCLfuV/
+ Hulb54Wrc8pNt1ibM8IFuN6XvkDj
+ ijiryyxGVgIgHfaVTZE/F2b02h4X
+ aAPBi1YIDvMAoycxd9ylXQI1cr0=
+ </data>
+ </array>
+ </dict>
+ <key>com.apple.wallet.paymentservices2</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYH4MIH1AgEwAgEBBCDMr1rH/wSx
+ KnXhhMuq2kmQAsbuu8aQ7CUjAaP7
+ ltmt56BlMGMwCgIBAwQFMAMCAQAw
+ JwIBBgQiBCAownsDFvISVYfCbbD/
+ 50T51ZSZzt04daIl5fdJpmI89jAs
+ AgEBBCcwJaAQDA5NYWMgT1MgWDsx
+ N0Q0N6ERGA8yMDE4MDkyODE5NDUz
+ MFqhZDBiBBQBooabXxCiCkCbBNbv
+ ACGlyp96aAIBAQRHMEUCIQC2O2y2
+ BdX70rfntL/TRaSfQ2hi2HDlJRcD
+ Y4Ac7dTNDAIgMCCNLTjH3w3yanom
+ cdUpUYpUXk0xg7rmWv776V2/ph0=
+ </data>
+ </array>
+ </dict>
+ <key>iAD</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGQMIGNAgEQAgEBBCDcezl6FqtG
+ yHkX174CEG8VSAOi4P3lIlFNO4qJ
+ fVX0saFjMGEEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEYwRAIgQvuS
+ zR9rw1O2ySTcaQADxxJd1GuffZ2c
+ xK1kGvS45cUCICC++3nOux4yl6TG
+ ku4P9QDla3NQp/7hH+lKmOIpvcOk
+ </data>
+ </array>
+ </dict>
+ <key>iCloudDrive</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGRMIGOAgECAgEBBCAXOlNsMQNV
+ JQUY+dqcGt39XUTbDVT2ksgEBMVv
+ yOjkPaFkMGIEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEcwRQIhAIL+
+ 1l8MsRW3rN9wMeM7tSinakp/c2/D
+ p2kO8Z8OZBxSAiAL15IC/CrJgkQL
+ yS4rarGeTmMFKGz34i/jQ1AQHzQy
+ 0Q==
+ </data>
+ </array>
+ </dict>
+ <key>iMessage</key>
+ <dict>
+ <key>PublicIdentities</key>
+ <array>
+ <data>
+ YYGQMIGNAgEKAgEBBCDK+TvjMZ0j
+ zhAklsGuo1nbUpfAsRutInhCa0uX
+ k/HLA6FjMGEEFAGihptfEKIKQJsE
+ 1u8AIaXKn3poAgEBBEYwRAIgaDaM
+ i4SMzCnvHsQyB4k94BaG6y34FbB3
+ LDlMT2pa7EYCIHJGgdwlbbRfFyYz
+ j08ohfXpCRbck5akTbDkOxRYIdyB
+ </data>
+ </array>
+ </dict>
+ </dict>
+ <key>SecureBackupStableMetadata</key>
+ <dict>
+ <key>EscrowKey</key>
+ <string>wVKb12gOwEEtjafTc2RgvD+ONtNzFtZ/v9mEkf1Dd3k=</string>
+ <key>LooseLeaves</key>
+ <dict>
+ <key>AccessibilityVOPronunciation3</key>
+ <array>
+ <data>
+ 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
+ </data>
+ </array>
+ <key>AccountData</key>
+ <array>
+ <data>
+ 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=
+ </data>
+ </array>
+ <key>Activities</key>
+ <array>
+ <data>
+ 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=
+ </data>
+ </array>
+ <key>BTAnnouncement</key>
+ <array>
+ <data>
+ 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==
+ </data>
+ </array>
+ <key>BTPairing</key>
+ <array>
+ <data>
+ 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=
+ </data>
+ </array>
+ <key>Backup</key>
+ <array>
+ <data>
+ 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=
+ </data>
+ </array>
+ <key>BulkMail</key>
+ <array>
+ <data>
+ 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=
+ </data>
+ </array>
+ <key>CloudKit</key>
+ <array>
+ <data>
+ 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
+ </data>
+ </array>
+ <key>CloudKitApple</key>
+ <array>
+ <data>
+ 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=
+ </data>
+ </array>
+ <key>Continuity</key>
+ <array>
+ <data>
+ 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=
+ </data>
+ </array>
+ <key>Escrow</key>
+ <array>
+ <data>
+ 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
+ </data>
+ </array>
+ <key>FDE</key>
+ <array>
+ <data>
+ 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=
+ </data>
+ </array>
+ <key>Gaming</key>
+ <array>
+ <data>
+ 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==
+ </data>
+ </array>
+ <key>KeyboardServices</key>
+ <array>
+ <data>
+ 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
+ </data>
+ </array>
+ <key>Maildrop</key>
+ <array>
+ <data>
+ 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==
+ </data>
+ </array>
+ <key>MapsSync</key>
+ <array>
+ <data>
+ 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==
+ </data>
+ </array>
+ <key>MasterKey</key>
+ <array>
+ <data>
+ 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
+ </data>
+ </array>
+ <key>News</key>
+ <array>
+ <data>
+ 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
+ </data>
+ </array>
+ <key>Notes</key>
+ <array>
+ <data>
+ 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=
+ </data>
+ </array>
+ <key>Photos</key>
+ <array>
+ <data>
+ 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==
+ </data>
+ </array>
+ <key>Safari</key>
+ <array>
+ <data>
+ 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=
+ </data>
+ </array>
+ <key>Sharing</key>
+ <array>
+ <data>
+ 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=
+ </data>
+ </array>
+ <key>TTYCallHistory</key>
+ <array>
+ <data>
+ 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=
+ </data>
+ </array>
+ <key>com.apple.icloud-appleid.privacy</key>
+ <array>
+ <data>
+ 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=
+ </data>
+ </array>
+ <key>iAD</key>
+ <array>
+ <data>
+ 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==
+ </data>
+ </array>
+ <key>iCloudDrive</key>
+ <array>
+ <data>
+ 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=
+ </data>
+ </array>
+ <key>iMessage</key>
+ <array>
+ <data>
+ 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==
+ </data>
+ </array>
+ </dict>
+ </dict>
+ <key>SecureBackupiCloudDataProtection</key>
+ <dict>
+ <key>kPCSMetadataEscrowedKeys</key>
+ <data>
+ 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==
+ </data>
+ <key>kPCSMetadataiCDP</key>
+ <true/>
+ <key>kPCSMetadataiCDPArmed</key>
+ <true/>
+ </dict>
+ <key>SecureBackupiCloudIdentityPublicData</key>
+ <data>
+ YYGRMIGOAgECAgEBBCAXOlNsMQNVJQUY+dqcGt39XUTbDVT2ksgE
+ BMVvyOjkPaFkMGIEFAGihptfEKIKQJsE1u8AIaXKn3poAgEBBEcw
+ RQIhAIL+1l8MsRW3rN9wMeM7tSinakp/c2/Dp2kO8Z8OZBxSAiAL
+ 15IC/CrJgkQLyS4rarGeTmMFKGz34i/jQ1AQHzQy0Q==
+ </data>
+ </dict>
+ <key>com.apple.securebackup.timestamp</key>
+ <string>2018-09-28 19:45:25</string>
+ </dict>
+ <key>SecureBackupStingrayMetadataHash</key>
+ <dict>
+ <key>BackupKeybagDigest</key>
+ <data>
+ LTrJHVHFZ5vQO59wUih1MEgg1qI=
+ </data>
+ <key>com.apple.securebackup.timestamp</key>
+ <string>2018-09-28 19:45:25</string>
+ <key>encodedMetadata</key>
+ <string>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</string>
+ </dict>
+ <key>SecureBackupStableMetadata</key>
+ <false/>
+ <key>SecureBackupUsesRecoveryKey</key>
+ <false/>
+ <key>SecureBackupiCDPRecords</key>
+ <array>
+ <dict>
+ <key>SecureBackupEscrowDate</key>
+ <date>2020-01-31T03:07:40Z</date>
+ <key>SecureBackupRemainingAttempts</key>
+ <integer>10</integer>
+ <key>encodedMetadata</key>
+ <string>YnBsaXN0MDDZAQIDBAUGBwgJCgsMDQ4PECYgVnNlcmlhbF8QEkJhY2t1cEtleWJhZ0RpZ2VzdFVidWlsZFhwZWVySW5mb18QIGNvbS5hcHBsZS5zZWN1cmViYWNrdXAudGltZXN0YW1wWGJvdHRsZUlEXkNsaWVudE1ldGFkYXRhXGVzY3Jvd2VkU1BLSV8QHVNlY3VyZUJhY2t1cFVzZXNNdWx0aXBsZWlDU0NzXEMzOVYyMDlBSjlMNU8QFMhRrcsWNmcw7dI/9uhpDUpq4FZ2VjE4QTIxNE8RBLIwggSuMYIEYTAUDA9Db25mbGljdFZlcnNpb24CAQMwKwwPQXBwbGljYXRpb25EYXRlBBgYFjIwMjAwMTMwMjI0MTI2LjI4MDA1N1owVQwQUHVibGljU2lnbmluZ0tleQRBBOW+fXyAnCMa6by/cKGf1iHkcz9VEsa6rocBXgrLGVSb7Dy4XzT7fa1jf+X2co6ZTrXr3Vt56TBJZx8X6YNMY+swWAwPQXBwbGljYXRpb25Vc2lnBEUwQwIgY4hdZ7zcWd+Ue77JKF2OK99No8MUe9f5Fg2AzLviJKcCH04d5DOYNyFk6LTzWVuHD/2uMR7zASajNdfXbpFQ578wcAwNRGV2aWNlR2VzdGFsdDFfMBMMCU1vZGVsTmFtZQwGaVBob25lMBMMCU9TVmVyc2lvbgwGMThBMjE0MBYMDENvbXB1dGVyTmFtZQwGaVBob25lMBsMFk1lc3NhZ2VQcm90b2NvbFZlcnNpb24CAQAwfAwXT2N0YWdvblB1YmxpY1NpZ25pbmdLZXkEYQSguiFhjcalFK/bQBPruMsnWzZ0qv7VtPwmhjbdCQJ4mCMY1v6+60RCEsWMs+wQ200Tv40DvCBpzRABcsM70f8tuk1Q/wMXVDQ2kVfgmIVmobzvqNLwcSBHpU44nOEnNRkwfwwaT2N0YWdvblB1YmxpY0VuY3J5cHRpb25LZXkEYQQNGdKw9D+ZMSXl2YwRidBiFyb2GI/MGdDSCFDNvvRq5ig9sJHGMKgbswKltv7gkYzgvvg51slkltO0d5nQm0Juqj3dnIh9QtbPXfUew7LGjBNJIj3IOI8DJdnPqdGee+cwggH4DBBWMkRpY3Rpb25hcnlEYXRhBIIB4jGCAd4wEAwMRXNjcm93UmVjb3JkBQAwHAwMU2VyaWFsTnVtYmVyDAxDMzlWMjA5QUo5TDUwLQwJQmFja3VwS2V5BCBmWfEWzk0k71iVH/hINYf572sP/4l/uVZaMyhNb36frzBgDAxNYWNoaW5lSURLZXkMUHlXbkk4dmROZzZFV2F5ZVcvRlA0Y0RaUnNlM0xNbjhQeGcveC9zUHpaSklTNWNzM1JLbzQvc3RPVzQ2blE5OGlObHBTSHJuUjBrZnNiUjNYMIIBGQwFVmlld3PRggEODAdBcHBsZVRWDAdIb21lS2l0DAdQQ1MtRkRFDAlQQ1MtTm90ZXMMClBDUy1CYWNrdXAMClBDUy1Fc2Nyb3cMClBDUy1QaG90b3MMC0JhY2t1cEJhZ1YwDAtQQ1MtU2hhcmluZwwMTmFub1JlZ2lzdHJ5DAxQQ1MtQ2xvdWRLaXQMDFBDUy1GZWxkc3BhcgwMUENTLU1haWxkcm9wDAxQQ1MtaU1lc3NhZ2UMDVBDUy1NYXN0ZXJLZXkMDldhdGNoTWlncmF0aW9uDA5pQ2xvdWRJZGVudGl0eQwPUENTLWlDbG91ZERyaXZlDBBBY2Nlc3NvcnlQYWlyaW5nDBBDb250aW51aXR5VW5sb2NrBEcwRQIgRLmiTIo/hgxmoOMgZEygsTzdJiHOMTI68Y8DQGgXpWICIQCHr913nsr4kFaYZd3i/ioYQum8B5KOpxFR90u1CPgPEl8QEzIwMjAtMDEtMzEgMDM6MDc6NDBfECRERDVFM0Y5Ri0zNzAyLTQ3ODktOEFDRi0yRDI4QkM4NkE5NEPcERITFBUWFxgZGhscHQ4eHR8gISIjICMlXxAWZGV2aWNlX2VuY2xvc3VyZV9jb2xvcl8QHVNlY3VyZUJhY2t1cE1ldGFkYXRhVGltZXN0YW1wXxAPZGV2aWNlX3BsYXRmb3JtXGRldmljZV9jb2xvcl8QI1NlY3VyZUJhY2t1cE51bWVyaWNQYXNzcGhyYXNlTGVuZ3RoXxAhU2VjdXJlQmFja3VwVXNlc0NvbXBsZXhQYXNzcGhyYXNlWmRldmljZV9taWRfEBRkZXZpY2VfbW9kZWxfdmVyc2lvbltkZXZpY2VfbmFtZV8QIVNlY3VyZUJhY2t1cFVzZXNOdW1lcmljUGFzc3BocmFzZV8QEmRldmljZV9tb2RlbF9jbGFzc1xkZXZpY2VfbW9kZWxRMRQAAAAAAAAAAAAAAAAAAAABEAYJXxBQeVduSTh2ZE5nNkVXYXllVy9GUDRjRFpSc2UzTE1uOFB4Zy94L3NQelpKSVM1Y3MzUktvNC9zdE9XNDZuUTk4aU5scFNIcm5SMGtmc2JSM1haaVBob25lMTAsNVZpUGhvbmUJXWlQaG9uZSA4IFBsdXNPEHgwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATIde8QFJDJYQJa6NrxP5WDLEhPNga9732ZGyoVoKi0RnxT6aIlb/LBrRvnrdZFyGUMlSYGSY3GIgrLz3YJ0A0W4BN6YKMtsgGCDONSD5/KHRzTEAE5e3Yp26nshhMavOcJAAgAGwAiADcAPQBGAGkAcgCBAI4ArgC7ANIA2QWPBaUFzAXlBf4GHgYwBj0GYwaHBpIGqQa1BtkG7gb7Bv0HDgcQBxEHZAdvB3YHdweFCAAAAAAAAAACAQAAAAAAAAAoAAAAAAAAAAAAAAAAAAAIAQ==</string>
+ <key>label</key>
+ <string>com.apple.icdp.record</string>
+ <key>metadata</key>
+ <dict>
+ <key>BackupKeybagDigest</key>
+ <data>
+ yFGtyxY2ZzDt0j/26GkNSmrgVnY=
+ </data>
+ <key>ClientMetadata</key>
+ <dict>
+ <key>SecureBackupMetadataTimestamp</key>
+ <string>2020-01-31 03:07:40</string>
+ <key>SecureBackupNumericPassphraseLength</key>
+ <integer>6</integer>
+ <key>SecureBackupUsesComplexPassphrase</key>
+ <true/>
+ <key>SecureBackupUsesNumericPassphrase</key>
+ <true/>
+ <key>device_color</key>
+ <string>1</string>
+ <key>device_enclosure_color</key>
+ <string>1</string>
+ <key>device_mid</key>
+ <string>yWnI8vdNg6EWayeW/FP4cDZRse3LMn8Pxg/x/sPzZJIS5cs3RKo4/stOW46nQ98iNlpSHrnR0kfsbR3X</string>
+ <key>device_model</key>
+ <string>iPhone 8 Plus</string>
+ <key>device_model_class</key>
+ <string>iPhone</string>
+ <key>device_model_version</key>
+ <string>iPhone10,5</string>
+ <key>device_name</key>
+ <string>iPhone</string>
+ <key>device_platform</key>
+ <integer>1</integer>
+ </dict>
+ <key>SecureBackupUsesMultipleiCSCs</key>
+ <true/>
+ <key>bottleID</key>
+ <string>DD5E3F9F-3702-4789-8ACF-2D28BC86A94C</string>
+ <key>bottleValid</key>
+ <string>valid</string>
+ <key>build</key>
+ <string>18A214</string>
+ <key>com.apple.securebackup.timestamp</key>
+ <string>2020-01-31 03:07:40</string>
+ <key>escrowedSPKI</key>
+ <data>
+ MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEyHXvEBSQyWEC
+ Wuja8T+VgyxITzYGve99mRsqFaCotEZ8U+miJW/ywa0b
+ 563WRchlDJUmBkmNxiIKy892CdANFuATemCjLbIBggzj
+ Ug+fyh0c0xABOXt2Kdup7IYTGrzn
+ </data>
+ <key>peerInfo</key>
+ <data>
+ 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=
+ </data>
+ <key>serial</key>
+ <string>C39V209AJ9L5</string>
+ </dict>
+ <key>osVersion</key>
+ <string>18A214</string>
+ <key>peerInfoSerialNumber</key>
+ <string>C39V209AJ9L5</string>
+ <key>recordID</key>
+ <string>sNs6voV0N35D/T91SuGmJnGO29</string>
+ <key>recordStatus</key>
+ <string>valid</string>
+ <key>silentAttemptAllowed</key>
+ <true/>
+ </dict>
+ </array>
+ <key>SecureBackupiCloudDataProtectionEnabled</key>
+ <false/>
+</dict>
+</plist>
+
+"""
+#endif
let peer1ID = self.assertResetAndBecomeTrustedInDefaultContext()
// Now, we'll approve a new peer with a new policy! First, make that new policy.
- let currentPolicyOptional = builtInPolicyDocuments().filter { $0.version.versionNumber == prevailingPolicyVersion.versionNumber }.first
+ let currentPolicyOptional = builtInPolicyDocuments().first { $0.version.versionNumber == prevailingPolicyVersion.versionNumber }
XCTAssertNotNil(currentPolicyOptional, "Should have one current policy")
let currentPolicy = currentPolicyOptional!
osVersion: "something",
policyVersion: newPolicy.version,
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 the second peer")
XCTAssertNotNil(peerID, "Should have a peerID")
peer2ID = peerID!
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()
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()
}
func testRejectVouchingForPeerWithUnknownNewPolicy() throws {
_ = self.assertResetAndBecomeTrustedInDefaultContext()
// Now, a new peer joins with a policy we can't fetch
- let currentPolicyOptional = builtInPolicyDocuments().filter { $0.version.versionNumber == prevailingPolicyVersion.versionNumber }.first
+ let currentPolicyOptional = builtInPolicyDocuments().first { $0.version.versionNumber == prevailingPolicyVersion.versionNumber }
XCTAssertNotNil(currentPolicyOptional, "Should have one current policy")
let currentPolicy = currentPolicyOptional!
osVersion: "something",
policyVersion: newPolicy.version,
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 the second peer")
XCTAssertNotNil(peerID, "Should have a peerID")
let peer1ID = self.assertResetAndBecomeTrustedInDefaultContext()
// Now, a new peer joins with a policy we can't fetch
- let currentPolicyOptional = builtInPolicyDocuments().filter { $0.version.versionNumber == prevailingPolicyVersion.versionNumber }.first
+ let currentPolicyOptional = builtInPolicyDocuments().first { $0.version.versionNumber == prevailingPolicyVersion.versionNumber }
XCTAssertNotNil(currentPolicyOptional, "Should have one current policy")
let currentPolicy = currentPolicyOptional!
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().filter { $0.version.versionNumber == prevailingPolicyVersion.versionNumber }.first
+ let currentPolicyOptional = builtInPolicyDocuments().first { $0.version.versionNumber == prevailingPolicyVersion.versionNumber }
XCTAssertNotNil(currentPolicyOptional, "Should have one current policy")
let currentPolicyDocument = currentPolicyOptional!
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,
- hashAlgo: .SHA256)
+ 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,
+ 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,
+ hashAlgo: .SHA256)
+
+ self.fakeCuttlefishServer.policyOverlay.append(newPolicyDocument)
+
+ return newPolicyDocument
+ }
+
func testRestoreBottledPeerUsingFuturePolicy() throws {
let (newPolicyDocument, futureViewZoneID) = try self.createOctagonAndCKKSUsingFuturePolicy()
self.putFakeKeyHierarchiesInCloudKit()
try self.putSelfTLKSharesInCloudKit(context: futurePeerContext)
- XCTAssertTrue(try self.tlkShareInCloudKit(receiverPeerID: futurePeerID, senderPeerID: futurePeerID, zoneID: futureViewZoneID))
+ XCTAssertTrue(self.tlkShareInCloudKit(receiverPeerID: futurePeerID, senderPeerID: futurePeerID, zoneID: futureViewZoneID))
// Now, our peer (with no inbuilt knowledge of newPolicyDocument) joins via escrow recovery.
- // 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
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(try self.tlkShareInCloudKit(receiverPeerID: peerID, senderPeerID: peerID, zoneID: futureViewZoneID))
+ XCTAssertTrue(self.tlkShareInCloudKit(receiverPeerID: peerID, senderPeerID: peerID, zoneID: futureViewZoneID))
}
func testPairingJoinUsingFuturePolicy() throws {
self.putFakeKeyHierarchiesInCloudKit()
try self.putSelfTLKSharesInCloudKit(context: futurePeerContext)
- XCTAssertTrue(try self.tlkShareInCloudKit(receiverPeerID: futurePeerID, senderPeerID: futurePeerID, zoneID: futureViewZoneID))
+ 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
// 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.sendAllCKKSViewsZoneChanged()
+ 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.wait(for: [serverJoinExpectation], timeout: 10)
// And the joined peer should have recovered the TLK, and uploaded itself a share
- XCTAssertTrue(try self.tlkShareInCloudKit(receiverPeerID: peerID, senderPeerID: peerID, zoneID: futureViewZoneID))
+ XCTAssertTrue(self.tlkShareInCloudKit(receiverPeerID: peerID, senderPeerID: peerID, zoneID: futureViewZoneID))
}
func testRecoveryKeyJoinUsingFuturePolicy() throws {
self.putFakeKeyHierarchiesInCloudKit()
try self.putSelfTLKSharesInCloudKit(context: futurePeerContext)
- XCTAssertTrue(try self.tlkShareInCloudKit(receiverPeerID: futurePeerID, senderPeerID: futurePeerID, zoneID: futureViewZoneID))
+ XCTAssertTrue(self.tlkShareInCloudKit(receiverPeerID: futurePeerID, senderPeerID: futurePeerID, zoneID: futureViewZoneID))
// Create the recovery key
let recoveryKey = SecPasswordGenerate(SecPasswordType(kSecPasswordTypeiCloudRecoveryKey), nil, nil)! as String
return nil
}
- // It should recover and upload the FutureView TLK
- self.assertAllCKKSViewsUpload(tlkShares: 1)
-
self.cuttlefishContext.startOctagonStateMachine()
self.assertEnters(context: self.cuttlefishContext, state: OctagonStateUntrusted, within: 10 * NSEC_PER_SEC)
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)
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)
self.assertResetAndBecomeTrustedInDefaultContext()
// Now, another peer comes along and joins via BP recovery, using a new policy
- let (newPolicyDocument, _) = try self.createOctagonAndCKKSUsingFuturePolicy()
+ 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()
+ 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
- }
+ 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
+ self.fakeCuttlefishServer.updateListener = {
+ request in
let newStableInfo = request.stableInfoAndSig.stableInfo()
XCTAssertEqual(newStableInfo.frozenPolicyVersion, frozenPolicyVersion, "Policy version in peer should match frozen policy version")
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)
}
}
#if OCTAGON
class OctagonHealthCheckTests: OctagonTestsBase {
-
func testHealthCheckAllTrusted() throws {
let containerName = OTCKContainerName
let contextName = OTDefaultContext
self.assertConsidersSelfUntrusted(context: self.cuttlefishContext)
#if os(tvOS)
- XCTAssertEqual(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), 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.followupHandler.hasPosted(.stateRepair), 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.wait(for: [healthCheckCallback2], timeout: 10)
#if os(tvOS)
- XCTAssertEqual(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), 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.followupHandler.hasPosted(.stateRepair), true, "Should have posted a CFU")
+ XCTAssertTrue(self.cuttlefishContext.followupHandler.hasPosted(.stateRepair), "Should have posted a CFU")
#endif
}
}
func testHealthCheckWhenLocked() throws {
-
let containerName = OTCKContainerName
let contextName = OTDefaultContext
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
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: <rdar://problem/49080104> 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()
+
+ 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 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
}
}
+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
@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: 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
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"
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.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
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]
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,
self.assertEnters(context: establishContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC)
self.assertConsidersSelfTrusted(context: establishContext)
+ 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
}
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()
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")
stableInfoAcceptorCheckDumpCallback.fulfill()
}
self.wait(for: [stableInfoAcceptorCheckDumpCallback], timeout: 10)
- try self.putSelfTLKSharesInCloudKit(context: recoveryContext)
+
+ // 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)
}
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)
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]
}
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()
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?
// Fake that this peer also created some TLKShares for itself
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()
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
XCTAssertNotNil(dump, "dump should not be nil")
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.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? [String: AnyObject]
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 {
self.assertSelfTLKSharesInCloudKit(context: establishContext)
- let recoveryKey = SecRKCreateRecoveryKeyString(nil)
- XCTAssertNotNil(recoveryKey, "recoveryKey should not be nil")
+ 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()
}
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 {
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
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 {
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")
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 {
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) -> String {
+ 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 = SecRKCreateRecoveryKeyString(nil)
- XCTAssertNotNil(recoveryKey, "recoveryKey should not be nil")
+ 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
+ TestsObjectiveC.setNewRecoveryKeyWithData(cliqueConfiguration, recoveryKey: recoveryKey) { _, error in
XCTAssertNil(error, "error should be nil")
setRecoveryKeyExpectation.fulfill()
}
self.wait(for: [setRecoveryKeyExpectation], timeout: 10)
- return recoveryKey!
+ return recoveryKey
}
func testConcurWithTrustedPeer() throws {
self.verifyDatabaseMocks()
// peer1 sets a recovery key
- var rkSigningPubKey : Data? = nil
- var rkEncryptionPubKey : Data? = nil
+ var rkSigningPubKey: Data?
+ var rkEncryptionPubKey: Data?
let setRKExpectation = self.expectation(description: "setRecoveryKey")
self.fakeCuttlefishServer.setRecoveryKeyListener = { request in
return nil
}
- self.createAndSetRecoveryKey(context: self.cuttlefishContext)
+ try self.createAndSetRecoveryKey(context: self.cuttlefishContext)
self.wait(for: [setRKExpectation], timeout: 10)
// And peer2 concurs with it upon receiving a push
self.startCKAccountStatusMock()
self.manager.setSOSEnabledForPlatformFlag(true)
- let _ = self.assertResetAndBecomeTrustedInDefaultContext()
+ _ = self.assertResetAndBecomeTrustedInDefaultContext()
// peer1 sets a recovery key
- self.createAndSetRecoveryKey(context: self.cuttlefishContext)
+ try self.createAndSetRecoveryKey(context: self.cuttlefishContext)
// Restart TPH
self.tphClient.containerMap.removeAllContainers()
self.startCKAccountStatusMock()
self.manager.setSOSEnabledForPlatformFlag(true)
- let _ = self.assertResetAndBecomeTrustedInDefaultContext()
+ _ = self.assertResetAndBecomeTrustedInDefaultContext()
// peer1 sets a recovery key
- self.createAndSetRecoveryKey(context: self.cuttlefishContext)
+ try self.createAndSetRecoveryKey(context: self.cuttlefishContext)
// Before restarting TPH, emulate a world in which the RK variables were not set on the container
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
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.isEmpty, "Should have at least one waitfortrust condition")
func testOctagonResetAlsoResetsCKKSViewsMissingTLKs() {
self.putFakeKeyHierarchiesInCloudKit()
+ self.putFakeDeviceStatusesInCloudKit()
let zoneKeys = self.keys![self.limitedPeersAllowedZoneID!] as? ZoneKeys
XCTAssertNotNil(zoneKeys, "Should have some zone keys")
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
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.limitedPeersAllowedZoneID!] as? ZoneKeys
XCTAssertNotNil(laterZoneKeys, "Should have some zone keys")
}
func testOctagonResetWithRemoteDevicesWithKeysDoesNotResetCKKS() {
- // CKKS has no keys, and there's another device claiming to have them already, so CKKS won't immediately reset it
+ // 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()
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")
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")
+ XCTAssertNotEqual(lpZoneKeys?.tlk?.uuid, lpLaterZoneKeys?.tlk?.uuid, "CKKS zone should not have the same keys for LimitedPeersAllowed - a reset should have occurred")
}
func testOctagonResetWithTLKsDoesNotResetCKKS() {
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 {
_ = 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")
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()
}
throw error
}
self.wait(for: [resetExpectation], timeout: 10)
-
}
func testResetReasonHealthCheck() throws {
-
let containerName = OTCKContainerName
let contextName = OTDefaultContext
}
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")
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.wait(for: [joinWithBottleExpectation], timeout: 10)
self.assertEnters(context: joinerContext, state: OctagonStateReady, within: 10 * NSEC_PER_SEC)
- self.assertConsidersSelfTrusted(context:joinerContext)
+ self.assertConsidersSelfTrusted(context: joinerContext)
self.silentZoneDeletesAllowed = true
self.sendContainerChangeWaitForFetchForStates(context: joinerContext, states: [OctagonStateUntrusted])
self.sendContainerChangeWaitForFetchForStates(context: self.cuttlefishContext, states: [OctagonStateReady])
- self.assertConsidersSelfTrusted(context:self.cuttlefishContext)
+ self.assertConsidersSelfTrusted(context: self.cuttlefishContext)
let statusExpectation = self.expectation(description: "status callback occurs")
let configuration = OTOperationConfiguration()
- joinerContext.rpcTrustStatus(configuration) { egoStatus, _, _, _, _ in
+ 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)
}
}
#if OCTAGON
class OctagonSOSTests: OctagonTestsBase {
-
func testSOSOctagonKeyConsistency() throws {
self.putFakeKeyHierarchiesInCloudKit()
self.putSelfTLKSharesInCloudKit()
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()
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()
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")
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()
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
self.verifyDatabaseMocks()
self.waitForCKModifications()
- assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC)
+ self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC)
}
func testSOSPerformOctagonKeyConsistencyOnCircleChange() throws {
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()
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())
// 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).
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'")
}
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() {
return
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)
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)
"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 {
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 preapproval
let peer2SOSMockPeer = self.createSOSPeer(peerID: "peer2ID")
updateTrustExpectation2.fulfill()
return nil
-
}
updateTrustExpectation1.fulfill()
// 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)
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'")
}
func testDoNotAttemptUpgradeOnRestart() throws {
}
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")
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")
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.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
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)
}
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)
}
// 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()
}
}
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: <rdar://problem/49080104> 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
#import <CloudKit/CloudKit_Private.h>
#import <AuthKit/AuthKit.h>
+#import <AuthKit/AKError.h>
#import <KeychainCircle/KeychainCircle.h>
#import "KeychainCircle/KCJoiningSession.h"
#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"
#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 <CoreCDP/CDPFollowUpController.h>
#include <dispatch/dispatch.h>
#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"
return self.mockOsVersion
}
- func serialNumber() -> String {
+ func serialNumber() -> String? {
return self.mockSerialNumber
}
}
let OTMockEscrowRequestNotification = Notification.Name("silent-escrow-request-triggered")
-class OTMockSecEscrowRequest: NSObject, SecEscrowRequestable {
+class OTMockSecEscrowRequest: NSObject, SecEscrowRequestable {
static var populateStatuses = false
var statuses: [String: String] = [:]
}
class OctagonTestsBase: CloudKitKeychainSyncingMockXCTest {
-
var tmpPath: String!
var tmpURL: URL!
var intendedCKKSZones: Set<CKRecordZone.ID>!
var manateeZoneID: CKRecordZone.ID!
var limitedPeersAllowedZoneID: CKRecordZone.ID!
+ var passwordsZoneID: CKRecordZone.ID!
var fakeCuttlefishServer: FakeCuttlefishServer!
var fakeCuttlefishCreator: FakeCuttlefishInvocableCreator!
self.manateeZoneID = CKRecordZone.ID(zoneName: "Manatee")
self.limitedPeersAllowedZoneID = CKRecordZone.ID(zoneName: "LimitedPeersAllowed")
+ self.passwordsZoneID = CKRecordZone.ID(zoneName: "Passwords")
// We'll use this set to limit the views that CKKS brings up in the tests (mostly for performance reasons)
if self.intendedCKKSZones == nil {
self.injectedManager!.setSyncingViewsAllowList(Set(self.intendedCKKSZones!.map { $0.zoneName }))
- // Ensure we've made the CKKSKeychainView objects we're interested in
- self.ckksZones.forEach { obj in
- let zoneID = obj as! CKRecordZone.ID
- self.ckksViews.add(self.injectedManager!.findOrCreateView(zoneID.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<CKRecordZone.ID>, self.intendedCKKSZones, "should still operate on our expected zones only")
- XCTAssertEqual(self.ckksZones.count, self.ckksViews.count, "Should have the same number of views as expected zones")
XCTAssertEqual(self.ckksZones.count, self.zones!.count, "Should have the same number of fake zones as expected zones")
- XCTAssertEqual(Set(self.ckksViews.map { ($0 as! CKKSKeychainView).zoneName }),
- Set(self.ckksZones.map { ($0 as! CKRecordZone.ID).zoneName }),
- "ckksViews should match ckksZones")
-
// Octagon must initialize the views
self.automaticallyBeginCKKSViewCloudKitOperation = false
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()
}
override func managedViewList() -> Set<String> {
- if(self.overrideUseCKKSViewsFromPolicy) {
+ if self.overrideUseCKKSViewsFromPolicy {
let viewNames = self.ckksZones.map { ($0 as! CKRecordZone.ID).zoneName }
return Set(viewNames)
} else {
}
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
self.tphClient.setAllowedMachineIDsWithContainer(container,
context: context,
allowedMachineIDs: self.mockAuthKit.currentDeviceList(), honorIDMSListChanges: honorIDMSListChanges) { _, error in
- XCTAssertNil(error, "Should be no error setting allow list")
- allowListExpectation.fulfill()
+ XCTAssertNil(error, "Should be no error setting allow list")
+ allowListExpectation.fulfill()
}
self.wait(for: [allowListExpectation], timeout: 10)
}
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)")
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()
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()
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")
statusexpectation.fulfill()
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")
statusexpectation.fulfill()
}
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 sendAllCKKSViewsZoneChanged() {
- for expectedView in self.ckksZones {
- let view = self.injectedManager?.findView((expectedView as! CKRecordZone.ID).zoneName)
- XCTAssertNotNil(view, "Should have a view '\(expectedView)'")
- view!.notifyZoneChange(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] as! CKKSCondition).wait(within), "CKKS state machine should enter '\(enters)' (currently '\(ckks.stateMachine.currentState)')")
}
- func assertAllCKKSViews(enter: String, within: UInt64) {
- for expectedView in self.ckksZones {
+ 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 assertAllCKKSViewsUpload(tlkShares: UInt) {
- for expectedView in self.ckksZones {
+ 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() {
- self.ckksZones.forEach { zone in
+ 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() {
- self.ckksZones.forEach { zone in
+ 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() {
- self.ckksZones.forEach { zone in
+ 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() {
- self.ckksZones.forEach { zone in
+ 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)
}
}
self.wait(for: [resetExpectation], timeout: 30)
}
- func putSelfTLKSharesInCloudKit(context: OTCuttlefishContext) throws {
- try self.ckksZones.forEach { zone in
+ 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 putRecoveryKeyTLKSharesInCloudKit(recoveryKey: String, salt: String) throws {
- try self.ckksZones.forEach { zone in
- try self.putRecoveryKeyTLKShareInCloudKit(recoveryKey: recoveryKey, salt: salt, zoneID: zone as! CKRecordZone.ID)
+ 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 putRecoveryKeyTLKShareInCloudKit(recoveryKey: String, salt: String, zoneID: CKRecordZone.ID) throws {
+ func putRecoveryKeyTLKSharesInCloudKit(recoveryKey: String, salt: String, sender: OTCuttlefishContext) throws {
let recoveryKeys = try RecoveryKey(recoveryKeyString: recoveryKey, recoverySalt: salt)
- let zoneKeys = self.keys![zoneID] as! ZoneKeys
- self.putTLKShare(inCloudKit: zoneKeys.tlk!, from: recoveryKeys.peerKeys, to: recoveryKeys.peerKeys, zoneID: zoneID)
+ 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) {
}
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 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) throws -> Bool {
+ func tlkShareInCloudKit(receiverPeerID: String, senderPeerID: String, zoneID: CKRecordZone.ID) -> Bool {
guard let zone = self.zones![zoneID] as? FakeCKZone else {
return false
}
return false
}
- func assertTLKShareInCloudKit(receiverPeerID: String, senderPeerID: String, zoneID: CKRecordZone.ID) throws {
- XCTAssertTrue(try self.tlkShareInCloudKit(receiverPeerID: receiverPeerID, senderPeerID: senderPeerID, zoneID: zoneID),
+ 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)")
}
// 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] as! CKKSCondition) }
let updateTrustExpectation = self.expectation(description: "fetchChanges")
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")
+ }
}
}
}
func assertSelfOSVersion(_ osVersion: String) {
-
let statusExpectation = self.expectation(description: "status callback occurs")
self.tphClient.dumpEgoPeer(withContainer: self.cuttlefishContext.containerName, context: self.cuttlefishContext.contextID) { _, _, stableInfo, _, error in
XCTAssertNil(error, "should be no error dumping ego peer")
class OctagonTests: OctagonTestsBase {
func testTPHPrepare() {
+ self.startCKAccountStatusMock()
+
let contextName = "asdf"
let containerName = "test_container"
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
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")
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")
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")
// 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 {
+ 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)
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.assertConsidersSelfTrusted(context: self.cuttlefishContext)
assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC)
self.verifyDatabaseMocks()
+ XCTAssertTrue(self.mockSOSAdapter.ckks4AllStatusIsSet, "SOS adapter should have been told that CKKS4All is not enabled")
+ XCTAssertTrue(self.mockSOSAdapter.ckks4AllStatus, "SOS adapter should have been told that CKKS4All is enabled")
+ self.mockSOSAdapter.ckks4AllStatusIsSet = false
// 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")
self.assertConsidersSelfUntrusted(context: self.cuttlefishContext)
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
}
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()
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")
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
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)),
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()
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
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 path = OctagonStateTransitionPath(from: [
OctagonStateResetAndEstablish: [
OctagonStateBottleJoinVouchWithBottle: [
- OctagonStateResetAndEstablish: OctagonStateTransitionPathStep.success(),
- ],
+ OctagonStateResetAndEstablish: OctagonStateTransitionPathStep.success(),
],
- ])
+ ],
+ ])
let watcher = OctagonStateTransitionWatcher(named: "should-fail",
serialQueue: self.cuttlefishContext.queue,
path: path!,
let cfuExpectation = self.expectation(description: "cfu callback occurs")
self.cuttlefishContext.followupHandler.clearAllPostedFlags()
- self.cuttlefishContext.checkTrustStatusAndPostRepairCFUIfNecessary { _, posted, _, error in
+ self.cuttlefishContext.checkTrustStatusAndPostRepairCFUIfNecessary { _, posted, _, _, error in
#if !os(tvOS)
XCTAssertTrue(posted, "posted should be true")
#else
self.startCKAccountStatusMock()
- self.aksLockState = true
- self.lockStateTracker.recheck()
-
let initiatorContext = self.manager.context(forContainerName: OTCKContainerName,
contextID: OTDefaultContext,
sosAdapter: self.mockSOSAdapter,
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.assertConsidersSelfTrusted(context: self.cuttlefishContext)
#if !os(tvOS)
- let expectedViews = Set(["ProtectedCloudStorage",
- "AutoUnlock",
- "LimitedPeersAllowed",
- "SecureObjectSync",
- "DevicePairing",
- "Engram",
- "Home",
- "Applications",
- "WiFi",
- "Health",
- "Manatee",
- // <rdar://problem/57810109> Cuttlefish: remove Safari prefix from view names
- "SafariCreditCards",
- "SafariPasswords",
- "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",
#endif
let getViewsExpectation = self.expectation(description: "getViews callback happens")
- self.tphClient.fetchCurrentPolicy(withContainer: OTCKContainerName, context: OTDefaultContext) { 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)
let octagonNotificationName = "com.apple.security.octagon.trust-status-change"
func testNotifications() throws {
-
let contextName = OTDefaultContext
let containerName = OTCKContainerName
}
func testAPSRateLimiter() throws {
-
let untrustedNotification = XCTDarwinNotificationExpectation(notificationName: octagonNotificationName)
self.startCKAccountStatusMock()
//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
+ self.manager.wait(forOctagonUpgrade: OTCKContainerName, context: OTDefaultContext) { error in
XCTAssertNotNil(error, "error should not be nil")
upgradeCallback.fulfill()
}
}
func testTTRTrusted() {
-
self.startCKAccountStatusMock()
self.cuttlefishContext.startOctagonStateMachine()
let limitedTLKs: Bool
}
- func assertTLKs(expectation: TestCase, receiverPeerID: String, senderPeerID: String) throws {
- let haveManateeTLK = try self.tlkShareInCloudKit(receiverPeerID: receiverPeerID,
- senderPeerID: senderPeerID,
- zoneID: self.manateeZoneID)
- let haveLimitedPeersAllowedTLK = try self.tlkShareInCloudKit(receiverPeerID: receiverPeerID,
- senderPeerID: senderPeerID,
- zoneID: self.limitedPeersAllowedZoneID)
+ 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)")
self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC)
- let ckksKeys: [CKKSKeychainBackedKeySet] = self.ckksViews.compactMap { view in
- let viewName = (view as! CKKSKeychainView).zoneName
- let currentKeySet = CKKSCurrentKeySet.load(forZone: CKRecordZone.ID(zoneName: viewName))
+ let ckksKeys: [CKKSKeychainBackedKeySet] = self.intendedCKKSZones.compactMap { zoneID in
+ let currentKeySet = CKKSCurrentKeySet.load(forZone: zoneID)
return try! currentKeySet.asKeychainBackedSet()
}
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")
XCTAssertNotNil(voucher, "Should have a voucher")
XCTAssertNotNil(voucherSig, "Should have a voucher signature")
- try! self.assertTLKs(expectation: testCase,
- receiverPeerID: peerID!,
- senderPeerID: senderPeerID)
+ self.assertTLKs(expectation: testCase,
+ receiverPeerID: peerID!,
+ senderPeerID: senderPeerID)
self.tphClient.join(withContainer: OTCKContainerName,
context: peer2ContextID,
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()
XCTAssertNil(voucherSig, "voucherSig should be nil")
XCTAssertNotNil(error, "error should be non nil")
- try! self.assertTLKs(expectation: testCase,
- receiverPeerID: peerID!,
- senderPeerID: senderPeerID)
+ self.assertTLKs(expectation: testCase,
+ receiverPeerID: peerID!,
+ senderPeerID: senderPeerID)
joinExpectation.fulfill()
}
}
-
}
self.wait(for: [joinExpectation], timeout: 10)
}
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")
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")
}
joinExpectation.fulfill()
}
-
}
self.wait(for: [joinExpectation], timeout: 10)
self.assertAllCKKSViews(enter: SecCKKSZoneKeyStateReady, within: 10 * NSEC_PER_SEC)
}
- try self.assertTLKs(expectation: testCase,
- receiverPeerID: peer2ID,
- senderPeerID: peer1ID)
+ self.assertTLKs(expectation: testCase,
+ receiverPeerID: peer2ID,
+ senderPeerID: peer1ID)
}
}
}
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()
let version0_txt_len = 395
extension OctagonPairingTests {
-
func testPiggybacking() {
self.startCKAccountStatusMock()
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()
do {
identityMessage = try requestCircleSession.initialMessage()
XCTAssertNotNil(identityMessage, "No identity message")
-
} catch {
XCTAssertNil(error, "error retrieving identityMessage message")
}
XCTAssertNotNil(voucherMessage, "No voucherMessage message")
} catch {
XCTAssertNil(error, "error retrieving voucherMessage message")
-
}
var nothing: Data?
XCTAssertNotNil(nothing, "No nothing message")
} catch {
XCTAssertNil(error, "error retrieving nothing message")
-
}
XCTAssertTrue(requestSession!.isDone(), "requestor should be done")
self.wait(for: [firstMessageWithNewJoiningConfigCallback], timeout: 10)
}
+ 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)
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!)
+ 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 {
+ 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 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")
}
var voucherMessage: Data?
do {
+ OctagonSetPlatformSupportsSOS(false)
voucherMessage = try acceptSession!.processMessage(identityMessage!)
let parsedMessage = try KCJoiningMessage(der: identityMessage!)
XCTAssertNotNil(parsedMessage.firstData, "No octagon 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 {
do {
identityMessage = try requestCircleSession.initialMessage()
XCTAssertNotNil(identityMessage, "No identity message")
-
} catch {
XCTAssertNil(error, "error retrieving identityMessage message")
}
XCTAssertNotNil(voucherMessage, "No voucherMessage message")
} catch {
XCTAssertNil(error, "error retrieving voucherMessage message")
-
}
var nothing: Data?
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
#if OCTAGON
extension OctagonPairingTests {
-
func test2ClientsBothOctagonAndSOS() {
-
OctagonSetPlatformSupportsSOS(true)
self.startCKAccountStatusMock()
}
func test2ClientsSOSOnly() {
-
OctagonSetPlatformSupportsSOS(true)
OctagonSetIsEnabled(false)
self.startCKAccountStatusMock()
#if OCTAGON
extension OctagonPairingTests {
-
func assertSOSSuccess() {
XCTAssertNotNil(self.fcInitiator?.accountPrivateKey, "no accountPrivateKey in fcInitiator")
XCTAssertNotNil(self.fcAcceptor?.accountPrivateKey, "no accountPrivateKey in fcAcceptor")
self.assertConsidersSelfTrusted(context: initiatorContext)
*/
}
-
}
#endif
#if OCTAGON
func GenerateFullECKey(keySize: Int) -> (SecKey) {
-
let keyPair = _SFECKeyPair.init(randomKeyPairWith: _SFECKeySpecifier.init(curve: SFEllipticCurve.nistp384))!
var keyAttributes: [String: String] = [:]
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
}
class KCJoiningAcceptTestDelegate: NSObject, KCJoiningAcceptSecretDelegate, KCJoiningAcceptCircleDelegate {
-
var secrets: [String] = []
var currentSecret: Int = 0
var retriesLeft: Int = 0
}
init(withSecrets secrets: [String], retries: Int, code: String) {
-
self.secrets = secrets
self.currentSecret = 0
self.retriesPerSecret = retries
}
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()
}
}
let acceptSession = try KCJoiningAcceptSession(secretDelegate: acceptDelegate as KCJoiningAcceptSecretDelegate,
circleDelegate: acceptDelegate as KCJoiningAcceptCircleDelegate,
dsid: dsid,
- rng: ccDRBGGetRngState())
+ rng: ccrng(nil))
requestSession.setControlObject(self.otControl)
acceptSession.setControlObject(self.otControl)
@objcMembers
class OctagonPairingTests: OctagonTestsBase {
-
var sosAdapterForAcceptor: CKKSMockSOSPresentAdapter!
var cuttlefishContextForAcceptor: OTCuttlefishContext!
var contextForAcceptor = "defaultContextForAcceptor"
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
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",
}
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")
}
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)
secondInitiatorData.dsid = "i-"+count
secondInitiatorData.altDSID = "alt-i-"+count
- let initiatorAnalytics = SFSignInAnalytics(signInUUID: "uuid", category: "com.apple.cdp", eventName: "signed in")
- XCTAssertNotNil(initiatorAnalytics, "initiatorAnalytics should not be nil")
- secondInitiatorData.analytics = initiatorAnalytics
let initiator = OTClique(contextData: secondInitiatorData)
XCTAssertNotNil(initiator, "Clique should not be nil")
initiator.setPairingDefault(true)
#import <Foundation/Foundation.h>
#import <Security/OTClique.h>
#import <TrustedPeers/TrustedPeers.h>
+#include <Security/SecureObjectSync/SOSCloudCircle.h>
+#include "keychain/ckks/CKKSPeer.h"
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
#import <Security/OTClique.h>
#import <OCMock/OCMock.h>
-#import <SoftLinking/SoftLinking.h>
#import "keychain/ot/OTCuttlefishContext.h"
#import <Security/SecItemPriv.h>
+#import <SecurityFoundation/SecurityFoundation.h>
#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,
}
}
++ (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<CKKSSelfPeer> 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
- (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)resetProtectedData:(NSString*)container context:(NSString*)contextID altDSID:(NSString*)altDSID appleID:(NSString*)appleID dsid:(NSString*)dsid;
+- (long)resetProtectedData:(NSString *)container context:(NSString *)contextID altDSID:(NSString *)altDSID appleID:(NSString *)appleID dsid:(NSString *)dsid;
-- (long)status:(NSString* _Nullable)container context:(NSString*)contextID json:(bool)json;
+- (long)status:(NSString * _Nullable)container context:(NSString *)contextID json:(bool)json;
-- (long)recoverUsingBottleID:(NSString*)bottleID
- entropy:(NSData*)entropy
- altDSID:(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)fetchAllBottles:(NSString*)altDSID
- containerName:(NSString*)containerName
- context:(NSString*)context
- control:(OTControl*)control;
+- (long)fetchAllBottles:(NSString *)altDSID
+ containerName:(NSString *)containerName
+ context:(NSString *)context
+ control:(OTControl *)control;
-- (long)healthCheck:(NSString* _Nullable)container context:(NSString*)contextID skipRateLimitingCheck:(BOOL)skipRateLimitingCheck;
-- (long)refetchCKKSPolicy:(NSString*)container context:(NSString*)contextID;
+- (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;
+
@end
NS_ASSUME_NONNULL_END
#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 <AuthKit/AKAppleIDAuthenticationController.h>
#import <AuthKit/AKAppleIDAuthenticationContext.h>
#import <AuthKit/AKAppleIDAuthenticationContext_Private.h>
-static NSString* fetch_pet(NSString* appleID, NSString* dsid)
+static NSString * fetch_pet(NSString * appleID, NSString * dsid)
{
if(!appleID && !dsid) {
NSLog(@"Must provide either an AppleID or a DSID to fetch a PET");
authContext.authenticationType = AKAppleIDAuthenticationTypeSilent;
authContext.isUsernameEditable = NO;
- __block NSString* pet = nil;
+ __block NSString * pet = nil;
dispatch_semaphore_t s = dispatch_semaphore_create(0);
return self;
}
-- (long)startOctagonStateMachine:(NSString*)container context:(NSString*)contextID {
+- (long)startOctagonStateMachine:(NSString *)container context:(NSString *)contextID {
#if OCTAGON
__block long ret = -1;
#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;
#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
#endif
}
-- (long)depart:(NSString* _Nullable)container context:(NSString*)contextID {
+- (long)depart:(NSString * _Nullable)container context:(NSString *)contextID {
#if OCTAGON
__block long ret = -1;
#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;
}
-- (long)resetProtectedData:(NSString*)container context:(NSString*)contextID altDSID:(NSString*)altDSID appleID:(NSString*)appleID dsid:(NSString*)dsid
+- (long)resetProtectedData:(NSString *)container context:(NSString *)contextID altDSID:(NSString *)altDSID appleID:(NSString *)appleID dsid:(NSString *)dsid
{
#if OCTAGON
__block long ret = -1;
data.authenticationAppleID = appleID;
data.altDSID = altDSID;
data.context = contextID;
+ data.containerName = container;
OTClique* clique = [OTClique resetProtectedData:data error:&error];
if(clique != nil && error == nil) {
#endif
}
-- (void)printPeer:(NSDictionary*)peerInformation prefix:(NSString* _Nullable)prefix {
- NSString* peerID = peerInformation[@"peerID"];
- NSString* model = peerInformation[@"permanentInfo"][@"model_id"];
+- (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] : ""),
[epoch intValue]);
}
-- (void)printPeers:(NSArray<NSString*>*)peerIDs
- egoPeerID:(NSString* _Nullable)egoPeerID
- informationOnPeers:(NSDictionary<NSString*, NSDictionary*>*)informationOnPeers {
- for(NSString* peerID in peerIDs) {
+- (void)printPeers:(NSArray<NSString *>*)peerIDs
+ egoPeerID:(NSString * _Nullable)egoPeerID
+ informationOnPeers:(NSDictionary<NSString *, NSDictionary*>*)informationOnPeers {
+ for(NSString * peerID in peerIDs) {
NSDictionary* peerInformation = informationOnPeers[peerID];
if(!peerInformation) {
}
}
-- (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<OTEscrowRecord*>* 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<OTEscrowRecord*>* 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<OTEscrowRecord*>* 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<OTEscrowRecord*>* 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;
NSDictionary* contextDump = result[@"contextDump"];
// Make it easy to find peer information
- NSMutableDictionary<NSString*, NSDictionary*>* peers = [NSMutableDictionary dictionary];
- NSMutableArray<NSString*>* allPeerIDs = [NSMutableArray array];
+ NSMutableDictionary<NSString *, NSDictionary*>* peers = [NSMutableDictionary dictionary];
+ NSMutableArray<NSString *>* 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];
}
NSDictionary* egoInformation = contextDump[@"self"];
- NSString* egoPeerID = egoInformation[@"peerID"];
+ NSString * egoPeerID = egoInformation[@"peerID"];
NSDictionary* egoDynamicInfo = egoInformation[@"dynamicInfo"];
if(egoPeerID) {
// The self peer is technically a peer, so, shove it on in there
peers[egoPeerID] = egoInformation;
- NSArray<NSString*>* includedPeers = egoDynamicInfo[@"included"];
+ NSArray<NSString *>* includedPeers = egoDynamicInfo[@"included"];
printf("Trusted peers (by me):\n");
if(includedPeers && includedPeers.count > 0) {
[self printPeers:includedPeers egoPeerID:egoPeerID informationOnPeers:peers];
}
printf("\n");
- NSArray<NSString*>* excludedPeers = egoDynamicInfo[@"excluded"];
+ NSArray<NSString *>* excludedPeers = egoDynamicInfo[@"excluded"];
printf("Excluded peers (by me):\n");
if(excludedPeers && excludedPeers.count > 0) {
[self printPeers:excludedPeers egoPeerID:egoPeerID informationOnPeers:peers];
#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;
#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<NSString*>* localViableBottleIDs = nil;
- __block NSArray<NSString*>* localPartiallyViableBottleIDs = nil;
+ __block NSArray<NSString *>* localViableBottleIDs = nil;
+ __block NSArray<NSString *>* localPartiallyViableBottleIDs = nil;
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[control fetchAllViableBottles:containerName
context:context
- reply:^(NSArray<NSString*>* _Nullable sortedBottleIDs,
- NSArray<NSString*>* _Nullable sortedPartialBottleIDs,
+ reply:^(NSArray<NSString *>* _Nullable sortedBottleIDs,
+ NSArray<NSString *>* _Nullable sortedPartialBottleIDs,
NSError* _Nullable controlError) {
if(controlError) {
secnotice("clique", "findOptimalBottleIDsWithContextData errored: %@\n", controlError);
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]);
}];
#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;
#endif
}
-- (long)refetchCKKSPolicy:(NSString*)container context:(NSString*)contextID
+- (long)refetchCKKSPolicy:(NSString *)container context:(NSString *)contextID
{
#if OCTAGON
__block long ret = 1;
#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
+}
+
+
@end
#import <Security/SecInternalReleasePriv.h>
#import <Security/Security.h>
#import <err.h>
+#import <OctagonTrust/OctagonTrust.h>
#import "keychain/otctl/OTControlCLI.h"
#import "keychain/otctl/EscrowRequestCLI.h"
static int signOut = false;
static int resetoctagon = false;
static int resetProtectedData = false;
+static int userControllableViewsSyncStatus = false;
static int fetchAllBottles = false;
static int recover = 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 health = false;
#if TARGET_OS_WATCH
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;
{.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"},
{.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"},
{.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"},
+
+
#if TARGET_OS_WATCH
{.command = "pairme", .flag = &pairme, .flagval = true, .description = "Perform pairing (watchOS only)"},
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];
}
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"]) {
#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,
#import <TargetConditionals.h>
#import <Foundation/Foundation.h>
#import <IDS/IDS.h>
-#import <Security/SecXPCHelper.h>
#import "keychain/categories/NSError+UsefulConstructors.h"
- (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;
}
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;
#import <IDS/IDS.h>
#import <KeychainCircle/KeychainCircle.h>
#import <os/assumes.h>
-#import <Security/SecXPCHelper.h>
#import <xpc/private.h>
#if TARGET_OS_WATCH
- (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];
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];
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;
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.
{
KCPairingChannelContext *channelContext = nil;
- self = [super init];
- if (self != nil) {
+ if ((self = [super init])) {
self.identifier = identifier;
channelContext = [KCPairingChannelContext new];
</array>
<key>com.apple.private.octagon</key>
<true/>
- <key>com.apple.security.exception.files.absolute-path.read-only</key>
- <array>
- <string>/usr/libexec</string>
- </array>
- <key>com.apple.security.exception.iokit-user-client-class</key>
- <array>
- <string>AppleKeyStoreUserClient</string>
- </array>
- <key>com.apple.security.exception.mach-lookup.global-name</key>
- <array>
- <string>com.apple.security.octagon</string>
- <string>com.apple.securityd.sos</string>
- </array>
- <key>com.apple.security.ts.identity-services-client</key>
- <true/>
<key>keychain-cloud-circle</key>
<true/>
<key>platform-application</key>
<true/>
<key>seatbelt-profiles</key>
<array>
- <string>temporary-sandbox</string>
+ <string>otpaird</string>
</array>
</dict>
</plist>
</array>
<key>com.apple.private.octagon</key>
<true/>
- <key>com.apple.security.exception.files.absolute-path.read-only</key>
- <array>
- <string>/usr/libexec</string>
- </array>
- <key>com.apple.security.exception.iokit-user-client-class</key>
- <array>
- <string>AppleKeyStoreUserClient</string>
- </array>
- <key>com.apple.security.exception.mach-lookup.global-name</key>
- <array>
- <string>com.apple.security.octagon</string>
- </array>
- <key>com.apple.security.ts.identity-services-client</key>
- <true/>
<key>platform-application</key>
<true/>
<key>seatbelt-profiles</key>
<array>
- <string>temporary-sandbox</string>
+ <string>otpaird</string>
</array>
</dict>
</plist>
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;
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);
}
{
__block bool result = false;
[acct performTransaction:^(SOSAccountTransaction * _Nonnull txn) {
- result = SOSAccountJoinCirclesAfterRestore(txn, nil, error);
+ result = SOSAccountJoinCirclesAfterRestore(txn, error);
}];
return result;
}
{
__block bool result = false;
[acct performTransaction:^(SOSAccountTransaction * _Nonnull txn) {
- result = SOSAccountJoinCircles(txn, nil, error);
+ result = SOSAccountJoinCircles(txn, error);
}];
return result;
}
-(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;
-(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;
-(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);
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);
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);
{
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);
#include "SOSAccountTesting.h"
#include "SecdTestKeychainUtilities.h"
+#if SOS_ENABLED
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include "SOSAccountTesting.h"
#include "keychain/SecureObjectSync/SOSAccount.h"
+#if SOS_ENABLED
#define kAccountPasswordString ((uint8_t*) "FooFooFoo")
#define kAccountPasswordStringLen 10
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include "SOSTestDataSource.h"
#include "SOSRegressionUtilities.h"
+#include "SOSAccountTesting.h"
+
+#if SOS_ENABLED
static int kTestTestCount = 10;
static int MAX_PENALTY_TIME = 32;
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;
}
#include "SOSTestDevice.h"
#include "SOSTestDataSource.h"
#include "keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h"
+#if SOS_ENABLED
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include "SOSAccountTesting.h"
#include "SecdTestKeychainUtilities.h"
+#if SOS_ENABLED
#define HOW_MANY_MINIONS 4
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include "SOSAccountTesting.h"
#include "SecdTestKeychainUtilities.h"
+#if SOS_ENABLED
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#import <utilities/SecCFWrappers.h>
#import "SecdTestKeychainUtilities.h"
+#include "SOSAccountTesting.h"
+
+#if SOS_ENABLED
const int kTestRecoveryKeyCount = 3;
}
}
+#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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#import "CKDSimulatedStore.h"
#import "CKDSimulatedAccount.h"
#import "CKDAKSLockMonitor.h"
-
#include "SOSCloudKeychainConstants.h"
+#include "SOSAccountTesting.h"
+
+
+#if SOS_ENABLED
@interface CKDSimulatedLockMonitor : NSObject<CKDLockMonitor>
}
- (instancetype) init {
- self = [super init];
- if (self) {
+ if ((self = [super init])) {
_locked = true;
_unlockedSinceBoot = false;
}
}
+#endif
int secd_210_keyinterest(int argc, char *const *argv)
{
+#if SOS_ENABLED
plan_tests(12);
-
tests();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include <utilities/SecCFWrappers.h>
#include <utilities/SecCFError.h>
#include <utilities/SecCFRelease.h>
+#include <utilities/der_plist.h>
#include <Security/SecBase64.h>
+#include <os/feature_private.h>
+
#include <libaks_acl_cf_keys.h>
#include <ctkclient/ctkclient_test.h>
(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;
(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;
(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;
(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);
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) ;
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 {
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);
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);
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);
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);
}
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";
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,
(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 };
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);
}
}
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);
}
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;
#include "secd_regressions.h"
+#import <Foundation/Foundation.h>
#include <Security/Security.h>
#include <utilities/SecCFWrappers.h>
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);
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;
#include "SecdTestKeychainUtilities.h"
#include "SOSAccountTesting.h"
+#if SOS_ENABLED
+
static int kTestTestCount = 9 + kSecdTestSetupTestCount;
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);
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include <utilities/der_plist.h>
#include "keychain/SecureObjectSync/SOSDigestVector.h"
#include "keychain/securityd/SecDbItem.h"
+#include "SOSAccountTesting.h"
+
+#if SOS_ENABLED
static void testNullMessage(uint64_t msgid)
{
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;
}
#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
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();
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include "SecdTestKeychainUtilities.h"
#include "SOSAccountTesting.h"
+#if SOS_ENABLED
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include "SecdTestKeychainUtilities.h"
+#if SOS_ENABLED
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);
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);
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include "SecdTestKeychainUtilities.h"
+#if SOS_ENABLED
+
static int kTestTestCount = 257;
static void tests(void)
carol_account.peerInfo,
NULL);
- ok(SOSAccountRemovePeersFromCircle(bob_account, peers_to_remove_array, nil, NULL));
+ ok(SOSAccountRemovePeersFromCircle(bob_account, peers_to_remove_array, NULL));
is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carol_account, NULL), 4, "Remove peers");
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include "SecdTestKeychainUtilities.h"
+#if SOS_ENABLED
+
static int kTestTestCount = 10;
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include "SecdTestKeychainUtilities.h"
+#if SOS_ENABLED
+
#define kAccountPasswordString ((uint8_t*) "FooFooFoo")
#define kAccountPasswordStringLen 10
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include "SOSAccountTesting.h"
#include "SecdTestKeychainUtilities.h"
+#include "SOSAccountTesting.h"
+#if SOS_ENABLED
static bool acceptApplicants(SOSAccount* account, CFIndex count) {
bool retval = false;
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include "SecdTestKeychainUtilities.h"
+#if SOS_ENABLED
+
/*
static void trim_retirements_from_circle(SOSAccount* account) {
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include "SOSAccountTesting.h"
#include "SecdTestKeychainUtilities.h"
+#if SOS_ENABLED
static bool AssertCreds(SOSAccount* account,CFStringRef acct_name, CFDataRef password) {
CFErrorRef error = NULL;
return retval;
}
-static inline bool SOSAccountEvaluateKeysAndCircle_wTxn(SOSAccount* acct, CFErrorRef* error)
-{
- __block bool result = false;
- [acct performTransaction:^(SOSAccountTransaction * _Nonnull txn) {
- result = SOSAccountEvaluateKeysAndCircle(txn, NULL);
- }];
- return result;
-}
-
static bool ResetToOffering(SOSAccount* account) {
CFErrorRef error = NULL;
bool retval;
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include "SecdTestKeychainUtilities.h"
+#if SOS_ENABLED
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include "SOSAccountTesting.h"
#include "SecdTestKeychainUtilities.h"
+#if SOS_ENABLED
static bool purgeICloudIdentity(SOSAccount* account) {
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include "SecdTestKeychainUtilities.h"
+#if SOS_ENABLED
+
/*
static void trim_retirements_from_circle(SOSAccount* account) {
SOSAccountForEachCircle(account, ^(SOSCircleRef circle) {
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include "keychain/securityd/SOSCloudCircleServer.h"
-#if !TARGET_OS_SIMULATOR
+
#include "SOSAccountTesting.h"
-#endif
#include "SecdTestKeychainUtilities.h"
-
-#if !TARGET_OS_SIMULATOR
+#if SOS_ENABLED
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");
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");
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include "SOSAccountTesting.h"
#include "SecdTestKeychainUtilities.h"
+#if SOS_ENABLED
typedef void (^stir_block)(int expected_iterations);
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include "SOSAccountTesting.h"
#include "SecdTestKeychainUtilities.h"
+#if SOS_ENABLED
static int64_t getCurrentGenCount(SOSAccount* account) {
SOSAccountTrustClassic* trust = account.trust;
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include "SecdTestKeychainUtilities.h"
+#if SOS_ENABLED
typedef void (^stir_block)(int expected_iterations);
typedef int (^execute_block)(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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#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"
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);
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
-
-#endif
+++ /dev/null
-/*
- * 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 <CoreFoundation/CFDictionary.h>
-#include <utilities/SecCFWrappers.h>
-
-#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;
-}
#include "SOSAccountTesting.h"
+#if SOS_ENABLED
+
static void tests() {
CFErrorRef error = NULL;
int keySizeInBits = 256;
}
+#endif
int secd_67_prefixedKeyIDs(int argc, char *const *argv) {
+#if SOS_ENABLED
plan_tests(12);
-
tests();
+#else
+ plan_tests(0);
+#endif
return 0;
}
--- /dev/null
+//
+// secd-68-fullPeerInfoIntegrity.m
+// secdRegressions
+//
+// Created by Richard Murphy on 4/30/20.
+//
+
+#import <Foundation/Foundation.h>
+
+#include <Security/SecBase.h>
+#include <Security/SecItem.h>
+
+#include <CoreFoundation/CFDictionary.h>
+
+#include "keychain/SecureObjectSync/SOSAccount.h"
+#include <Security/SecureObjectSync/SOSCloudCircle.h>
+#include "keychain/SecureObjectSync/SOSInternal.h"
+#include "keychain/SecureObjectSync/SOSUserKeygen.h"
+#include "keychain/SecureObjectSync/SOSTransport.h"
+#include "keychain/SecureObjectSync/SOSAccountTrustClassic+Circle.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "secd_regressions.h"
+#include "SOSTestDataSource.h"
+
+#include "SOSRegressionUtilities.h"
+#include <utilities/SecCFWrappers.h>
+#include <Security/SecKeyPriv.h>
+
+#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();
+#else
+ plan_tests(0);
+#endif
+ return 0;
+}
#include <utilities/SecCFWrappers.h>
#include <utilities/SecIOFormat.h>
#include <utilities/SecFileLocations.h>
+#include "SOSAccountTesting.h"
#include <AssertMacros.h>
#include <stdint.h>
+#if SOS_ENABLED
static int kTestTestCount = 121;
}, 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();
-
__security_simulatecrash_enable(true);
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include "keychain/SecureObjectSync/Regressions/SOSTestDevice.h"
#include "secd_regressions.h"
#include "SecdTestKeychainUtilities.h"
+#include "SOSAccountTesting.h"
+
+#if SOS_ENABLED
static int kTestTestCount = 581;
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include <AssertMacros.h>
#include <stdint.h>
+#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;
}
}
CFReleaseSafe(messageDigestStr);
- //SOSCircleHandleCircleWithLock(source->ds->engine, SOSEngineGetMyID(source->ds->engine), CFDataCreate(kCFAllocatorDefault, 0, 0), NULL);
-
}
return false;
}, CFSTR("alice"), CFSTR("bob"), NULL);
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include "SOSAccountTesting.h"
#include "SecdTestKeychainUtilities.h"
+#if SOS_ENABLED
static void RegressionsLogError(CFErrorRef error) {
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include <utilities/SecCFWrappers.h>
#include <utilities/SecIOFormat.h>
#include <utilities/SecFileLocations.h>
+#include "SOSAccountTesting.h"
#include <AssertMacros.h>
#include <stdint.h>
+#if SOS_ENABLED
static int kTestTestCount = 8;
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;
}
#include "keychain/SecureObjectSync/Regressions/SOSTestDevice.h"
#include "secd_regressions.h"
#include "SecdTestKeychainUtilities.h"
+#include "SOSAccountTesting.h"
+
+#if SOS_ENABLED
static int kTestTestCount = 646;
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#include "SecdTestKeychainUtilities.h"
#include <utilities/SecCFWrappers.h>
#include "keychain/SecureObjectSync/SOSPeer.h"
+#include "SOSAccountTesting.h"
+
+#if SOS_ENABLED
static int kTestTestCount = 53;
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
#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;
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();
+#else
+ plan_tests(0);
+#endif
return 0;
}
#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) {
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;
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);
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
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;
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);
#include <unistd.h>
#include "secd_regressions.h"
-#include "SOSTestDataSource.h"
+#include "keychain/SecureObjectSync/Regressions/SOSTestDataSource.h"
#include "SOSRegressionUtilities.h"
#include <utilities/SecCFWrappers.h>
#include "SOSAccountTesting.h"
#include "SecdTestKeychainUtilities.h"
+#if SOS_ENABLED
static bool SOSAccountResetCircleToNastyOffering(SOSAccount* account, SecKeyRef userPriv, SOSPeerInfoRef pi, CFErrorRef *error) {
bool result = false;
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;
}
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();
-
+#else
+ plan_tests(0);
+#endif
return 0;
}
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)
DISABLED_ONE_TEST(secd_70_otr_remote)
#import <Security/SecItem.h>
#import <Security/SecItemPriv.h>
#import <Foundation/NSXPCConnection_Private.h>
+#import <Security/SecXPCHelper.h>
NSString* kSecEntitlementKeychainControl = @"com.apple.private.keychain.keychaincontrol";
return NO;
}
+ NSSet<Class>* 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];
#import "SecTask.h"
#import "keychain/categories/NSError+UsefulConstructors.h"
#import "SecEntitlements.h"
+#import <Security/SecXPCHelper.h>
#import <SecurityFoundation/SFKeychain.h>
#import <SecurityFoundation/SFCredential_Private.h>
#import <SecurityFoundation/SFCredentialStore_Private.h>
// wait a bit for shared function from SecurityFoundation to get to SDK, then addopt that
NSXPCInterface* interface = [NSXPCInterface interfaceWithProtocol:@protocol(SFKeychainServerProtocol)];
+
+ NSSet<Class> *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;
//
// 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 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);
enum DepartureReason SOSCCGetLastDepartureReason_Server(CFErrorRef* error);
bool SOSCCRegisterSingleRecoverySecret_Server(CFDataRef backupSlice, bool setupV0Only, CFErrorRef *error);
bool SOSCCWaitForInitialSync_Server(CFErrorRef*);
-bool SOSCCWaitForInitialSyncWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error);
//
// MARK: Internal kicks.
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
#import "keychain/SigninMetrics/OctagonSignPosts.h"
#import "NSError+UsefulConstructors.h"
-#include <utilities/SecADWrapper.h>
+#import "utilities/SecCoreAnalytics.h"
#include <utilities/SecCFWrappers.h>
#include <utilities/SecCFRelease.h>
#include <corecrypto/ccec.h>
#include <corecrypto/ccdigest.h>
#include <corecrypto/ccsha2.h>
-#include <CommonCrypto/CommonRandomSPI.h>
#include <Security/SecKeyPriv.h>
#include <Security/SecFramework.h>
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;
if (account){
[account.trust updateGestalt:account newGestalt:our_gestalt];
} else {
- secerror("Got error inflating account: %@", inflationError);
+ secnotice("account", "Got error inflating account: %@", inflationError);
}
}
account = SOSAccountCreate(kCFAllocatorDefault, our_gestalt, factory);
if (!account)
- secerror("Got NULL creating account");
+ secnotice("account", "Got NULL creating account");
}
- //[account startStateMachine];
+ [account startStateMachine];
done:
CFReleaseNull(savedAccount);
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
// 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");
}
}
};
// 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);
// Get ramp settings from the Cloud
if(ghostbustnow) {
gbOptions = [SOSAccount ghostBustGetRampSettings];
+ gbOptions += SOSGhostBustiCloudIdentities;
}
}
#endif
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];
+ 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){
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;
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);
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);
}
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);
+
+ // 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;
+ });
- 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 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;
- });
- 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);
+ // 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(Flush(error), done);
-
-done:
- OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCTryUserCredentials, OctagonSignpostNumber1(SOSSignpostNameSOSCCTryUserCredentials), (int)result);
-
return result;
}
-static bool SOSCCAssertUserCredentialsAndOptionalDSID(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, NSData* parentEvent, CFErrorRef *error) {
+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);
-
- NSError* localError = nil;
- SFSignInAnalytics* parent = nil;
-
- if(parentEvent) {
- 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);
+
+ 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);
- if(parent) {
- syncAndWaitEvent = [parent newSubTaskForEvent:@"syncAndWaitEvent"];
- }
- require_quiet(SyncKVSAndWait(error), done); // Make sure we've seen what the server has
- if(syncAndWaitEvent) {
- [syncAndWaitEvent stopWithAttributes:nil];
- }
+ 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;
+ });
- if(parent) {
- flushEvent = [parent newSubTaskForEvent:@"flushEvent"];
- }
- require_quiet(Flush(error), done); // And processed it already...before asserting
- if(flushEvent) {
- [flushEvent stopWithAttributes:nil];
- }
+ 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);
+ });
+ }
- result = do_with_account_while_unlocked(error, ^bool(SOSAccountTransaction* txn, CFErrorRef *block_error) {
- return SOSAccountAssertUserCredentials(txn.account, user_label, user_password, block_error);
- });
+ // if either key constructions passed do a flush to bring through anything we weren't "interested" in before.
+ if(result) {
+ Flush(error);
+ }
- require_quiet(result, done);
- if(parent) {
- secondFlushEvent = [parent newSubTaskForEvent:@"secondFlushEvent"];
- }
- require_quiet(Flush(error), done); // Process any incoming information..circles et.al. before fixing our signature
- if(secondFlushEvent) {
- [secondFlushEvent stopWithAttributes:nil];
- }
+ 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);
- if(parent) {
- generationSignatureUpdateEvent = [parent newSubTaskForEvent:@"generationSignatureUpdateEvent"];
- }
- result = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) {
- return SOSAccountGenerationSignatureUpdate(txn.account, error);
+ OctagonSignpostEnd(signPost, SOSSignpostNameAssertUserCredentialsAndOptionalDSID, OctagonSignpostNumber1(SOSSignpostNameAssertUserCredentialsAndOptionalDSID), (int)result);
});
- if(generationSignatureUpdateEvent) {
- [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;
}
bool SOSCCSetUserCredentialsAndDSID_Server(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFErrorRef *error)
{
// TODO: Return error if DSID is NULL to insist our callers provide one?
- return SOSCCAssertUserCredentialsAndOptionalDSID(user_label, user_password, dsid, nil, error);
-}
-
-bool SOSCCSetUserCredentialsAndDSIDWithAnalytics_Server(CFStringRef user_label, CFDataRef user_password, CFStringRef dsid, CFDataRef parentEvent, CFErrorRef *error)
-{
- return SOSCCAssertUserCredentialsAndOptionalDSID(user_label, user_password, dsid, (__bridge NSData*)parentEvent, error);
+ return SOSCCAssertUserCredentialsAndOptionalDSID(user_label, user_password, dsid, error);
}
bool SOSCCSetUserCredentials_Server(CFStringRef user_label, CFDataRef user_password, CFErrorRef *error)
{
- return SOSCCAssertUserCredentialsAndOptionalDSID(user_label, user_password, NULL, nil, error);
+ return SOSCCAssertUserCredentialsAndOptionalDSID(user_label, user_password, NULL, error);
}
bool SOSCCCanAuthenticate_Server(CFErrorRef *error)
}) ? status : kSOSCCError;
}
-bool SOSCCRequestToJoinCircleWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error)
+bool SOSCCRequestToJoinCircle_Server(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 = SOSAccountJoinCircles(txn, (__bridge NSData*)parentEvent, block_error);
+ result = SOSAccountJoinCircles(txn, block_error);
return result;
});
OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCRequestToJoinCircle, OctagonSignpostNumber1(SOSSignpostNameSOSCCRequestToJoinCircle), (int)requested);
return requested;
}
-bool SOSCCRequestToJoinCircle_Server(CFErrorRef* error)
-{
- return SOSCCRequestToJoinCircleWithAnalytics_Server(nil, error);
-}
-
bool SOSCCAccountHasPublicKey_Server(CFErrorRef *error)
{
__block bool result = true;
return hasPublicKey;
}
-bool SOSCCRequestToJoinCircleAfterRestoreWithAnalytics_Server(CFDataRef parentEvent, CFErrorRef* error)
+bool SOSCCRequestToJoinCircleAfterRestore_Server(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 = nil;
- SFSignInAnalytics *ensurePeerRegistrationEvent = nil;
-
- if(parentEvent) {
- parent = [NSKeyedUnarchiver unarchivedObjectOfClass:[SFSignInAnalytics class] fromData:(__bridge NSData*)parentEvent error:&localError];
- ensurePeerRegistrationEvent = [parent newSubTaskForEvent:@"ensurePeerRegistrationEvent"];
- }
-
SOSAccountEnsurePeerRegistration(txn.account, block_error);
if(block_error && *block_error){
NSError* blockError = (__bridge NSError*)*block_error;
- if(blockError){
- if(ensurePeerRegistrationEvent) {
- [ensurePeerRegistrationEvent logRecoverableError:blockError];
- }
+ if (blockError) {
secerror("ensure peer registration error: %@", blockError);
}
}
- if(ensurePeerRegistrationEvent) {
- [ensurePeerRegistrationEvent stopWithAttributes:nil];
- }
- result = SOSAccountJoinCirclesAfterRestore(txn, (__bridge NSData*)parentEvent, block_error);
+ result = SOSAccountJoinCirclesAfterRestore(txn, block_error);
return result;
});
OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCRequestToJoinCircleAfterRestore, OctagonSignpostNumber1(SOSSignpostNameSOSCCRequestToJoinCircleAfterRestore), (int)result);
return returned;
-
-}
-
-bool SOSCCRequestToJoinCircleAfterRestore_Server(CFErrorRef* error)
-{
- return SOSCCRequestToJoinCircleAfterRestoreWithAnalytics_Server(nil, error);
}
bool SOSCCAccountSetToNew_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);
OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCRemovePeersFromCircle);
bool removeResult = do_with_account_while_unlocked(error, ^bool (SOSAccountTransaction* txn, CFErrorRef* block_error) {
- bool result = SOSAccountRemovePeersFromCircle(txn.account, peers, nil, block_error);
+ bool result = SOSAccountRemovePeersFromCircle(txn.account, peers, block_error);
return result;
});
OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCRemovePeersFromCircle, OctagonSignpostNumber1(SOSSignpostNameSOSCCRemovePeersFromCircle), (int)removeResult);
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 = SOSAccountRemovePeersFromCircle(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)
sync_the_last_data_to_kvs((__bridge CFTypeRef)(txn.account), waitForeverForSynchronization);
SOSAccountSetToNew(txn.account);
-
+ txn.account.accountIsChanging = true;
return result;
});
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;
}
});
}
-
- require_quiet(result, fail);
- if(result)
- {
- SecADClientPushValueForDistributionKey(SOSAggdSyncCompletionKey, getTimeDifference(start));
- }
- else if(!result)
- {
- SecADAddValueForScalarKey(SOSAggdSyncTimeoutKey, 1);
+ if(result) {
+ [SecCoreAnalytics sendEvent:(__bridge id)SOSAggdSyncCompletionKey
+ event:@{SecCoreAnalyticsValue: [NSNumber numberWithLong:getTimeDifference(start)]}];
+ } else {
+ [SecCoreAnalytics sendEvent:(__bridge id)SOSAggdSyncTimeoutKey
+ event:@{SecCoreAnalyticsValue: @1}];
}
-
secnotice("initial sync", "Finished!: %d", result);
fail:
return processResult;
}
+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;
+ });
+}
+
+#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);
+ }
+ CFReleaseNull(subset);
+ return retval;
+}
+
CF_RETURNS_RETAINED CFSetRef SOSCCProcessSyncWithPeers_Server(CFSetRef peers, CFSetRef backupPeers, CFErrorRef *error) {
- __block CFSetRef result = NULL;
- OctagonSignpost signPost = OctagonSignpostBegin(SOSSignpostNameSOSCCProcessSyncWithPeers);
+ 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 (!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);
+ if(!peers) {
+ peers = noPeers;
}
- OctagonSignpostEnd(signPost, SOSSignpostNameSOSCCProcessSyncWithPeers, OctagonSignpostNumber1(SOSSignpostNameSOSCCProcessSyncWithPeers), (int)(result != NULL));
- return result;
+ 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)
});
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);
});
});
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);
{
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);
});
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) {
*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];
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;
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;
*/
// 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)
+#define SECDB_BACKUPS_ENABLED ((TARGET_OS_OSX || TARGET_OS_IOS || TARGET_OS_MACCATALYST) && !TARGET_OS_SIMULATOR && !TARGET_DARWINOS)
#if __OBJC2__
#import <Foundation/Foundation.h>
-#if !TARGET_OS_BRIDGE // Specifically needed until rdar://problem/40583882 lands
#import <SecurityFoundation/SFKey.h>
-#endif
#import "SecAKSObjCWrappers.h"
#import "CheckV12DevEnabled.h"
SecDbBackupTestCodeFailure = 255, // support code for testing is falling over somehow
};
-@interface SecDbBackupWrappedItemKey : NSObject <NSSecureCoding>
+@interface SecDbBackupWrappedKey : NSObject <NSSecureCoding>
@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<NSString*, NSString*>* results, NSError* _Nullable error))completion;
// Declare C functions here
bool SecDbBackupCreateOrLoadBackupInfrastructure(CFErrorRef _Nullable * _Nonnull error);
+void SecDbResetBackupManager(void); // For testing. Here so SecKeychainDbReset can use it.
*/
#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;
}
}
@end
-#if !SECDB_BACKUPS_ENABLED
-
-@implementation SecDbBackupManager
-
-+ (instancetype)manager
-{
- return nil;
-}
-
-- (void)verifyBackupIntegrity:(bool)lightweight
- completion:(void (^)(NSDictionary<NSString*, NSString*>* 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 <CommonCrypto/CommonRandom.h>
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;
+ (void)resetManager
{
if (staticManager) {
- staticManager = [SecDbBackupManager new];
+ secnotice("SecDbBackup", "Resetting backup manager");
+ staticManager = [[SecDbBackupManager alloc] init];
}
}
}
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"];
error:error];
}
+- (NSData*)currentBackupBagUUID
+{
+ return [_bagIdentity.baguuid copy];
+}
+
#pragma mark - Fixup And Verification
- (void)verifyBackupIntegrity:(bool)lightweight
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.
- (BOOL)onQueueReloadDefaultBackupBagWithError:(NSError**)error
{
+ dispatch_assert_queue(_queue);
if (_handle != bad_keybag_handle) {
aks_unload_bag(_handle);
}
- (InMemoryKCSK*)onQueueReadKCSKFromDiskForClass:(keyclass_t)keyclass error:(NSError**)error
{
+ dispatch_assert_queue(_queue);
__block bool ok = true;
__block CFErrorRef cfError = NULL;
__block NSData* readUUID;
- (SFECKeyPair*)onQueueFetchKCSKForKeyclass:(keyclass_t)keyclass error:(NSError**)error
{
+ dispatch_assert_queue(_queue);
assert(error);
assert(_bagIdentity);
assert(_handle != bad_keybag_handle);
#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"];
return nil;
}
- __block SecDbBackupWrappedItemKey* backupWrappedKey;
+ __block SecDbBackupWrappedKey* backupWrappedKey;
__block NSMutableData* wrappedKey = [NSMutableData dataWithLength:APPLE_KEYSTORE_MAX_ASYM_WRAPPED_KEY_LEN];
__block NSError* localError;
return;
}
}
- backupWrappedKey = [SecDbBackupWrappedItemKey new];
+ backupWrappedKey = [SecDbBackupWrappedKey new];
backupWrappedKey.wrappedKey = [NSKeyedArchiver archivedDataWithRootObject:wrappedAndSigned requiringSecureCoding:YES error:&localError];
backupWrappedKey.baguuid = self->_bagIdentity.baguuid;
});
- (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;
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
@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<NSString*, NSString*>* 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
// 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
}
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)) {
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;
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)
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) {
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;
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;
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;
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);
+ }
+ }
+ }
}
});
}
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) &&
}
// 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;
kSecDbSyncPrimaryKeyV0 = (1 << 14),
kSecDbSyncPrimaryKeyV2 = (1 << 15),
kSecDbSyncFlag = (1 << 16),
+ kSecDbSyncSOSCannotSyncFlag= (1 << 17),
};
#define SecVersionDbFlag(v) ((v & 0xFF) << 8)
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);
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);
// 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);
#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_ */
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;
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();
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;
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];
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)) {
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) {
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;
}
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);
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);
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;
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) {
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) {
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);
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;
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;
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) {
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);
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) {
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);
@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
- (instancetype)initWithCiphertext:(SFAuthenticatedCiphertext*)ciphertext
wrappedKey:(SecDbKeychainAKSWrappedKey*)wrappedKey
tamperCheck:(NSString*)tamperCheck
- backupWrappedKey:(SecDbBackupWrappedItemKey*)backupWrappedKey
+ backupWrappedKey:(SecDbBackupWrappedKey*)backupWrappedKey
error:(NSError**)error
{
if (self = [super init]) {
{
if (!_metadataAttributes) {
SFAESKey* metadataClassKey = [self metadataClassKeyWithKeybag:_keybag
- createKeyIfMissing:false
- overwriteCorruptKey:false
+ allowWrites:false
error:error];
if (metadataClassKey) {
NSError* localError = nil;
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];
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) {
}
- (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];
}
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
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];
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"));
}
}
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];
- (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
#import <notify.h>
#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;
initializeSharedMetadataStoreQueue();
dispatch_sync(sharedMetadataStoreQueue, ^{
if(sharedStore) {
- dispatch_sync(sharedStore->_queue, ^{
- [sharedStore _onQueueDropAllKeys];
- });
+ [sharedStore dropAllKeys];
}
sharedStore = nil;
});
_keysDict[@(key_class_akpu)] = nil;
}
+- (void)dropAllKeys
+{
+ dispatch_sync(_queue, ^{
+ [self _onQueueDropAllKeys];
+ });
+}
+
- (void)_onQueueDropAllKeys
{
dispatch_assert_queue(_queue);
[_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;
+ keyclass_t classToUse = keyclass;
+ if (*outKeyclass != key_class_none && *outKeyclass != keyclass) {
+ classToUse = *outKeyclass;
+ }
+
+ 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;
+ }
+ }
- secnotice("SecDbKeychainItemV7", "saving actualKeyclass %d for metadata keyclass %d", actualKeyclassToWriteBackToDB, keyclass);
+ return key;
+}
- kc_with_dbt_non_item_tables(true, &cfError, ^bool(SecDbConnectionRef dbt) {
- __block bool actualKeyWriteBackOk = true;
+- (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];
+}
- // 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
- });
- });
+- (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);
- if (actualKeyWriteBackOk) {
- secnotice("SecDbKeychainItemV7", "successfully saved actualKeyclass %d for metadata keyclass %d", actualKeyclassToWriteBackToDB, keyclass);
+ 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;
}
- 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 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);
}
- return actualKeyWriteBackOk;
+ 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;
}
-- (SFAESKey*)keyForKeyclass:(keyclass_t)keyclass
+- (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
- createKeyIfMissing:(bool)createIfMissing
- overwriteCorruptKey:(bool)overwriteCorruptKey
+ allowWrites:(BOOL)allowWrites
error:(NSError**)error
{
- __block SFAESKey* key = nil;
- __block NSError* nsErrorLocal = nil;
- __block CFErrorRef cfError = NULL;
- static __thread BOOL reentrant = NO;
+ 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, ^{
- // 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
- // <rdar://problem/37523001> 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
+ // try our cache first and rejoice if that succeeds
+ bool allowCaching = [SecDbKeychainMetadataKeyStore cachingEnabled];
- 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
+ key = allowCaching ? self->_keysDict[@(keyclass)] : nil;
+ if (key) {
+ return; // Cache contains validated key for class, excellent!
+ }
- 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);
- }
- }
- }
- }
+ // 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);
});
});
-
- 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"}];
- }
+ 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 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];
- });
+ 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
}
- else {
- key = nil;
- }
+ 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;
- if (error && nsErrorLocal) {
- *error = nsErrorLocal;
- CFReleaseNull(cfError);
- }
- else {
- BridgeCFErrorToNSErrorOut(error, cfError);
- }
-
return key;
}
@end
+
+NS_ASSUME_NONNULL_END
--- /dev/null
+syntax = "proto2";
+
+message SecDbKeychainSerializedMetadataKey {
+ optional int32 keyclass = 1;
+ optional int32 actualKeyclass = 2;
+ optional bytes baguuid = 3;
+ optional bytes akswrappedkey = 4;
+ optional bytes backupwrappedkey = 5;
+}
--- /dev/null
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from SecDbKeychainSerializedMetadataKey.proto
+
+#import <Foundation/Foundation.h>
+#import <ProtocolBuffer/PBCodable.h>
+
+#ifdef __cplusplus
+#define SECDBKEYCHAINSERIALIZEDMETADATAKEY_FUNCTION extern "C"
+#else
+#define SECDBKEYCHAINSERIALIZEDMETADATAKEY_FUNCTION extern
+#endif
+
+@interface SecDbKeychainSerializedMetadataKey : PBCodable <NSCopying>
+{
+ 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
+
--- /dev/null
+// This file was automatically generated by protocompiler
+// DO NOT EDIT!
+// Compiled from SecDbKeychainSerializedMetadataKey.proto
+
+#import "SecDbKeychainSerializedMetadataKey.h"
+#import <ProtocolBuffer/PBConstants.h>
+#import <ProtocolBuffer/PBHashUtil.h>
+#import <ProtocolBuffer/PBDataReader.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 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
+
}
}
-
-/* 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. */
Query *query_create(const SecDbClass *qclass,
CFDataRef musr,
CFDictionaryRef query,
+ SecurityClient* client,
CFErrorRef *error)
{
if (!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;
}
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)) {
#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
// 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;
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);
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;
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
}
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;
}
// 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;
// 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;
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);
}
// 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)));
}
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) {
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;
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;
}
#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) {
// 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;
- });
- });
- 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);
+ // 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);
+
+ // 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);
}
}
+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;
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) {
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,
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);
}
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))
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)
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);
// 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);
}
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)
if (stmt) {
ok = SecDbFinalize(stmt, error);
}
- if (!ok)
+ if (!ok) {
secwarning("DeleteAllFromTableForMUSRView failed for %@ for musr: %@: %@", sql2, musr, error ? *error : NULL);
+ }
CFReleaseNull(sql2);
}
#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;
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;
}
}
+ /* 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 ||
CFReleaseSafe(pref);
}
}
- } else {
+ } else if (!ok || !allAttributes) {
OSStatus status = SecErrorGetOSStatus(localError);
if (status == errSecInteractionNotAllowed && is_akpu) {
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);
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);
#endif
}
-
CFDictionaryRef
SecServerCopyKeychainPlist(SecDbConnectionRef dbt,
SecurityClient *client,
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) {
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. */
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
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);
}
}
};
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;
#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));
#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);
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);
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);
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);
&v10_1pcspublickey,
&v10_1pcspublicidentity,
&v10_1itempersistentref,
+ &v11_7appclip,
&v12_backupUUID,
0
},
&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
},
&v10_1pcspublickey,
&v10_1pcspublicidentity,
&v10_1itempersistentref,
+ &v11_7appclip,
&v12_backupUUID,
0
},
&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,
&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,
}
};
+/*
+ * 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)
*/
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,
};
const SecDbSchema *v10_kc_schemas[] = {
+ &v11_9_schema,
+ &v11_8_schema,
+ &v11_7_schema,
&v11_6_schema,
&v11_5_schema,
&v11_4_schema,
--- /dev/null
+/*
+ * 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 <TargetConditionals.h>
+
+#if TARGET_OS_IOS && !TARGET_OS_BRIDGE
+#include <CoreFoundation/CoreFoundation.h>
+
+// 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
--- /dev/null
+/*
+ * 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 <SharedWebCredentials/SharedWebCredentials.h>
+
+#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<NSString *> *)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
#include "keychain/securityd/SecItemDb.h"
#include "keychain/securityd/SecItemSchema.h"
#include <utilities/SecDb.h>
+#include <utilities/SecDbInternal.h>
+#import <utilities/SecCoreAnalytics.h>
#include "keychain/securityd/SecDbKeychainItem.h"
#include "keychain/securityd/SOSCloudCircleServer.h"
#include <Security/SecBasePriv.h>
#endif
#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
-#include <utilities/SecADWrapper.h>
#include <sys/time.h>
#include <unistd.h>
#endif
#include <Security/SecuritydXPC.h>
#include "swcagent_client.h"
#include "SecPLWrappers.h"
-
-#if TARGET_OS_IOS && !TARGET_OS_BRIDGE
-#include <SharedWebCredentials/SharedWebCredentials.h>
-#endif
+#include "SecItemServer+SWC.h"
+#include <ipc/server_entitlement_helpers.h>
#include <os/variant_private.h>
}
out:
secnotice("upgr", "database version is: 0x%08x : %d : %@", *version, ok, localError);
+ secnotice("upgr", "UID: %d EUID: %d", getuid(), geteuid());
CFReleaseSafe(localError);
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);
}
}
{
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 */
// 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.
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;
}
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;
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.
// 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;
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;
// 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);
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
}
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 {
//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);
dispatch_sync(get_kc_dbhandle_dispatch(), ^{
CFReleaseNull(_kc_dbhandle);
SecDbResetMetadataKeys();
-
+ SecDbResetBackupManager();
if (inbetween)
inbetween();
});
// 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)) {
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);
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(dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{
+ __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 ****************
****************************************************************************/
{
#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")
}
}
-/* 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;
}
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) {
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
#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"));
});
}
- if (!query_destroy(q, error))
+ if (!query_destroy(q, error)) {
ok = false;
+ }
}
CFReleaseNull(accessGroups);
}
}
-
-/* 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;
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);
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"));
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;
}
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;
}
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"));
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;
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
#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"));
}
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) {
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) {
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();
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);
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);
#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)
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; }
// 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) {
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) {
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
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);
ok = _SecItemDelete(query, &swcclient, error);
}
}
-
+
if(result) CFReleaseNull(*result);
if(error) CFReleaseNull(*error);
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);
};
// On input, the query dictionary contains optional fqdn and account entries.
- fqdn = CFDictionaryGetValue(query, kSecAttrServer);
account = CFDictionaryGetValue(query, kSecAttrAccount);
// Check autofill enabled status
}
// 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"));
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");
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) {
}
SecError(status, error, CFSTR("%@"), msg);
CFReleaseSafe(msg);
- CFReleaseSafe(fqdn);
goto cleanup;
}
#endif
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);
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)));
}
CFReleaseSafe(items);
CFReleaseSafe(attrs);
- CFReleaseSafe(fqdn);
}
// If matching credentials are found, the credentials provided to the completionHandler
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) {
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 */
errOut:
return ok;
}
+
+#else /* SECUREOBJECTSYNC */
+
+SOSDataSourceFactoryRef SecItemDataSourceFactoryGetDefault(void) {
+ return NULL;
+}
+
#endif /* SECUREOBJECTSYNC */
bool _SecServerRollKeysGlue(bool force, CFErrorRef *error) {
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;
continue;
}
- if (!SecDbItemInsert(dbi, dbt, &cferror)) {
+ if (!SecDbItemInsert(dbi, dbt, false, &cferror)) {
secinfo("ImportInitialSyncItems", "Item store failed with: %@: %@", cferror, dbi);
CFReleaseNull(cferror);
}
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;
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;
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);
continue;
}
- q = query_create(*kcClass, SecMUSRGetSingleUserKeychainUUID(), NULL, error);
+ q = query_create(*kcClass, SecMUSRGetSingleUserKeychainUUID(), NULL, client, error);
if (q == NULL)
continue;
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);
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);
void SecKeychainDbForceClose(void);
void SecKeychainDbReset(dispatch_block_t inbetween);
-
SOSDataSourceFactoryRef SecItemDataSourceFactoryGetDefault(void);
/* FIXME: there is a specific type for keybag handle (keybag_handle_t)
bool itemInAccessGroup(CFDictionaryRef item, CFArrayRef accessGroups);
void SecKeychainChanged(void);
+void deleteCorruptedItemAsync(SecDbConnectionRef dbt, CFStringRef tablename, sqlite_int64 rowid);
+
__END_DECLS
#endif /* _SECURITYD_SECITEMSERVER_H_ */
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()) {
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) {
privateKeyRef = SOSAccountCopyDeviceKey(privateAccount, error);
require_quiet(privateKeyRef, fail);
- privateIdentity = SecOTRFullIdentityCreateFromSecKeyRef(kCFAllocatorDefault, privateKeyRef, error);
+ privateIdentity = SecOTRFullIdentityCreateFromSecKeyRefSOS(kCFAllocatorDefault, privateKeyRef, error);
require_quiet(privateIdentity, fail);
CFReleaseNull(privateKeyRef);
(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(/|$)")
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
+ <key>com.apple.private.cloudkit.notifyOnAccountWarmup</key>
+ <true/>
<key>com.apple.private.dark-wake-push</key>
<true/>
<key>com.apple.private.accounts.allaccounts</key>
<true/>
<key>com.apple.private.cloudkit.supportservice</key>
<true/>
+ <key>com.apple.private.cloudkit.spi</key>
+ <true/>
<key>com.apple.private.appleaccount.app-hidden-from-icloud-settings</key>
<true/>
<key>com.apple.private.tcc.allow</key>
<true/>
<key>com.apple.symptom_diagnostics.report</key>
<true/>
+ <key>com.apple.private.security.storage.Keychains</key>
+ <true/>
</dict>
</plist>
.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,
.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,
.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_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,
.soscc_SetNewPublicBackupKey = SOSCCSetNewPublicBackupKey_Server,
.soscc_RegisterSingleRecoverySecret = SOSCCRegisterSingleRecoverySecret_Server,
.soscc_WaitForInitialSync = SOSCCWaitForInitialSync_Server,
- .soscc_WaitForInitialSyncWithAnalytics = SOSCCWaitForInitialSyncWithAnalytics_Server,
.soscc_AccountHasPublicKey = SOSCCAccountHasPublicKey_Server,
.soscc_SOSCCPeersHaveViewsEnabled = SOSCCPeersHaveViewsEnabled_Server,
.soscc_RegisterRecoveryPublicKey = SOSCCRegisterRecoveryPublicKey_Server,
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.
print("Error: --policy-secret data must be base-64")
exitUsage(1)
}
- if nil == policySecrets {
+ if policySecrets == nil {
policySecrets = [:]
}
policySecrets![name] = data
}
voucher = voucherData
voucherSig = voucherSigData
-
} else {
guard let voucherBase64 = argIterator.next() else {
print("Error: join needs a voucher")
permanentInfoSig = permanentInfoSigData
stableInfo = stableInfoData
stableInfoSig = stableInfoSigData
-
} else {
-
guard let peerIDString = argIterator.next() else {
print("Error: vouch needs a peerID")
print()
// 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!)
}
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!)
}
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!)
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
}
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
}
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))")
}
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 {
}
case .prepare:
- os_log("preparing (%@, %@)", log: tplogDebug, type: .default, container, context)
+ logger.log("preparing (\(container), \(context))")
if machineID == nil {
let anisetteController = AKAnisetteProvisioningController()
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,
bottleID: UUID().uuidString,
modelID: modelID ?? deviceInfo.modelID(),
deviceName: deviceName ?? deviceInfo.deviceName(),
- serialNumber: serialNumber ?? deviceInfo.serialNumber(),
+ serialNumber: serialNumber,
osVersion: osVersion ?? deviceInfo.osVersion(),
policyVersion: nil,
policySecrets: policySecrets,
+ syncUserControllableViews: .UNKNOWN,
signingPrivKeyPersistentRef: nil,
- encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, views, _, error in
+ encPrivKeyPersistentRef: nil) { peerID, permanentInfo, permanentInfoSig, stableInfo, stableInfoSig, syncingPolicy, error in
guard error == nil else {
print("Error preparing:", error!)
return
"stableInfo": stableInfo!.base64EncodedString(),
"stableInfoSig": stableInfoSig!.base64EncodedString(),
"machineID": machineID!,
- "views": Array(views ?? Set()),
+ "views": Array(syncingPolicy?.viewList ?? Set()),
] as [String: Any]
do {
print(try TPCTLObjectiveC.jsonSerialize(cleanDictionaryForJSON(result)))
}
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: nil,
- policySecrets: policySecrets) { _, error in
+ policySecrets: policySecrets,
+ syncUserControllableViews: nil) { _, _, error in
guard error == nil else {
print("Error updating:", error!)
return
}
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!)
}
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!)
}
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!)
}
}
- 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,
}
}
- 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,
}
}
- 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<String> = Set()
var accountIsDemo: Bool = false
+++ /dev/null
-.
\ No newline at end of file
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);
{
OSStatus ortn;
- ASSERT(cmsEncoder->arena == NULL);
+ ASSERT(cmsEncoder->cmsMsg != NULL);
ASSERT(cmsEncoder->encoder == NULL);
cmsEncoder->encoderOut = CFDataCreateMutable(NULL, 0);
#include <CoreFoundation/CoreFoundation.h>
#include <Security/SecAsn1Types.h>
-#include <assert.h>
__BEGIN_DECLS
#define CFRELEASE(cfr) if(cfr != NULL) { CFRelease(cfr); }
+#include <security_utilities/simulatecrash_assert.h>
+#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
/*
* CMS digesting.
*/
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include "cmslocal.h"
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;
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;
}
#include <Security/SecIdentity.h>
#include <Security/SecCertificateInternal.h>
#include <Security/SecKeyPriv.h>
+#include <utilities/SecCFWrappers.h>
#include <CommonCrypto/CommonDigest.h>
#include <AssertMacros.h>
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;
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);
+++ /dev/null
-.
\ No newline at end of file
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include <strings.h>
/*
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));
#include <sys/param.h>
#include <stdlib.h>
#include <stdint.h>
-#include <assert.h>
+#include <utilities/simulatecrash_assert.h>
#include <fcntl.h>
#include <ctype.h>
#include <strings.h>
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; dex<len; dex++) {
/* convert to little-endian unicode */
res = ntlmStringToLE(pwd, &data, &len);
- if (res)
+ if (res) {
return res;
- /* md4 hash of that */
- md4Hash(data, len, digest);
- free(data);
+ }
+ /* md4 hash of that */
+ md4Hash(data, len, digest);
+ free(data);
return 0;
}
#define SEC_PROTOCOL_OPTIONS_KEY_enable_renegotiation "enable_renegotiation"
#define SEC_PROTOCOL_OPTIONS_KEY_enable_early_data "enable_early_data"
#define SEC_PROTOCOL_OPTIONS_KEY_peer_authentication_required "peer_authentication_required"
+#define SEC_PROTOCOL_OPTIONS_KEY_peer_authentication_optional "peer_authentication_optional"
#define SEC_PROTOCOL_OPTIONS_KEY_certificate_compression_enabled "certificate_compression_enabled"
-#define SEC_PROTOCOL_OPTIONS_KEY_tls_SIKE503_exchange_enabled "tls_SIKE503_exchange_enabled"
-#define SEC_PROTOCOL_OPTIONS_KEY_tls_HRSS_exchange_enabled "tls_HRSS_exchange_enabled"
#define SEC_PROTOCOL_OPTIONS_KEY_eddsa_enabled "eddsa_enabled"
#define SEC_PROTOCOL_OPTIONS_KEY_tls_delegated_credentials_enabled "tls_delegated_credentials_enabled"
#define SEC_PROTOCOL_OPTIONS_KEY_tls_grease_enabled "tls_grease_enabled"
CHECK_FIELD(enable_renegotiation);
CHECK_FIELD(enable_early_data);
CHECK_FIELD(peer_authentication_required);
+ CHECK_FIELD(peer_authentication_optional);
CHECK_FIELD(certificate_compression_enabled);
- CHECK_FIELD(tls_SIKE503_exchange_enabled);
- CHECK_FIELD(tls_HRSS_exchange_enabled);
CHECK_FIELD(eddsa_enabled);
CHECK_FIELD(tls_delegated_credentials_enabled);
CHECK_FIELD(tls_grease_enabled);
+ CHECK_FIELD(allow_unknown_alpn_protos);
#undef CHECK_FIELD
CHECK_BLOCK_QUEUE(challenge_block, challenge_queue);
CHECK_BLOCK_QUEUE(verify_block, verify_queue);
CHECK_BLOCK_QUEUE(tls_secret_update_block, tls_secret_update_queue);
+ CHECK_BLOCK_QUEUE(tls_encryption_level_update_block, tls_encryption_level_update_queue);
#undef CHECK_BLOCK_QUEUE
}
void
-sec_protocol_options_set_tls_server_name(sec_protocol_options_t options, const char *server_name)
+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(server_name,);
+ 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);
- CFStringRef serverName = CFStringCreateWithCString(NULL, server_name, kCFStringEncodingUTF8);
- if (serverName == NULL) {
- return false;
- }
- if (!SecFrameworkIsDNSName(serverName)) {
- CFRelease(serverName);
+ 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;
}
- CFRelease(serverName);
- free(content->server_name);
+ 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)
+{
+ SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
+ SEC_PROTOCOL_OPTIONS_VALIDATE(server_name,);
+
+ (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);
+
+ free(content->server_name);
content->server_name = strdup(server_name);
return true;
});
});
}
+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_key_update_block(sec_protocol_options_t options, sec_protocol_key_update_t update_block, dispatch_queue_t update_queue)
{
});
}
+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)
{
}
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_set_eddsa_enabled(sec_protocol_options_t options, bool eddsa_enabled)
{
SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
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;
+ content->eddsa_enabled = eddsa_enabled;
return true;
});
}
void
-sec_protocol_options_set_eddsa_enabled(sec_protocol_options_t options, bool eddsa_enabled)
+sec_protocol_options_set_tls_delegated_credentials_enabled(sec_protocol_options_t options, bool tls_delegated_credentials_enabled)
{
SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
- content->eddsa_enabled = eddsa_enabled;
+ content->tls_delegated_credentials_enabled = tls_delegated_credentials_enabled;
return true;
});
}
void
-sec_protocol_options_set_tls_delegated_credentials_enabled(sec_protocol_options_t options, bool tls_delegated_credentials_enabled)
+sec_protocol_options_set_tls_grease_enabled(sec_protocol_options_t options, bool tls_grease_enabled)
{
SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
- content->tls_delegated_credentials_enabled = tls_delegated_credentials_enabled;
+ content->tls_grease_enabled = tls_grease_enabled;
return true;
});
}
void
-sec_protocol_options_set_tls_grease_enabled(sec_protocol_options_t options, bool tls_grease_enabled)
+sec_protocol_options_set_allow_unknown_alpn_protos(sec_protocol_options_t options, bool allow_unknown_alpn_protos)
{
SEC_PROTOCOL_OPTIONS_VALIDATE(options,);
sec_protocol_options_content_t content = (sec_protocol_options_content_t)handle;
SEC_PROTOCOL_OPTIONS_VALIDATE(content, false);
- content->tls_grease_enabled = tls_grease_enabled;
+ content->allow_unknown_alpn_protos = allow_unknown_alpn_protos;
+ content->allow_unknown_alpn_protos_override = true;
return true;
});
}
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,
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));
.setter_pointer = sec_protocol_options_set_peer_authentication_required,
},
{
- .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_peer_authentication_optional,
+ .setter_pointer = sec_protocol_options_set_peer_authentication_optional,
},
{
- .key = SEC_PROTOCOL_OPTIONS_KEY_tls_HRSS_exchange_enabled,
- .setter_pointer = sec_protocol_options_set_tls_HRSS_exchange_enabled,
+ .key = SEC_PROTOCOL_OPTIONS_KEY_certificate_compression_enabled,
+ .setter_pointer = sec_protocol_options_set_tls_certificate_compression_enabled,
},
{
.key = SEC_PROTOCOL_OPTIONS_KEY_eddsa_enabled,
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;
+ });
+}
* @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
#import <Foundation/Foundation.h>
#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
}
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) {
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.
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);
}
}
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
#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; \
+ } \
} \
}
*stop = YES;
}
- 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");
+ 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);
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);
return (sec_protocol_options_t)_nw_protocol_create_options(mock_protocol_copy_definition());
}
-- (void)testExampleFile:(NSURL *)path
+static bool
+isLocalTLD(NSString *host)
{
- 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;
+ 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
+{
NSData *exampleData = [[NSData alloc] initWithContentsOfURL:path];
NSDictionary *exampleATS = [NSJSONSerialization JSONObjectWithData:exampleData options:kNilOptions error:nil];
XCTAssertNotNil(exampleATS, @"Loading %@ failed", path);
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"]) {
}
});
- 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);
+ }
}];
}
}];
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)
{
#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, \
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);
*
* @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);
* @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);
* @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);
* @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);
* 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);
* 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);
* @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
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 (this
+ * function is a no-op for clients). 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);
+
#ifdef __BLOCKS__
/*!
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
*
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
*
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
*
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
*
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
+#define SEC_PROTOCOL_HAS_PEER_AUTHENTICATION_OPTIONAL 1
+
struct sec_protocol_options_content {
SSLProtocol min_version;
SSLProtocol max_version;
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;
unsigned enable_early_data : 1;
unsigned enable_early_data_override : 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 {
});
}
+- (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];
});
}
+- (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];
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.
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));
}
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];
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
- (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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
@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));
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;
@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;
"NSAllowsArbitraryLoads": false,
"NSAllowsArbitraryLoadsForMedia": false,
"NSAllowsArbitraryLoadsInWebContent": false,
- "NSAllowsLocalNetworking": false,
+ "NSAllowsLocalNetworking": true,
"NSExceptionDomains": {
"apple.com": {
"NSIncludesSubdomains": true,
"NSExceptionAllowsInsecureHTTPLoads": true,
"NSExceptionMinimumTLSVersion": "TLSv1.2",
"NSExceptionRequiresForwardSecrecy": false
- }
+ },
+ "example.local": {
+ }
}
-}
\ No newline at end of file
+}
<array>
<string>com.apple.security.sos</string>
</array>
+ <key>com.apple.private.security.storage.Keychains</key>
+ <true/>
</dict>
</plist>
<true/>
<key>com.apple.private.security.no-sandbox</key>
<true/>
+ <key>com.apple.security.app-sandbox</key>
+ <false/>
<key>keychain-cloud-circle</key>
<true/>
<key>com.apple.keystore.access-keychain-keys</key>
<true/>
<key>com.apple.keystore.device</key>
<true/>
- <key>com.apple.private.applecredentialmanager.allow</key>
+ <key>com.apple.keystore.lockassertion</key>
<true/>
<key>restore-keychain</key>
<true/>
<string>com.apple.ProtectedCloudStorage</string>
<string>com.apple.security.ckks</string>
</array>
+ <key>com.apple.private.security.storage.Keychains</key>
+ <true/>
</dict>
</plist>
_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]];
}
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"];
#import "CKKS.h"
#import "SecDbKeychainItemV7.h"
#import "SecItemPriv.h"
+#include "SecItemInternal.h"
#import "SecItemServer.h"
#import "spi.h"
#import "SecDbKeychainSerializedItemV7.h"
#include <utilities/SecDb.h>
#include <sys/stat.h>
#include <utilities/SecFileLocations.h>
-
-void* testlist = NULL;
+#include "der_plist.h"
+#import "SecItemRateLimit_tests.h"
#if USE_KEYSTORE
+ (void)setUp
{
[super setUp];
- SecCKKSDisable();
- securityd_init(NULL);
}
- (NSString*)nameOfTest
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[] = {
}
}
+- (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);
+}
+
+#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
--- /dev/null
+/*
+ * 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 <Security/Security.h>
+#import <Security/SecItemPriv.h>
+#include <Security/SecEntitlements.h>
+#include <ipc/server_security_helpers.h>
+
+#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
--- /dev/null
+#import "KeychainXCTest.h"
+#import <Security/Security.h>
+#import <Security/SecItemPriv.h>
+#include <Security/SecEntitlements.h>
+#include <ipc/server_security_helpers.h>
+
+@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, @YES);
+
+ // 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
#import "spi.h"
#import "SecDbKeychainSerializedItemV7.h"
#import "SecDbKeychainSerializedMetadata.h"
+#import "SecDbKeychainSerializedMetadataKey.h"
#import "SecDbKeychainSerializedSecretData.h"
#import "SecDbKeychainSerializedAKSWrappedKey.h"
#import <utilities/SecCFWrappers.h>
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);
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");
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;
}
- (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;
[[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;
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];
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);
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);
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);
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;
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];
// 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];
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);
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);
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");
__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;
});
#import <Security/Security.h>
#import <Security/SecItemPriv.h>
+#import <os/feature_private.h>
#import "KeychainXCTest.h"
// 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);
(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);
}
(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);
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);
-
- [self setEntitlements:@{ @"com.apple.application-identifier": @"com.apple.test-app-identifier" } validated:YES];
+ XCTAssertEqual(SecItemUpdateTokenItemsForAccessGroups(@"com.apple.testtoken", (__bridge CFArrayRef)@[(id)kSecAttrAccessGroupToken], (__bridge CFArrayRef)tokenItems), errSecSuccess);
- // 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 {
@property keyclass_t keyclassUsedForAKSDecryption;
@property SFAESKeySpecifier* keySpecifier;
-@property SFAESKey* fakeAKSKey;
+@property NSData* fakeAKSKey;
@property id keychainPartialMock;
- (void)setEntitlements:(NSDictionary<NSString *, id> *)entitlements validated:(BOOL)validated;
-- (NSData*)getDatabaseKeyDataithError:(NSError**)error;
+- (NSData*)getDatabaseKeyDataWithError:(NSError**)error;
@end
#import "CKKS.h"
#import "SecDbKeychainItemV7.h"
#import "SecDbKeychainMetadataKeyStore.h"
+#import "SecDbBackupManager_Internal.h"
#import "SecAKSObjCWrappers.h"
#import "SecItemPriv.h"
#import "SecTaskPriv.h"
#import <SecurityFoundation/SFKeychain.h>
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
+#include <corecrypto/ccpbkdf2.h>
+#include <corecrypto/ccsha2.h>
+#include <corecrypto/ccaes.h>
+#include <corecrypto/ccmode.h>
+#include <corecrypto/ccwrap.h>
+#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;
+}
#if USE_KEYSTORE
@implementation KeychainXCTest {
id _keychainPartialMock;
CFArrayRef _originalAccessGroups;
+ bool _simcrashenabled;
}
@synthesize keychainPartialMock = _keychainPartialMock;
+ (void)setUp
{
[super setUp];
-
SecCKKSDisable();
+ // 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];
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];
id refKeyMock = OCMClassMock([SecAKSRefKey class]);
[[[refKeyMock stub] andCall:@selector(alloc) onObject:[FakeAKSRefKey class]] alloc];
+ checkV12DevEnabled = testCheckV12DevEnabled;
NSArray* partsOfName = [self.name componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" ]"]];
+ // Calls SecKeychainDbReset which also resets metadata keys and backup manager
secd_test_setup_temp_keychain([partsOfName[1] UTF8String], NULL);
_originalAccessGroups = SecAccessGroupsGetCurrent();
+ SecResetLocalSecuritydXPCFakeEntitlements();
}
- (void)tearDown
{
[self.mockSecDbKeychainItemV7 stopMocking];
[self.mockSecAKSObjCWrappers stopMocking];
+ [self resetEntitlements];
SecAccessGroupsSetCurrent(_originalAccessGroups);
+ __security_simulatecrash_enable(_simcrashenabled);
+
+ [super tearDown];
+}
++ (void)tearDown {
+ SecResetLocalSecuritydXPCFakeEntitlements();
[super tearDown];
}
- (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
}
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;
}
}
// 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];
// 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];
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
{
[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];
}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>com.apple.application-identifier</key>
+ <string>com.apple.secdxctests</string>
+ <key>application-identifier</key>
+ <string>com.apple.secdxctests</string>
+ <key>com.apple.keystore.access-keychain-keys</key>
+ <true/>
+ <key>com.apple.keystore.lockassertion</key>
+ <true/>
+ <key>com.apple.private.associated-domains</key>
+ <true/>
+ <key>com.apple.private.necp.match</key>
+ <true/>
+ <key>com.apple.mkb.usersession.info</key>
+ <true/>
+ <key>seatbelt-profiles</key>
+ <array>
+ <string>securityd</string>
+ </array>
+ <key>com.apple.security.app-sandbox</key>
+ <false/>
+ <key>com.apple.security.get-task-allow</key>
+ <true/>
+ <key>keychain-access-groups</key>
+ <array>
+ <string>SecDbBackupManager-UnitTests</string>
+ </array>
+</dict>
+</plist>
+
Note that iOS and macOS uses different value for the same constant.
*/
+#define kSecEntitlementAppleApplicationIdentifier CFSTR("com.apple.application-identifier")
+#define kSecEntitlementBasicApplicationIdentifier CFSTR("application-identifier")
#if TARGET_OS_IPHONE
-#define kSecEntitlementApplicationIdentifier CFSTR("application-identifier")
+#define kSecEntitlementApplicationIdentifier kSecEntitlementBasicApplicationIdentifier
#else
-#define kSecEntitlementAppleApplicationIdentifier CFSTR("com.apple.application-identifier")
#define kSecEntitlementApplicationIdentifier kSecEntitlementAppleApplicationIdentifier
#endif
/* 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")
/* 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")
+
+/* 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
#include "SecTaskPriv.h"
#include <utilities/debugging.h>
+#include <utilities/entitlements.h>
#include <AssertMacros.h>
#include <CoreFoundation/CFRuntime.h>
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
-
- 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;
- }
-
- 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
- }
+ 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
+
+ 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
+
+ // 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) {
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;
*/
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
--- /dev/null
+#ifndef SystemEntitlements_h
+#define SystemEntitlements_h
+
+/*
+ This file collects entitlements defined on the platform and in use by Security.
+ */
+
+#include <CoreFoundation/CFString.h>
+
+__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 */
(global-name "com.apple.PowerManagement.control")
(global-name "com.apple.security.syspolicy")
(global-name "com.apple.security.agent")
- (global-name "com.apple.security.agent.login"))
+ (global-name "com.apple.security.agent.login")
+ (global-name "com.apple.security.KeychainStasher"))
(allow ipc-posix-shm
(ipc-posix-name "com.apple.AppleDatabaseChanged")
189D462D166AC95C001D8533 /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 1120;
+ LastUpgradeCheck = 1200;
ORGANIZATIONNAME = Apple;
};
buildConfigurationList = 189D4630166AC95C001D8533 /* Build configuration list for PBXProject "securityd_service" */;
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;
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)",
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;
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)";
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;
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_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;
#include <os/log.h>
#include <stdio.h>
#include <errno.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include <unistd.h>
#include <pwd.h>
#include <uuid/uuid.h>
{
#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");
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)) {
}
}
- 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
}
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;
if (data) {
*key = calloc(1u, data_len);
memcpy(*key, data, data_len);
- *key_len = (int)data_len;
+ *key_len = data_len;
}
}
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)
}
*/
#include <errno.h>
-#include <assert.h>
+#include <security_utilities/simulatecrash_assert.h>
#include <stdio.h> // vsnprintf()
#include <stdarg.h> // va_start(), et al.
#include <syslog.h>
{
// 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))
{
// 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 <string.h>
+
#include "kcdatabase.h"
#include "agentquery.h"
#include "kckey.h"
#include "session.h"
#include "notifications.h"
#include "SecRandom.h"
+#include "keychainstasherinterface.h"
#include <vector> // @@@ 4003540 workaround
#include <security_cdsa_utilities/acl_any.h> // for default owner ACLs
#include <security_cdsa_utilities/cssmendian.h>
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<Mutex> _(common());
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);
}
//
void KeychainDatabase::stashDb()
{
+ secnotice("KCdb", "Let's stash a key");
CssmAutoData data(Allocator::standard(Allocator::sensitive));
{
StLock<Mutex> _(common());
-
if (!common().isValid()) {
CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
}
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");
}
//
--- /dev/null
+#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 */
--- /dev/null
+#import <Foundation/Foundation.h>
+#import <Foundation/NSXPCConnection_Private.h>
+#import <Foundation/NSData_Private.h>
+
+#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<KeychainStasherProtocol> 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<KeychainStasherProtocol> 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;
+}
#include "server.h"
#include "session.h"
#include "notifications.h"
-#include "pcscmonitor.h"
#include "auditevents.h"
#include "self.h"
#include "util.h"
//
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;
//
// 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);
// program arguments (preset to defaults)
bool debugMode = false;
- 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:ims: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;
case 'm':
mdsIsInstalled = true;
break;
- case 's':
- smartCardOptions = optarg;
- break;
case 't':
if ((maxThreads = atoi(optarg)) < 0)
maxThreads = 0;
case 'v':
verbose++;
break;
- case 'X':
- doFork = true;
- reExecute = true;
- break;
default:
usage(argv[0]);
}
}
// 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
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);
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[-s off|on|conservative|aggressive] smartcard operation level"
"\n\t[-t maxthreads] [-T threadTimeout] server thread control"
"\n", me);
exit(2);
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
}
}
-
-//
-// 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<Mutex> _(setLock);
- pair<Iterator, Iterator> 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
//
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;
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.
</array>
<key>com.apple.private.security.storage.SystemKeychain</key>
<true/>
+ <key>com.apple.private.securityd.stash-agent-client</key>
+ <true/>
</dict>
</plist>
#include <mach/mach_error.h>
#include <security_utilities/ccaudit.h>
#include <security_utilities/casts.h>
-#include "pcscmonitor.h"
#include "agentquery.h"
#endif //DEBUGDUMP
case SIGUSR2:
- {
- extern PCSCMonitor *gPCSC;
- gPCSC->startSoftTokens();
- break;
- }
+ fprintf(stderr, "securityd ignoring SIGUSR2 received");
+ break;
default:
assert(false);
//
void Server::loadCssm(bool mdsIsInstalled)
{
+ try {
+
if (!mCssm->isActive()) {
StLock<Mutex> _(*this);
xpc_transaction_begin();
}
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();
+ }
}
#include <sys/wait.h>
#include <grp.h>
#include <pwd.h>
-#include <msgtracer_client.h>
using namespace MDSClient;
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.
//
identifiers.append(";");
identifiers.append(*i);
}
- mt_log_ctk_tokend(identifiers.c_str(), chosenIdentifier.c_str());
return leader;
}
#include <Security/AuthorizationTagsPriv.h>
#include <AssertMacros.h>
#include <security_utilities/errors.h>
+#include <Security/SecEntitlements.h>
#include <CoreFoundation/CFNumber.h>
#include <CoreFoundation/CFDictionary.h>
#define BEGIN_IPCN *rcode = CSSM_OK; try {
#define BEGIN_IPC(name) BEGIN_IPCN RefPointer<Connection> 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)); \
END_IPCN(CSSM)
if (*rcode)
Syslog::notice("setup(%s) failed rcode=%d", identity ? identity : "<NULL>", *rcode);
+ mach_port_deallocate(mach_task_self(), taskPort);
return KERN_SUCCESS;
}
END_IPCN(CSSM)
if (*rcode)
Syslog::notice("setupThread failed rcode=%d", *rcode);
+ mach_port_deallocate(mach_task_self(), taskPort);
return KERN_SUCCESS;
}
}
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);
}
if (info && CFDictionaryGetCount(info)) {
showInfo(info);
}
- if (info)
+ if (info) {
CFRelease(info);
+ }
- numCerts = SecTrustGetCertificateCount(peerTrust);
- for(i=0; i<numCerts; i++) {
+ numCerts = SecTrustGetCertificateCount(peerTrust);
+ for(i=0; i<numCerts; i++) {
plist = SecTrustCopySummaryPropertiesAtIndex(peerTrust, i);
- printf("\n============= Peer Trust Cert %lu Summary =============\n\n", i);
+ printf("\n============= Peer Trust Cert %lu Summary =============\n\n", i);
print_plist(plist);
- if (plist)
+ if (plist) {
CFRelease(plist);
- printf("\n============= Peer Trust Cert %lu Details =============\n\n", i);
- plist = SecTrustCopyDetailedPropertiesAtIndex(peerTrust, i);
+ }
+ printf("\n============= Peer Trust Cert %lu Details =============\n\n", i);
+ plist = SecTrustCopyDetailedPropertiesAtIndex(peerTrust, i);
print_plist(plist);
- if (plist)
+ if (plist) {
CFRelease(plist);
- printf("\n============= End of Peer Trust Cert %lu ==============\n", i);
- }
+ }
+ printf("\n============= End of Peer Trust Cert %lu ==============\n", i);
+ }
#endif
}
doTlsV11 = true;
break;
case '^':
- doSslV2 = doSslV3 = doTlsV1 = doTlsV12 = false;
+ doSslV2 = doSslV3 = doTlsV1 = false;
doTlsV12 = true;
break;
case 'L':
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]);
--- /dev/null
+(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 "/Library/Keychains/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)
*/
#include <TargetConditionals.h>
+#import <Foundation/NSError_Private.h>
+#import <dirhelper_priv.h>
+
+#if TARGET_OS_OSX
+#include <sandbox.h>
+#include <notify.h>
+#include <pwd.h>
+#endif
#if TARGET_OS_SIMULATOR
@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
<true/>
<key>com.apple.security.network.client</key>
<true/>
+ <key>com.apple.private.security.storage.SFAnalytics</key>
+ <true/>
</dict>
</plist>
+ (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
#if TARGET_OS_OSX
#include "dirhelper_priv.h"
+#include <membership.h>
#endif
#if TARGET_OS_OSX
#import <AppleAccount/ACAccount+AppleAccount.h>
#import <AppleAccount/ACAccountStore+AppleAccount.h>
+#import "utilities/simulatecrash_assert.h"
+
NSString* const SFAnalyticsSplunkTopic = @"topic";
NSString* const SFAnalyticsClientId = @"clientId";
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]
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) {
- secnotice("json", "client '%@' for topic '%@' force-included", client.name, _internalTopicName);
- } else {
- secnotice("json", "including client '%@' for topic '%@' for upload", client.name, _internalTopicName);
+ 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;
}
- [localClients addObject:client];
- }
- NSMutableDictionary* healthSummary = [self healthSummaryWithName:client.name store:store uuid:linkedUUID];
- if (healthSummary) {
- if (ckdeviceID) {
- healthSummary[SFAnalyticsDeviceID] = ckdeviceID;
+ 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);
+ 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];
}
- if (accountID) {
- healthSummary[SFAnalyticsAltDSID] = accountID;
+
+ 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];
}
- [localHealthSummaries addObject:healthSummary];
- }
- [hardFailures addObject:store.hardFailures];
- [softFailures addObject:store.softFailures];
+ [hardFailures addObject:store.hardFailures];
+ [softFailures addObject:store.softFailures];
+ }
}
if (upload && [localClients count] == 0) {
return [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory((__bridge CFStringRef)@"Analytics/localkeychain.db") path];
}
-+ (NSString*)databasePathForTrustdHealth
++ (NSString*)databasePathForTrust
{
#if TARGET_OS_IPHONE
- return [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory(CFSTR("Analytics/trustd_health_analytics.db")) path];
+ return [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory(CFSTR("Analytics/trust_analytics.db")) path];
#else
- return [(__bridge_transfer NSURL*)SecCopyURLForFileInUserCacheDirectory(CFSTR("Analytics/trustd_health_analytics.db")) path];
+ return [SFAnalytics defaultProtectedAnalyticsDatabasePath:@"trust_analytics"];
#endif
}
-+ (NSString*)databasePathForTrust
+#if TARGET_OS_OSX
++ (NSUUID *)rootUUID
{
-#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];
+ uuid_t rootUuid;
+ int ret = mbr_uid_to_uuid(0, 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 rootUUID]];
}
+#endif
-+ (NSString*)databasePathForTLS
++ (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 rootUUID]];
+}
+#endif
+
+ (NSString*)databasePathForSignIn
{
return [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory(CFSTR("Analytics/signin_metrics.db")) path];
/* 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, ...)
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>com.apple.application-identifier</key>
- <string>com.apple.private.security.SecDbBackupTests</string>
- <key>application-identifier</key>
- <string>com.apple.private.security.SecDbBackupTests</string>
- <key>com.apple.keystore.access-keychain-keys</key>
- <true/>
- <key>com.apple.keystore.lockassertion</key>
- <true/>
- <key>com.apple.private.associated-domains</key>
- <true/>
- <key>com.apple.private.necp.match</key>
- <true/>
- <key>com.apple.mkb.usersession.info</key>
- <true/>
- <key>seatbelt-profiles</key>
- <array>
- <string>securityd</string>
- </array>
- <key>com.apple.security.app-sandbox</key>
- <false/>
- <key>com.apple.security.get-task-allow</key>
- <true/>
- <key>keychain-access-groups</key>
- <array>
- <string>SecDbBackupManager-UnitTests</string>
- </array>
-</dict>
-</plist>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>com.apple.application-identifier</key>
+ <string>com.apple.private.security.SecDbBackupTests</string>
+ <key>application-identifier</key>
+ <string>com.apple.private.security.SecDbBackupTests</string>
+ <key>com.apple.keystore.access-keychain-keys</key>
+ <true/>
+ <key>com.apple.keystore.lockassertion</key>
+ <true/>
+ <key>com.apple.private.associated-domains</key>
+ <true/>
+ <key>com.apple.private.necp.match</key>
+ <true/>
+ <key>com.apple.mkb.usersession.info</key>
+ <true/>
+ <key>seatbelt-profiles</key>
+ <array>
+ <string>securityd</string>
+ </array>
+ <key>com.apple.security.app-sandbox</key>
+ <false/>
+ <key>com.apple.security.get-task-allow</key>
+ <true/>
+ <key>keychain-access-groups</key>
+ <array>
+ <string>SecDbBackupManager-UnitTests</string>
+ </array>
+ <key>com.apple.private.security.storage.Keychains</key>
+ <true/>
+</dict>
+</plist>
-//
-// SecDbBackupTests.m
-// Security
-//
-// Created by Wouter de Groot on 2018-12-12.
-//
-
-#import <XCTest/XCTest.h>
+#import "SecDbBackupTestsBase.h"
#import "keychain/securityd/SecDbBackupManager.h"
#if !SECDB_BACKUPS_ENABLED
#import "keychain/securityd/SecDbBackupManager_Internal.h"
-#import "CKKS.h"
-#import <utilities/SecFileLocations.h>
-#import "spi.h"
-#import "SecItemServer.h"
+
#import <objc/runtime.h>
#include "utilities/der_plist.h"
#include <Security/SecItemPriv.h>
-@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];
}
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
- (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");
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.
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
- <dict>
- <key>BATSConfigVersion</key>
- <string>0.1.0</string>
- <key>Project</key>
- <string>Security</string>
- <key>Tests</key>
- <array>
- <dict>
- <key>TestName</key>
- <string>SecDbBackupTests</string>
- <key>WorkingDirectory</key>
- <string>/AppleInternal/XCTests/com.apple.security/</string>
- <key>ShowSubtestResults</key>
- <true/>
- <key>Timeout</key>
- <integer>1200</integer>
- <key>Command</key>
- <array>
- <string>BATS_XCTEST_CMD SecDbBackupTests.xctest</string>
- </array>
- </dict>
- </array>
- </dict>
-</plist>
--- /dev/null
+#ifndef SecDbBackupTestsBase_h
+#define SecDbBackupTestsBase_h
+
+#import <XCTest/XCTest.h>
+
+// This isn't inheritance-based data hiding, this whole class is for convenience building tests
+#import "keychain/securityd/CheckV12DevEnabled.h"
+#import "CKKS.h"
+#import <utilities/SecFileLocations.h>
+#import "spi.h"
+#import "SecItemServer.h"
+
+@interface SecDbBackupTestsBase : XCTestCase
+
++ (void)setV12Development:(BOOL)newState;
+
+@end
+
+#endif /* SecDbBackupTestsBase_h */
--- /dev/null
+#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);
+
+ 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; });
+}
+
+- (void)tearDown {
+ // Put teardown code here. This method is called after the invocation of each test method in the class.
+}
+
++ (void)tearDown {
+ SetCustomHomeURL(NULL);
+ SecKeychainDbReset(NULL);
+ resetCheckV12DevEnabled();
+}
+
+@end
--- /dev/null
+#import <TargetConditionals.h>
+
+#if TARGET_OS_OSX
+
+#import <Cocoa/Cocoa.h>
+@interface AppDelegate : NSObject <NSApplicationDelegate>
+@end
+
+#else
+
+#import <UIKit/UIKit.h>
+@interface AppDelegate : UIResponder <UIApplicationDelegate>
+@property (strong, nonatomic) UIWindow *window;
+@end
+
+#endif
--- /dev/null
+#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
--- /dev/null
+{
+ "images" : [
+ {
+ "idiom" : "mac",
+ "size" : "16x16",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "16x16",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "32x32",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "32x32",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "128x128",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "128x128",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "256x256",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "256x256",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "512x512",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "mac",
+ "size" : "512x512",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>UIRequiresFullScreen</key>
+ <true/>
+#import <TargetConditionals.h>
+#if TARGET_OS_OSX
+ <key>LSMinimumSystemVersion</key>
+ <string>$(MACOSX_DEPLOYMENT_TARGET)</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+#endif
+</dict>
+</plist>
--- /dev/null
+#import <TargetConditionals.h>
+
+#if TARGET_OS_OSX
+
+#import <Cocoa/Cocoa.h>
+@interface ViewController : NSViewController
+@end
+
+#else
+
+#import <UIKit/UIKit.h>
+@interface ViewController : UIViewController
+@end
+
+#endif
--- /dev/null
+#import "ViewController.h"
+
+#if TARGET_OS_OSX
+
+@implementation ViewController
+- (void)viewDidLoad {
+ [super viewDidLoad];
+}
+- (void)setRepresentedObject:(id)representedObject {
+ [super setRepresentedObject:representedObject];
+}
+@end
+
+#else
+
+@implementation ViewController
+- (void)viewDidLoad {
+ [super viewDidLoad];
+}
+- (void)didReceiveMemoryWarning {
+ [super didReceiveMemoryWarning];
+ }
+@end
+
+#endif
--- /dev/null
+#import <TargetConditionals.h>
+
+#if TARGET_OS_OSX
+
+#import <Cocoa/Cocoa.h>
+
+int main(int argc, const char * argv[]) {
+ return NSApplicationMain(argc, argv);
+}
+
+#else
+
+#import <UIKit/UIKit.h>
+#import "AppDelegate.h"
+
+int main(int argc, char * argv[]) {
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+ }
+}
+
+#endif
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>com.apple.application-identifier</key>
+ <string>com.apple.security.KeychainEntitledTestRunner</string>
+ <key>application-identifier</key>
+ <string>com.apple.security.KeychainEntitledTestRunner</string>
+ <key>com.apple.developer.icloud-services</key>
+ <array>
+ <string>CloudKit</string>
+ </array>
+ <key>com.apple.private.cloudkit.masquerade</key>
+ <true/>
+ <key>com.apple.private.cloudkit.customAccounts</key>
+ <true/>
+ <key>com.apple.developer.icloud-container-environment</key>
+ <string>Development</string>
+ <key>com.apple.private.aps-connection-initiate</key>
+ <true/>
+ <key>aps-connection-initiate</key>
+ <true/>
+ <key>aps-environment</key>
+ <string>serverPreferred</string>
+ <key>keychain-access-groups</key>
+ <array>
+ <string>com.apple.security.ckks</string>
+ <string>SecDbBackupManager-UnitTests</string>
+ </array>
+ <key>keychain-cloud-circle</key>
+ <true/>
+ <key>com.apple.security.app-sandbox</key>
+ <false/>
+ <key>com.apple.security.get-task-allow</key>
+ <true/>
+ <key>com.apple.keystore.access-keychain-keys</key>
+ <true/>
+ <key>com.apple.keystore.lockassertion</key>
+ <true/>
+ <key>com.apple.private.associated-domains</key>
+ <true/>
+ <key>com.apple.private.necp.match</key>
+ <true/>
+ <key>com.apple.mkb.usersession.info</key>
+ <true/>
+</dict>
+</plist>
--- /dev/null
+//
+// KeychainEntitledTestRunner.m
+// KeychainEntitledTestRunner
+//
+// Stolen from Mark Pauley / CDEntitledTestRunner who stole it from Drew Terry / MobileContainerManager
+// Copyright 2016-2017 Apple. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <unistd.h>
+#import <XCTest/XCTest.h>
+
+@interface TestRunner : NSObject <XCTestObservation> {
+ NSBundle *_bundle;
+ XCTestSuite *_testSuite;
+}
+
+- (instancetype)initWithBundlePath:(NSString *)path andTestNames:(NSArray *)names;
+- (NSUInteger)runUnitTestSuite;
+
+- (void)testLogWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2);
+- (void)testLogWithFormat:(NSString *)format arguments:(va_list)arguments NS_FORMAT_FUNCTION(1,0);
+
+@end
+
+@implementation TestRunner
+- (instancetype)initWithBundlePath:(NSString *)path andTestNames:(NSArray *)names
+{
+ if ((self = [super init])) {
+ NSError *error = nil;
+
+ _bundle = [NSBundle bundleWithPath:path];
+ if (!_bundle) {
+ [self testLogWithFormat:@"No bundle at location %@ (%s)\n", path, strerror(errno)];
+ return nil;
+ }
+ if (![_bundle loadAndReturnError:&error]) {
+ [self testLogWithFormat:@"Test Bundle at %@ didn't load: %@\n", path, error];
+ return nil;
+ }
+
+ if(names) {
+ XCTestSuite* testSuite = [[XCTestSuite alloc] initWithName:[[path lastPathComponent] stringByDeletingPathExtension]];
+ XCTestSuite* loadedSuite = [XCTestSuite testSuiteForBundlePath:path];
+ // Filter out only the tests that were named.
+ [loadedSuite.tests enumerateObjectsUsingBlock:^(__kindof XCTest * _Nonnull test, NSUInteger __unused idx, BOOL * __unused _Nonnull stop) {
+ [self testLogWithFormat:@"Checking test %@\n", test.name];
+ if([names containsObject:test.name]) {
+ [testSuite addTest:test];
+ }
+ }];
+ _testSuite = testSuite;
+ }
+ else {
+ _testSuite = [XCTestSuite testSuiteForBundlePath:path];
+ }
+ }
+ return self;
+}
+
+- (NSUInteger)runUnitTestSuite
+{
+ [[XCTestObservationCenter sharedTestObservationCenter] addTestObserver:self];
+
+ [_testSuite runTest];
+
+ XCTestRun *testRun = [_testSuite testRun];
+
+ return testRun.totalFailureCount;
+}
+
+- (NSFileHandle *)logFileHandle
+{
+ return [NSFileHandle fileHandleWithStandardOutput];
+}
+
+- (void)testLogWithFormat:(NSString *)format, ...
+{
+ va_list ap;
+ va_start(ap, format);
+ [self testLogWithFormat:format arguments:ap];
+ va_end(ap);
+}
+
+- (void)testLogWithFormat:(NSString *)format arguments:(va_list)arguments
+{
+ NSString *message = [[NSString alloc] initWithFormat:format arguments:arguments];
+ [self.logFileHandle writeData:[message dataUsingEncoding:NSUTF8StringEncoding]];
+}
+
+- (NSDateFormatter *)dateFormatter
+{
+ static NSDateFormatter *dateFormatter;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ dateFormatter = [NSDateFormatter new];
+ dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss.SSS";
+ });
+ return dateFormatter;
+}
+
+/* -testBundleWillStart: // exactly once per test bundle
+ * -testSuiteWillStart: // exactly once per test suite
+ * -testCaseWillStart: // exactly once per test case
+ * -testCase:didFailWithDescription:... // zero or more times per test case, any time between test case start and finish
+ * -testCaseDidFinish: // exactly once per test case
+ * -testSuite:didFailWithDescription:... // zero or more times per test suite, any time between test suite start and finish
+ * -testSuiteDidFinish: // exactly once per test suite
+ * -testBundleDidFinish: // exactly once per test bundle
+ */
+
+- (void)testSuiteWillStart:(XCTestSuite *)testSuite
+{
+ [self testLogWithFormat:@"Test Suite '%@' started at %@\n", testSuite.name, [self.dateFormatter stringFromDate:testSuite.testRun.startDate]];
+}
+
+- (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
+{
+ XCTestRun *testRun = testSuite.testRun;
+ [self testLogWithFormat:@"Test Suite '%@' %s at %@.\n\t Executed %lu test%s, with %lu failure%s (%lu unexpected) in %.3f (%.3f) seconds\n",
+ testSuite.name,
+ (testRun.hasSucceeded ? "passed" : "failed"),
+ [self.dateFormatter stringFromDate:testRun.stopDate],
+ ((unsigned long)testRun.executionCount), (testRun.executionCount != 1 ? "s" : ""),
+ ((unsigned long)testRun.totalFailureCount), (testRun.totalFailureCount != 1 ? "s" : ""),
+ ((unsigned long)testRun.unexpectedExceptionCount),
+ testRun.testDuration,
+ testRun.totalDuration];
+}
+
+- (void)testCaseWillStart:(XCTestCase *)testCase
+{
+ [self testLogWithFormat:@"Test Case '%@' started.\n", testCase.name];
+}
+
+- (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
+{
+ [self testLogWithFormat:@"Test Case '%@' %s (%.3f seconds).\n", testCase.name, (testCase.testRun.hasSucceeded ? "passed" : "failed"), testCase.testRun.totalDuration];
+
+}
+@end
+
+
+
+
+static char* gTestBundleDir = "/AppleInternal/XCTests/com.apple.security";
+static char* gTestBundleName = "CKKSCloudKitTests";
+
+static NSMutableArray* gTestCaseNames = nil;
+
+static const char* opt_str = "d:t:c:h";
+
+static void usage(char*const binName, bool longUsage) {
+ fprintf(stderr, "Usage: %s [-d <test_dir>] -t test_bundle_name [(-c test_case_name)*]\n", binName);
+ if (longUsage) {
+ fprintf(stderr, "-d: argument = path to directory where test bundles live\n");
+ fprintf(stderr, "-t: argument = name of test bundle to be run (without extension)\n");
+ fprintf(stderr, "-c: argument = name of test case to be run (multiple)\n");
+ }
+}
+
+static void getOptions(int argc, char *const *argv) {
+ int ch;
+ while ( (ch = getopt(argc, argv, opt_str)) != -1 ) {
+ switch(ch)
+ {
+ case 'd':
+ gTestBundleDir = optarg;
+ break;
+ case 't':
+ gTestBundleName = optarg;
+ break;
+ case 'c':
+ if(!gTestCaseNames) {
+ gTestCaseNames = [NSMutableArray new];
+ }
+ [gTestCaseNames addObject:@(optarg)];
+ break;
+ case 'h':
+ case '?':
+ default:
+ usage(argv[0], true);
+ exit(0);
+ break;
+ }
+ }
+}
+
+int main (int argc, const char * argv[])
+{
+ @autoreleasepool {
+ getOptions(argc, (char*const*)argv);
+ NSString *testBundleDir = [NSString stringWithCString:gTestBundleDir encoding:NSUTF8StringEncoding];
+ NSString *testBundleName = [NSString stringWithCString:gTestBundleName encoding:NSUTF8StringEncoding];
+ NSString *testBundlePath = [[testBundleDir stringByAppendingPathComponent:testBundleName] stringByAppendingPathExtension:@"xctest"];
+
+ printf("Running unit tests %s at: %s\n", gTestCaseNames?gTestCaseNames.description.UTF8String:"[All]", testBundlePath.UTF8String);
+
+ TestRunner *unitTest = [[TestRunner alloc] initWithBundlePath:testBundlePath andTestNames:gTestCaseNames];
+ if (!unitTest) {
+ fprintf(stderr, "Failed to load unit test runner at: %s\n", testBundlePath.UTF8String);
+ return 1;
+ }
+
+ //runUnitTestSuite returns the number of failures. 0 = success, non-zero means failure. This complies with BATS testing standards.
+ return (int)[unitTest runUnitTestSuite];
+
+ return 0;
+ }
+}
--- /dev/null
+//
+// PersonalizationTests.m
+// Security
+//
+//
+
+#import <XCTest/XCTest.h>
+#import <Foundation/Foundation.h>
+#import "trust/trustd/personalization.h"
+
+#import "TrustDaemonTestCase.h"
+
+@interface PersonalizationTests: TrustDaemonTestCase
+@end
+
+@implementation PersonalizationTests
+
+
+@end
* @APPLE_LICENSE_HEADER_END@
*
*/
-
#ifndef _TRUSTTESTS_DAEMON_TESTCASE_H_
#define _TRUSTTESTS_DAEMON_TESTCASE_H_
--- /dev/null
+/*
+* 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 <AssertMacros.h>
+#import <XCTest/XCTest.h>
+#import <Foundation/Foundation.h>
+#include <Security/SecCertificate.h>
+#include <Security/SecCertificatePriv.h>
+#include <Security/SecPolicyPriv.h>
+#include <Security/SecTrust.h>
+#include <Security/SecTrustPriv.h>
+#include <utilities/SecCFRelease.h>
+
+#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];
+}
+
+@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
--- /dev/null
+//
+// 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_ */
--- /dev/null
+/*
+* Copyright (c) 2006-2019 Apple Inc. All Rights Reserved.
+*/
+
+#include <AssertMacros.h>
+#import <XCTest/XCTest.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <Security/SecCertificate.h>
+#include <Security/SecCertificatePriv.h>
+#include <Security/SecPolicyPriv.h>
+#include <Security/SecTrustPriv.h>
+#include <utilities/array_size.h>
+#include <utilities/SecCFRelease.h>
+
+#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
--- /dev/null
+/*
+* 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_ */
#include "trust/trustd/OTATrustUtilities.h"
#if !TARGET_OS_BRIDGE
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wquoted-include-in-framework-header"
#import <OCMock/OCMock.h>
+#pragma clang diagnostic pop
#endif
#if TARGET_OS_IPHONE
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);
+
+}
+
@end
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);
return result;
}
+#if !TARGET_OS_WATCH
+// Skip test on watchOS due to size constraints (rdar://66792084)
- (void) testBetterTLS {
NSArray<NSDictionary *> *testsArray = [self getTestsArray];
if([self untar_test_certs]) {
[[NSFileManager defaultManager] removeItemAtURL:tmpCertsDir error:nil];
}
+#endif //!TARGET_OS_WATCH
@end
- (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);
#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,
};
#include <utilities/SecInternalReleasePriv.h>
#include <utilities/SecCFRelease.h>
+#include <utilities/SecCFWrappers.h>
#include <Security/SecCertificate.h>
#include <Security/SecCertificatePriv.h>
#include <Security/SecPolicyPriv.h>
+#include <Security/SecPolicyInternal.h>
#include <Security/SecTrust.h>
#include <Security/SecTrustPriv.h>
#include "../TrustEvaluationTestHelpers.h"
const NSString *kSecTrustTestPinningPolicyResources = @"si-20-sectrust-policies-data";
+const NSString *kSecTrustTestPinnningTest = @"PinningPolicyTrustTest";
@interface PolicyTests : TrustEvaluationTestCase
@end
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);
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);
+ }];
+}
+
@end
--- /dev/null
+//
+// SMIMEPolicyTests.m
+// Security
+//
+// Created by Bailey Basile on 11/5/19.
+//
+
+#import <Foundation/Foundation.h>
+
+#include <Security/SecPolicyPriv.h>
+#include <utilities/SecCFWrappers.h>
+
+#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 /* <rdar://57130017> */
+ SecPolicyRef policy = SecPolicyCreateSMIME(kSecKeyExchangeEncryptSMIMEUsage, emailAddr);
+ XCTAssert([self runTrustEvalForLeaf:leaf policy:policy]);
+
+ // Look for Key Agreement Decrypt KU /* <rdar://57130017> */
+ 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 /* <rdar://57130017> */
+ 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 /* <rdar://57130017> */
+ 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
#include "SSLPolicyTests_data.h"
#import "TrustEvaluationTestCase.h"
+NSString * const testDirectory = @"ssl-policy-certs";
+
@interface SSLPolicyTests : TrustEvaluationTestCase
@end
- (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;
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));
}
- (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;
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
}
#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
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_ */
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);
NS_ASSUME_NONNULL_END
#include <Security/SecCertificatePriv.h>
#include <Security/SecTrustPriv.h>
#include <Security/SecPolicy.h>
+#include <Security/SecPolicyPriv.h>
#include <Security/SecTrustSettings.h>
#include <Security/SecTrustSettingsPriv.h>
#include "OSX/utilities/SecCFWrappers.h"
@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, ^{
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);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2008-2010,2012,2016 Apple Inc. All Rights Reserved.
+ */
+
+#include <Foundation/Foundation.h>
+#include <Security/SecCertificate.h>
+#include <Security/SecCertificatePriv.h>
+#include <Security/SecItem.h>
+#include <Security/SecItemPriv.h>
+#include <Security/SecPolicy.h>
+#include <Security/SecPolicyPriv.h>
+#include <Security/SecTrust.h>
+#include <Security/SecTrustSettings.h>
+#include <Security/SecTrustSettingsPriv.h>
+#include <Security/SecTrustPriv.h>
+#include <utilities/SecCFRelease.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#if TARGET_OS_IPHONE
+#include <Security/SecTrustStore.h>
+#else
+#include <Security/SecKeychain.h>
+#endif
+
+#include "../TestMacroConversions.h"
+#include "TrustSettingsTests_data.h"
+#import "TrustEvaluationTestCase.h"
+
+@interface TrustSettingsTests : TrustEvaluationTestCase
+@end
+
+/* bridgeOS doesn't support trust settings */
+#if !TARGET_OS_BRIDGE
+
+#if TARGET_OS_IPHONE
+#define setTS(cert, settings) \
+{ \
+ ok_status(SecTrustStoreSetTrustSettings(defaultStore, cert, settings), \
+ "set trust settings"); \
+}
+#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) \
+{ \
+ SecCertificateRef frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert); \
+ ok_status(SecTrustSettingsSetTrustSettings(frameworkCert, kSecTrustSettingsDomainAdmin, \
+ settings), "set trust settings"); \
+ CFReleaseNull(frameworkCert); \
+ usleep(20000); \
+}
+#endif
+
+#if TARGET_OS_IPHONE
+#define setTSFail(cert, settings) \
+{ \
+ is(SecTrustStoreSetTrustSettings(defaultStore, cert, settings), errSecParam, \
+ "set trust settings"); \
+}
+#else
+#define setTSFail(cert, settings) \
+{ \
+ SecCertificateRef frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert); \
+ is(SecTrustSettingsSetTrustSettings(frameworkCert, kSecTrustSettingsDomainAdmin, \
+ settings), errSecParam, "set trust settings"); \
+ CFReleaseNull(frameworkCert); \
+}
+#endif
+
+#if TARGET_OS_IPHONE
+#define removeTS(cert) \
+{ \
+ ok_status(SecTrustStoreRemoveCertificate(defaultStore, cert), \
+ "remove trust settings"); \
+}
+#else
+#define removeTS(cert) \
+{ \
+ SecCertificateRef frameworkCert = SecFrameworkCertificateCreateFromTestCert(cert); \
+ ok_status(SecTrustSettingsRemoveTrustSettings(cert, kSecTrustSettingsDomainAdmin), \
+ "remove trust settings"); \
+ CFReleaseNull(frameworkCert); \
+}
+#endif
+
+#define check_trust(certs, policy, valid_date, expected) \
+{ \
+ SecTrustRef trust = NULL; \
+ SecTrustResultType trust_result; \
+ ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), \
+ "create trust with " #policy " policy"); \
+ ok_status(SecTrustSetVerifyDate(trust, (__bridge CFDateRef)valid_date), \
+ "set trust verify date"); \
+ (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); \
+}
+
+static SecCertificateRef cert0 = NULL;
+static SecCertificateRef cert1 = NULL;
+static SecCertificateRef cert2 = NULL;
+static SecCertificateRef cert3 = NULL;
+static SecPolicyRef sslPolicy = NULL;
+static SecPolicyRef smimePolicy = NULL;
+static SecPolicyRef basicPolicy = NULL;
+static CFArrayRef sslChain = NULL;
+static CFArrayRef smimeChain = NULL;
+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
+
++ (void)setUp
+{
+ [super setUp];
+ cert0 = SecCertificateCreateWithBytes(NULL, _trustSettingsRoot, sizeof(_trustSettingsRoot));
+ cert1 = SecCertificateCreateWithBytes(NULL, _trustSettingsInt, sizeof(_trustSettingsInt));
+ cert2 = SecCertificateCreateWithBytes(NULL, _trustSettingsSSLLeaf, sizeof(_trustSettingsSSLLeaf));
+ cert3 = SecCertificateCreateWithBytes(NULL, _trustSettingsSMIMELeaf, sizeof(_trustSettingsSMIMELeaf));
+
+ sslPolicy = SecPolicyCreateSSL(true, CFSTR("testserver.apple.com"));
+ smimePolicy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME, CFSTR("username@apple.com"));
+ basicPolicy = SecPolicyCreateBasicX509();
+
+ const void *v_certs1[] = { cert2, cert1, cert0 };
+ sslChain = CFArrayCreate(NULL, v_certs1, sizeof(v_certs1)/sizeof(*v_certs1), &kCFTypeArrayCallBacks);
+
+ const void *v_certs2[] = { cert3, cert1, cert0 };
+ smimeChain = CFArrayCreate(NULL, v_certs2, sizeof(v_certs2)/sizeof(*v_certs2), &kCFTypeArrayCallBacks);
+
+ verify_date = [NSDate dateWithTimeIntervalSinceReferenceDate:482000000.0]; // Apr 10 2016
+
+#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.
+ * 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) {
+ return;
+ }
+
+ deleteMeCertificates = [[NSMutableArray alloc] init];
+
+ 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);
+
+ 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);
+
+ 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);
+
+ 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);
+
+ CFReleaseNull(kcRef);
+#endif
+}
+
++ (void)tearDown
+{
+#if !TARGET_OS_IPHONE
+ [deleteMeCertificates enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+ SecItemDelete((CFDictionaryRef)@{ (__bridge NSString*)kSecValuePersistentRef: [obj objectAtIndex:0]});
+ }];
+#endif
+
+ CFReleaseNull(cert0);
+ CFReleaseNull(cert1);
+ CFReleaseNull(cert2);
+ CFReleaseNull(cert3);
+ CFReleaseNull(sslPolicy);
+ CFReleaseNull(sslFrameworkPolicy);
+ CFReleaseNull(smimePolicy);
+ CFReleaseNull(basicPolicy);
+ CFReleaseNull(sslChain);
+ CFReleaseNull(smimeChain);
+ [super tearDown];
+}
+
+- (void)test_no_constraints
+{
+ /* root with the default TrustRoot result succeeds */
+ setTS(cert0, NULL);
+ check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
+ removeTS(cert0);
+
+ /* intermediate with the default TrustRoot result fails */
+ setTSFail(cert1, NULL);
+
+ /* root with TrustRoot result succeeds */
+ NSDictionary *trustRoot = @{ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)};
+ setTS(cert0, (__bridge CFDictionaryRef)trustRoot);
+ check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
+ removeTS(cert0);
+
+ /* intermediate with TrustRoot fails to set */
+ setTSFail(cert1, (__bridge CFDictionaryRef)trustRoot);
+
+ /* root with TrustAsRoot fails to set */
+ NSDictionary *trustAsRoot = @{ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot)};
+ setTSFail(cert0, (__bridge CFDictionaryRef)trustAsRoot);
+
+ /* intermediate with TrustAsRoot result succeeds */
+ setTS(cert1, (__bridge CFDictionaryRef)trustAsRoot);
+ check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
+ removeTS(cert1);
+
+ /* trusting the root but denying the intermediate fails */
+ NSDictionary *deny = @{ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny)};
+ setTS(cert0, NULL);
+ setTS(cert1, (__bridge CFDictionaryRef)deny);
+ check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultDeny);
+ removeTS(cert1);
+ removeTS(cert0);
+
+ /* the unspecified result gives us default behavior */
+ NSDictionary *unspecified = @{ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)};
+ setTS(cert1, (__bridge CFDictionaryRef)unspecified);
+ check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
+ removeTS(cert1);
+
+ /* trusting one leaf doesn't make other leaf trusted */
+ setTS(cert2, (__bridge CFDictionaryRef)trustAsRoot);
+ check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
+ check_trust(smimeChain, basicPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
+ removeTS(cert2);
+}
+
+- (void)test_policy_constraints
+{
+ /* Trust only for SSL server. SSL server policy succeeds. */
+ NSDictionary *sslServerAllowed = @{ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy,
+ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot) };
+ setTS(cert1, (__bridge CFDictionaryRef)sslServerAllowed);
+ check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultProceed);
+
+ /* SSL client policy fails. */
+ SecPolicyRef sslClient = SecPolicyCreateSSL(false, NULL);
+ check_trust(sslChain, sslClient, verify_date, kSecTrustResultRecoverableTrustFailure);
+ CFReleaseNull(sslClient);
+
+ /* Basic policy fails */
+ check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
+ removeTS(cert1);
+}
+
+- (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)sslFrameworkPolicy,
+ (__bridge NSString*)kSecTrustSettingsPolicyString: @("testserver.apple.com"),
+ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot) }
+ ];
+ setTS(cert2, (__bridge CFArrayRef)hostnameAllowed);
+ /* evaluating against trusted hostname passes */
+ check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultProceed);
+
+ /* evaluating against hostname not in trust settings is recoverable failure */
+ SecPolicyRef weirdnamePolicy = SecPolicyCreateSSL(true, CFSTR("weirdname.apple.com"));
+ check_trust(sslChain, weirdnamePolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
+ CFReleaseNull(weirdnamePolicy);
+
+ /* evaluating against hostname denied by trust settings is denied */
+ SecPolicyRef wrongnamePolicy = SecPolicyCreateSSL(true, CFSTR("wrongname.apple.com"));
+ check_trust(sslChain, wrongnamePolicy, verify_date, kSecTrustResultDeny);
+ CFReleaseNull(wrongnamePolicy);
+ removeTS(cert2);
+
+#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)smimeFrameworkPolicy,
+ (__bridge NSString*)kSecTrustSettingsPolicyString: @("username@apple.com"),
+ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot) }
+ ];
+ setTS(cert3, (__bridge CFArrayRef)emailAllowed);
+ /* evaluating against trusted email passes */
+ check_trust(smimeChain, smimePolicy, verify_date, kSecTrustResultProceed);
+
+ /* evaluating against hostname not in trust settings is recoverable failure */
+ SecPolicyRef weirdemailPolicy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME, CFSTR("weirdemail@apple.com"));
+ check_trust(smimeChain, weirdemailPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
+ CFReleaseNull(weirdemailPolicy);
+
+ /* evaluating against hostname denied by trust settings is denied */
+ SecPolicyRef wrongemailPolicy = SecPolicyCreateSMIME(kSecAnyEncryptSMIME, CFSTR("wrongemail@apple.com"));
+ check_trust(smimeChain, wrongemailPolicy, verify_date, kSecTrustResultDeny);
+ CFReleaseNull(wrongemailPolicy);
+ removeTS(cert3);
+
+#if TARGET_OS_OSX
+ CFReleaseNull(smimeFrameworkPolicy);
+#endif
+}
+
+#if TARGET_OS_OSX
+#include <Security/SecTrustedApplicationPriv.h>
+- (void)test_application_constraints
+{
+ SecTrustedApplicationRef thisApp = NULL, someOtherApp = NULL;
+
+ #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)};
+
+ NSDictionary *someOtherAppTS = @{ (__bridge NSString*)kSecTrustSettingsApplication: (__bridge id)someOtherApp,
+ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)};
+
+ /* This application Trust Setting succeeds */
+ setTS(cert0, (__bridge CFDictionaryRef)thisAppTS);
+ check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
+ removeTS(cert0);
+
+ /* Some other application Trust Setting fails */
+ setTS(cert0, (__bridge CFDictionaryRef)someOtherAppTS);
+ check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
+ removeTS(cert0);
+
+ CFReleaseNull(thisApp);
+ CFReleaseNull(someOtherApp);
+}
+#endif // TARGET_OS_OSX
+
+- (void)test_key_usage_constraints {
+ /* any key usage succeeds */
+ NSDictionary *anyKeyUse = @{ (__bridge NSString*)kSecTrustSettingsKeyUsage: @(kSecTrustSettingsKeyUseAny),
+ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)};
+ setTS(cert0, (__bridge CFDictionaryRef)anyKeyUse);
+ check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
+ removeTS(cert0);
+
+ /* signCert key usage on an intermediate or root succeeds */
+ NSDictionary *signCertUseRoot = @{ (__bridge NSString*)kSecTrustSettingsKeyUsage: @(kSecTrustSettingsKeyUseSignCert),
+ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)};
+ setTS(cert0, (__bridge CFDictionaryRef)signCertUseRoot);
+ check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
+ removeTS(cert0)
+
+ NSDictionary *signCertUseInt = @{ (__bridge NSString*)kSecTrustSettingsKeyUsage: @(kSecTrustSettingsKeyUseSignCert),
+ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot)};
+ setTS(cert1, (__bridge CFDictionaryRef)signCertUseInt);
+ check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
+ removeTS(cert1);
+
+ /* intermediate without signCert key usage fails */
+ NSDictionary *signatureUse = @{ (__bridge NSString*)kSecTrustSettingsKeyUsage: @(kSecTrustSettingsKeyUseSignature),
+ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot)};
+ setTS(cert1, (__bridge CFDictionaryRef)signatureUse);
+ check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
+ removeTS(cert1);
+
+ /* brief interlude to create a bunch of SMIME policies with different key usages */
+ SecPolicyRef smimeSignature = SecPolicyCreateSMIME(kSecSignSMIMEUsage, CFSTR("username@apple.com"));
+ SecPolicyRef smimeDataEncrypt = SecPolicyCreateSMIME(kSecDataEncryptSMIMEUsage, CFSTR("username@apple.com"));
+ SecPolicyRef smimeKeyEncrypt = SecPolicyCreateSMIME(kSecKeyEncryptSMIMEUsage, CFSTR("username@apple.com"));
+ SecPolicyRef smimeKeyExchange = SecPolicyCreateSMIME(kSecKeyExchangeBothSMIMEUsage, CFSTR("username@apple.com"));
+ SecPolicyRef smimeMultiple = SecPolicyCreateSMIME((kSecSignSMIMEUsage | kSecKeyEncryptSMIMEUsage),
+ CFSTR("username@apple.com"));
+
+ /* signature smime policy passes for signature use TS*/
+ setTS(cert3, (__bridge CFDictionaryRef)signatureUse);
+ check_trust(smimeChain, smimeSignature, verify_date, kSecTrustResultProceed);
+
+ /* any use policy fails for signature use TS */
+ check_trust(smimeChain, smimePolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
+
+ /* multiple use smime policy against signature use */
+ check_trust(smimeChain, smimeMultiple, verify_date, kSecTrustResultRecoverableTrustFailure);
+ removeTS(cert3);
+
+ /* key encrypt smime policy passes for key encrypt use */
+ NSDictionary *keyEncryptUse = @{ (__bridge NSString*)kSecTrustSettingsKeyUsage: @(kSecTrustSettingsKeyUseEnDecryptKey),
+ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot)};
+ setTS(cert3, (__bridge CFDictionaryRef)keyEncryptUse);
+ check_trust(smimeChain, smimeKeyEncrypt, verify_date, kSecTrustResultProceed);
+ removeTS(cert3);
+
+ /* multiple use smime policy against multiple uses */
+ NSDictionary *multipleUse = @{ (__bridge NSString*)kSecTrustSettingsKeyUsage: @(kSecTrustSettingsKeyUseEnDecryptKey |
+ kSecTrustSettingsKeyUseSignature),
+ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustAsRoot)};
+ setTS(cert3, (__bridge CFDictionaryRef)multipleUse)
+ check_trust(smimeChain, smimeMultiple, verify_date, kSecTrustResultProceed);
+
+ /* signature smime policy against multiple uses */
+ check_trust(smimeChain, smimeSignature, verify_date, kSecTrustResultRecoverableTrustFailure);
+
+ /* any use smime policy against multiple uses */
+ check_trust(smimeChain, smimePolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
+ removeTS(cert3);
+
+ CFReleaseNull(smimeSignature);
+ CFReleaseNull(smimeDataEncrypt);
+ CFReleaseNull(smimeKeyEncrypt);
+ CFReleaseNull(smimeKeyExchange);
+ CFReleaseNull(smimeMultiple);
+}
+
+- (void)test_allowed_errors
+{
+ setTS(cert0, NULL);
+
+ /* allow expired errors */
+ NSDate *expired_date = [NSDate dateWithTimeIntervalSinceReferenceDate:520000000.0]; // Jun 24 2017
+ check_trust(sslChain, basicPolicy, expired_date, kSecTrustResultRecoverableTrustFailure);
+
+ NSDictionary *allowExpired = @{ (__bridge NSString*)kSecTrustSettingsAllowedError: @(-2147409654),
+ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)};
+ setTS(cert1, (__bridge CFDictionaryRef)allowExpired)
+ setTS(cert2, (__bridge CFDictionaryRef)allowExpired);
+ check_trust(sslChain, basicPolicy, expired_date, kSecTrustResultProceed);
+ removeTS(cert2);
+ removeTS(cert1);
+
+ /* allow hostname mismatch errors */
+ SecPolicyRef wrongNameSSL = NULL;
+ wrongNameSSL = SecPolicyCreateSSL(true, CFSTR("wrongname.apple.com"));
+ check_trust(sslChain, wrongNameSSL, verify_date, kSecTrustResultRecoverableTrustFailure);
+
+ NSDictionary *allowHostnameMismatch = @{ (__bridge NSString*)kSecTrustSettingsAllowedError: @(-2147408896),
+ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified) };
+ setTS(cert2, (__bridge CFDictionaryRef)allowHostnameMismatch);
+ sleep(1); // sleep a little extra so trustd gets trust settings event before evaluating leaf
+ check_trust(sslChain, wrongNameSSL, verify_date, kSecTrustResultProceed);
+ removeTS(cert2);
+ CFReleaseNull(wrongNameSSL);
+
+ /* allow email mismatch errors */
+ SecPolicyRef wrongNameSMIME = NULL;
+ wrongNameSMIME = SecPolicyCreateSMIME(kSecAnyEncryptSMIME, CFSTR("test@apple.com"));
+ check_trust(smimeChain, wrongNameSMIME, verify_date, kSecTrustResultRecoverableTrustFailure);
+
+ NSDictionary *allowEmailMismatch = @{ (__bridge NSString*)kSecTrustSettingsAllowedError: @(-2147408872),
+ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified) };
+ setTS(cert3, (__bridge CFDictionaryRef)allowEmailMismatch);
+ sleep(1); // sleep a little extra so trustd gets trust settings event before evaluating leaf
+ check_trust(smimeChain, wrongNameSMIME, verify_date, kSecTrustResultProceed);
+ removeTS(cert3);
+ CFReleaseNull(wrongNameSMIME);
+
+ /* allowed error with a policy constraint */
+ NSDictionary *allowExpiredConstrained = @{ (__bridge NSString*)kSecTrustSettingsAllowedError: @(-2147409654),
+ (__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy,
+ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)};
+ setTS(cert1, (__bridge CFDictionaryRef)allowExpiredConstrained)
+ setTS(cert2, (__bridge CFDictionaryRef)allowExpiredConstrained);
+ check_trust(sslChain, sslPolicy, expired_date, kSecTrustResultProceed);
+ check_trust(sslChain, basicPolicy, expired_date, kSecTrustResultRecoverableTrustFailure);
+ removeTS(cert2);
+ removeTS(cert1);
+
+ removeTS(cert0);
+}
+
+- (void)test_multiple_constraints
+{
+ /* deny all but */
+ NSArray *denyAllBut = @[
+ @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy ,
+ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot)},
+ @{(__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny) }
+ ];
+ setTS(cert0, (__bridge CFArrayRef)denyAllBut);
+ check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultDeny);
+ check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultProceed);
+ removeTS(cert0);
+
+ /* allow all but */
+ NSArray *allowAllBut = @[
+ @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy ,
+ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)},
+ @{(__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot) }
+ ];
+ setTS(cert0, (__bridge CFArrayRef)allowAllBut);
+ check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
+ 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)sslFrameworkPolicy,
+ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultDeny)},
+ @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)basicFrameworkPolicy,
+ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot) }
+ ];
+ setTS(cert0, (__bridge CFArrayRef)specifyPolicyResult);
+ check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
+ check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultDeny);
+ check_trust(smimeChain, smimePolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
+ removeTS(cert0);
+
+ /* different results for additional constraint with same policy */
+ NSArray *policyConstraintResult = @[
+ @{(__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)sslFrameworkPolicy,
+ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified) }
+ ];
+ SecPolicyRef wrongNameSSL = NULL;
+ wrongNameSSL = SecPolicyCreateSSL(true, CFSTR("wrongname.apple.com"));
+ setTS(cert2, (__bridge CFArrayRef)policyConstraintResult);
+ sleep(1); // sleep a little extra so trustd gets trust settings event before evaluating leaf
+ check_trust(sslChain, wrongNameSSL, verify_date, kSecTrustResultProceed);
+ check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
+ removeTS(cert2);
+ CFReleaseNull(wrongNameSSL);
+
+#if TARGET_OS_OSX
+ CFReleaseNull(basicFrameworkPolicy);
+#endif
+}
+
+- (void)test_change_constraints
+{
+ /* allow all but */
+ NSArray *allowAllBut = @[
+ @{(__bridge NSString*)kSecTrustSettingsPolicy: (__bridge id)sslFrameworkPolicy ,
+ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)},
+ @{(__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot) }
+ ];
+ setTS(cert0, (__bridge CFArrayRef)allowAllBut);
+ check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
+ check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultRecoverableTrustFailure);
+
+ /* Don't clear trust settings. Just change them. */
+
+ /* root with the default TrustRoot result succeeds */
+ setTS(cert0, NULL);
+ check_trust(sslChain, basicPolicy, verify_date, kSecTrustResultProceed);
+ check_trust(sslChain, sslPolicy, verify_date, kSecTrustResultProceed);
+ removeTS(cert0);
+}
+
+- (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)frameworkPolicy ,
+ (__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultUnspecified)},
+ @{(__bridge NSString*)kSecTrustSettingsResult: @(kSecTrustSettingsResultTrustRoot) }
+ ];
+ setTS(cert0, (__bridge CFArrayRef)allowAllBut);
+
+ SecTrustRef trust = NULL;
+ 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");
+ XCTAssertFalse(SecTrustEvaluateWithError(trust, nil), "evaluate trust");
+ CFReleaseSafe(trust);
+ CFReleaseNull(policy);
+ CFReleaseNull(frameworkPolicy);
+
+ removeTS(cert0);
+}
+
+
+- (void)testDistrustSystemRoot
+{
+ // 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];
+}
+
+@end
+
+#else // TARGET_OS_BRIDGE
+@implementation TrustSettingsTests
+- (void)testSkipTests
+{
+ XCTAssert(true);
+}
+@end
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2016-2019 Apple Inc. All Rights Reserved.
+ */
+
+#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 */
+unsigned char _trustSettingsRoot[1008]={
+ 0x30,0x82,0x03,0xEC,0x30,0x82,0x02,0xD4,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00,
+ 0xEE,0xAD,0xE6,0x5E,0x2C,0x5C,0x7C,0x40,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,
+ 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,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,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,
+ 0x2C,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,
+ 0x54,0x72,0x75,0x73,0x74,0x20,0x53,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x20,0x54,
+ 0x65,0x73,0x74,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,
+ 0x36,0x30,0x33,0x31,0x39,0x32,0x33,0x33,0x30,0x34,0x34,0x5A,0x17,0x0D,0x32,0x36,
+ 0x30,0x33,0x31,0x37,0x32,0x33,0x33,0x30,0x34,0x34,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,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,
+ 0x70,0x70,0x6C,0x65,0x2C,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,0x54,0x72,0x75,0x73,0x74,0x20,0x53,0x65,0x74,0x74,0x69,0x6E,
+ 0x67,0x73,0x20,0x54,0x65,0x73,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,
+ 0xC6,0xB5,0x94,0x9F,0x10,0xC7,0x49,0x4F,0xAF,0xA5,0xE4,0x98,0xEE,0xEB,0x9C,0x39,
+ 0xCA,0xF0,0x47,0x54,0xCA,0x26,0x4A,0xDD,0x6E,0x1E,0x33,0x4F,0x5E,0xF5,0x9F,0x4A,
+ 0x41,0x3F,0xC3,0xCF,0xEB,0x30,0x51,0xD8,0x85,0xAB,0xD6,0xDD,0x45,0xBF,0x0D,0x67,
+ 0x0D,0xDA,0x88,0x07,0xD8,0xB2,0x6D,0x6C,0x56,0xEE,0x27,0x74,0xDE,0x81,0xAC,0x35,
+ 0x9F,0xBC,0x9E,0x4A,0x97,0x0E,0xB4,0x84,0xA4,0xFA,0x24,0x21,0xBE,0x74,0x40,0xB4,
+ 0x9E,0xFC,0x81,0x9B,0xE6,0x82,0xB8,0xB6,0xAD,0x33,0x88,0xEC,0x30,0x5B,0x88,0x56,
+ 0x7E,0x3D,0x03,0x7A,0xC7,0xC2,0x58,0xF9,0x7C,0x68,0x77,0x75,0x8B,0x59,0x82,0x28,
+ 0xFC,0x0B,0x69,0x25,0x61,0x1E,0xCA,0x1F,0x7C,0x4D,0x3E,0x74,0xE5,0xE1,0xA0,0xDD,
+ 0xB3,0xD8,0xBD,0x11,0x4A,0x57,0xB9,0xAA,0xB3,0x92,0x53,0x9C,0x2A,0xE5,0x91,0xD8,
+ 0x57,0xCC,0xAD,0xB9,0x7F,0x4B,0x94,0x0F,0xCD,0xE0,0xEF,0xF7,0xE9,0x2A,0xE4,0x90,
+ 0xEF,0xA2,0x69,0x53,0x46,0x68,0x5D,0x39,0xD5,0x08,0x24,0x33,0x3D,0x81,0xF5,0x34,
+ 0xCD,0x06,0xC4,0xDB,0xC7,0x59,0xF9,0x9C,0xD9,0x00,0xD1,0x33,0x8F,0xE5,0x9D,0xF5,
+ 0x7A,0xD0,0x91,0x3A,0x1F,0xE2,0x5C,0x24,0xB4,0xFD,0xF1,0x86,0x04,0x66,0x10,0xEC,
+ 0x8F,0xB5,0x50,0xEF,0xBC,0x13,0xC2,0x32,0x52,0xFD,0x55,0x8D,0x9A,0x3E,0xB1,0xA0,
+ 0x94,0x02,0x96,0xF4,0x64,0xE3,0x23,0x4F,0x18,0x19,0xAF,0x82,0xD0,0x25,0xA2,0x8C,
+ 0x76,0x6B,0xDA,0xBA,0xF9,0xE8,0x0D,0xBA,0x32,0x74,0xF1,0x2F,0xB9,0xE3,0xD2,0x93,
+ 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,0x03,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,0x68,0x31,0x64,0x1E,0x5C,0x68,0x6A,0x83,
+ 0xBD,0x39,0x22,0x44,0xF6,0xD3,0x6C,0x70,0xF7,0xDD,0x22,0x53,0x30,0x0D,0x06,0x09,
+ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,
+ 0x01,0xDF,0xE1,0x02,0xED,0x2A,0x55,0xC3,0xFF,0x9A,0xD7,0x43,0xCF,0xD9,0x5F,0x3C,
+ 0xD5,0xAF,0xB1,0xEF,0x1F,0xF1,0x15,0x88,0x17,0x37,0x69,0x25,0xC1,0x42,0xFC,0xE3,
+ 0x18,0xBC,0x02,0x6A,0x0B,0xAD,0xDB,0x49,0xE0,0xCB,0xBE,0x84,0xC0,0xF8,0x26,0xD0,
+ 0xA6,0x4C,0xCB,0x3D,0xF4,0x52,0xBA,0xF2,0x3B,0x2C,0x3F,0xD6,0x46,0xAA,0xC8,0xE7,
+ 0xE5,0x4A,0x41,0x7D,0xCA,0xC3,0x3A,0xEF,0xD0,0xFF,0xA2,0x1A,0x07,0x4E,0x18,0x70,
+ 0xC6,0xBD,0xA2,0x37,0xD9,0x72,0xFB,0x95,0xC9,0x0A,0x4E,0x39,0x0D,0x67,0x45,0xF2,
+ 0x92,0x34,0x2E,0x94,0x02,0x51,0x97,0x96,0x82,0x75,0x1C,0x7D,0x14,0x40,0x15,0x38,
+ 0xB5,0x4D,0x17,0xBE,0xCE,0xDB,0x54,0x12,0x68,0xF6,0xCE,0xFA,0xE0,0x73,0xD3,0x3B,
+ 0x7B,0x01,0xDC,0x43,0x17,0x46,0x00,0x2F,0x82,0x1F,0x4D,0x09,0x78,0x22,0x84,0x76,
+ 0x2B,0xB6,0xA4,0xA8,0x87,0xC3,0x3F,0x13,0x4D,0x99,0xEF,0x23,0x52,0x92,0xCE,0x65,
+ 0x1C,0x00,0x4A,0xCC,0xEE,0x3B,0x73,0xEB,0x52,0x86,0xA3,0xBC,0x22,0xAF,0xE2,0x88,
+ 0x5A,0xED,0x34,0x51,0xC4,0x67,0x9F,0xA2,0x7E,0x4B,0xCC,0x65,0xFC,0xD6,0x38,0x42,
+ 0x5A,0x24,0xB8,0x02,0x6F,0x99,0xA0,0xF7,0x38,0x86,0x8A,0x02,0xCD,0x28,0x9B,0xEA,
+ 0xD9,0xA0,0x24,0x57,0x1E,0x40,0x02,0x89,0x29,0x4C,0x3F,0xF5,0xEF,0x8F,0xE7,0x4C,
+ 0xDB,0x42,0xFA,0x8D,0x4C,0xD3,0x30,0xF7,0x71,0x7F,0xC2,0x41,0x66,0x19,0x7D,0x47,
+ 0x99,0x26,0xF5,0x74,0x39,0xFE,0xB8,0xDF,0x60,0x36,0x02,0x0E,0x77,0x28,0x12,0x84,
+};
+
+/* subject:/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=Trust Settings Test Sub CA */
+/* issuer :/C=US/ST=California/L=Cupertino/O=Apple, Inc./OU=Security Engineering/CN=Trust Settings Test Root CA */
+unsigned char _trustSettingsInt[1016]={
+ 0x30,0x82,0x03,0xF4,0x30,0x82,0x02,0xDC,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00,
+ 0xBE,0x29,0xEC,0x6D,0x40,0x7E,0x44,0x9A,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,
+ 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,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,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,
+ 0x2C,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,
+ 0x54,0x72,0x75,0x73,0x74,0x20,0x53,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x20,0x54,
+ 0x65,0x73,0x74,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,
+ 0x36,0x30,0x33,0x31,0x39,0x32,0x33,0x34,0x30,0x31,0x33,0x5A,0x17,0x0D,0x31,0x37,
+ 0x30,0x33,0x31,0x39,0x32,0x33,0x34,0x30,0x31,0x33,0x5A,0x30,0x7C,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,
+ 0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,
+ 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,0x54,
+ 0x72,0x75,0x73,0x74,0x20,0x53,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x20,0x54,0x65,
+ 0x73,0x74,0x20,0x53,0x75,0x62,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,0xC3,0x98,0xDB,0xB7,0x52,0xC3,
+ 0xC9,0xD3,0xB8,0x35,0x57,0xAE,0xF4,0x93,0x21,0xDD,0xAD,0x17,0xA8,0xE3,0x39,0xB0,
+ 0x27,0xF3,0x9F,0x12,0x77,0xF3,0xF0,0x03,0xED,0xAE,0xE7,0x79,0x86,0x17,0x07,0x1C,
+ 0xDE,0x34,0x41,0x25,0x39,0xCA,0xFE,0xD1,0x13,0x3B,0xBB,0x7E,0x77,0x7E,0x32,0x99,
+ 0xDD,0xEB,0xBA,0xDC,0x6D,0xB9,0xF5,0x8A,0x1C,0x19,0x71,0xE3,0xE4,0x7F,0x39,0x0C,
+ 0x3F,0x09,0x46,0x22,0x28,0x60,0x1A,0x42,0xA2,0x6E,0xE4,0x64,0xCF,0x02,0x68,0xAC,
+ 0x74,0xD1,0xBD,0xE4,0xC7,0x69,0x90,0xA5,0xA4,0x4F,0x1C,0x6E,0x08,0x79,0x28,0xE8,
+ 0x3E,0xE3,0x62,0x15,0xF8,0xB9,0xC1,0x56,0x1A,0xB0,0xE3,0x27,0x02,0xC6,0x29,0x20,
+ 0x7B,0x34,0x54,0xCC,0x0F,0xDB,0x5B,0x5E,0x81,0x0F,0x20,0xB7,0xB4,0x43,0xB3,0x29,
+ 0xE7,0xB7,0x83,0xCB,0x01,0xB3,0x57,0x3E,0x7B,0xBC,0x21,0x2F,0xED,0x24,0x99,0xB4,
+ 0xCD,0x64,0x9F,0x47,0xA3,0x5E,0x7B,0x99,0x69,0x8D,0xEB,0x6C,0x9D,0x60,0x7C,0x2F,
+ 0x2D,0xF5,0xC9,0x9D,0x11,0x7B,0x61,0x4A,0x0D,0x70,0x11,0x14,0x6C,0xE1,0xCB,0xC1,
+ 0x20,0xAF,0x55,0xBF,0xBE,0x8B,0xB6,0x9A,0x03,0x6C,0xFD,0x7A,0xCF,0xFB,0x92,0xD1,
+ 0x85,0xEE,0x5B,0x1E,0xEA,0xDC,0x58,0xF3,0xF1,0x0B,0x88,0x9E,0xA5,0xB4,0xD2,0xCD,
+ 0x74,0x47,0x18,0xA8,0xE3,0xFD,0x45,0xC2,0xE1,0x4D,0x97,0x77,0x89,0x48,0xF9,0x66,
+ 0xA4,0xEF,0x9E,0x33,0x3E,0xF0,0xED,0x55,0xF7,0x92,0xF4,0x1B,0xF7,0xF6,0xF9,0x90,
+ 0xCE,0xD5,0xA1,0x3F,0xE7,0xB7,0x2E,0x33,0x8F,0x9D,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,0xFD,
+ 0x26,0x89,0x9C,0xA6,0x9A,0xF6,0x33,0x48,0xA9,0x5D,0x0B,0xF6,0x90,0x2F,0xA6,0xC8,
+ 0x22,0x30,0x70,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,
+ 0x68,0x31,0x64,0x1E,0x5C,0x68,0x6A,0x83,0xBD,0x39,0x22,0x44,0xF6,0xD3,0x6C,0x70,
+ 0xF7,0xDD,0x22,0x53,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,
+ 0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0xA0,0xCA,0xAB,0x34,0xCF,0x6A,0x97,0x40,
+ 0x58,0x49,0xEE,0xA5,0x03,0x98,0xDB,0x6B,0x8D,0x19,0x11,0x83,0x5C,0x52,0xA5,0xD0,
+ 0xA2,0x3B,0x5E,0x59,0x13,0x53,0xCA,0xAA,0x6B,0x26,0x6D,0x14,0x4A,0x6D,0x8A,0x61,
+ 0xA7,0xDD,0x3E,0x2D,0x8B,0x4A,0x62,0xA4,0x3D,0x06,0xEE,0x76,0xB5,0x6F,0x93,0x30,
+ 0xD1,0x29,0xEA,0x34,0x01,0xB3,0x6B,0x1A,0xF3,0xCA,0x26,0x1E,0x76,0x2E,0x46,0xB3,
+ 0x73,0xE1,0x97,0x95,0x2F,0x16,0xC8,0x1F,0xF8,0x79,0x0E,0xEA,0x36,0xB0,0xEA,0x49,
+ 0xBE,0x5A,0x40,0xFE,0x83,0x51,0x94,0x78,0x74,0xD0,0x22,0x87,0x34,0xF5,0xEE,0x44,
+ 0x55,0x4B,0x4A,0xFF,0xF9,0xCD,0x84,0x68,0x32,0x94,0x98,0xCF,0xE0,0x51,0x66,0xEC,
+ 0x93,0x12,0x26,0x37,0xBD,0xA1,0x71,0x3B,0xF6,0x7A,0x40,0x48,0x62,0xC8,0xDD,0xE8,
+ 0x74,0x2C,0x14,0x09,0x18,0xDA,0x23,0x85,0xFF,0x2A,0x65,0xBF,0x0E,0x72,0x32,0xE2,
+ 0xD8,0x89,0x36,0x99,0x51,0x00,0xBD,0x16,0x48,0x46,0xFB,0x02,0xFA,0x7A,0xC3,0x73,
+ 0xBC,0x3B,0xB4,0x34,0x1C,0xBD,0x63,0x8D,0x12,0x97,0x66,0x8E,0x89,0x6C,0x79,0x8C,
+ 0xA9,0x77,0x49,0x92,0x7E,0xB2,0xF8,0xDE,0x58,0xB9,0xF1,0xEA,0xAF,0x74,0x94,0x46,
+ 0x1A,0x7B,0x5F,0x65,0x8D,0x08,0x38,0xBA,0xE4,0xB2,0xC2,0x27,0x05,0x76,0x38,0x1F,
+ 0x2B,0xFD,0x29,0x86,0xDA,0x38,0xB3,0x1E,0x37,0x38,0xE4,0x6F,0x81,0x35,0xA7,0x82,
+ 0x85,0xF5,0x8B,0xEC,0x24,0xD1,0xA1,0x12,0xFB,0x54,0xC4,0x51,0xA4,0x97,0xF2,0x0B,
+ 0xD4,0xE5,0x79,0x49,0x60,0x27,0x0D,0x5D,
+};
+
+/* subject:/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=Trust Settings Test SSL Leaf */
+/* issuer :/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=Trust Settings Test Sub CA */
+unsigned char _trustSettingsSSLLeaf[1059]={
+ 0x30,0x82,0x04,0x1F,0x30,0x82,0x03,0x07,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00,
+ 0x81,0x94,0x54,0x10,0xDC,0xA5,0x98,0x17,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,
+ 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x7C,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,0x14,0x30,0x12,0x06,
+ 0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,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,0x54,0x72,0x75,0x73,0x74,
+ 0x20,0x53,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x20,0x54,0x65,0x73,0x74,0x20,0x53,
+ 0x75,0x62,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x36,0x30,0x33,0x32,0x30,0x30,
+ 0x30,0x31,0x30,0x35,0x37,0x5A,0x17,0x0D,0x31,0x37,0x30,0x33,0x32,0x30,0x30,0x30,
+ 0x31,0x30,0x35,0x37,0x5A,0x30,0x7E,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,0x14,0x30,0x12,0x06,0x03,0x55,
+ 0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,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,0x54,0x72,0x75,0x73,0x74,0x20,0x53,
+ 0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x20,0x54,0x65,0x73,0x74,0x20,0x53,0x53,0x4C,
+ 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,0xBC,0x1C,0xAC,0x0E,0x78,0xFC,0xFA,0x63,0x97,0x5B,
+ 0xE3,0xFB,0xE9,0x31,0x60,0x9C,0xAE,0x81,0x9F,0xE1,0x19,0x95,0xF1,0xE2,0x27,0x14,
+ 0x33,0x86,0xA3,0x11,0x16,0x35,0x36,0x93,0x05,0xB6,0x88,0xC1,0x97,0x52,0xAB,0x0D,
+ 0xA6,0x22,0xF2,0x5E,0xDF,0x9E,0x27,0x9F,0x82,0x4F,0x0B,0xAD,0x96,0x9D,0xD4,0x7A,
+ 0x85,0xEA,0x62,0x89,0x6E,0xD5,0xC1,0x0D,0xCD,0x0D,0x15,0x4D,0x66,0x1F,0xA9,0xA8,
+ 0xB3,0xFA,0xC1,0x59,0x74,0x69,0xE6,0xA5,0x4A,0xF2,0xA3,0xC9,0x5F,0x29,0x7D,0x9E,
+ 0x49,0x5B,0x02,0x41,0x11,0x80,0x5C,0xD0,0x69,0x41,0x7C,0x05,0xFB,0xBA,0x0B,0xB6,
+ 0x10,0x6D,0x30,0xF3,0xB7,0x76,0x4A,0x32,0xCE,0xF0,0x50,0x74,0x70,0x1C,0x7A,0xE7,
+ 0x05,0x2A,0x01,0x00,0xB0,0xBB,0x22,0xB0,0xAD,0x7C,0x19,0xFD,0x5A,0xE3,0xC5,0xCD,
+ 0x51,0x15,0x97,0xF4,0xE4,0xEF,0x60,0x56,0x2C,0x92,0xB1,0xD4,0x9D,0xF9,0x26,0x1F,
+ 0x0C,0x11,0x2F,0x2F,0xA5,0xFA,0xD6,0x8E,0x87,0x1D,0xCC,0xA7,0xA0,0x3C,0x23,0xBB,
+ 0x52,0x30,0x11,0x13,0x43,0x7C,0xFE,0x63,0xEE,0xAE,0xAF,0xE6,0xED,0x07,0xD2,0x89,
+ 0xCB,0xC0,0xFE,0xF1,0xBF,0x75,0x18,0xA8,0xFF,0x34,0x9A,0x5C,0x28,0xEC,0x18,0x55,
+ 0x68,0xF7,0x24,0x30,0x94,0x49,0x23,0xCB,0xF1,0xE3,0xBE,0x1D,0x51,0xA3,0x2B,0x21,
+ 0x7D,0xFC,0x6E,0x93,0x19,0xE7,0xA5,0x26,0xFE,0xE2,0x5D,0xED,0x4A,0xD4,0xB9,0x60,
+ 0xE4,0xE7,0x77,0xA8,0xFF,0x13,0x06,0x0D,0x58,0x82,0x25,0x6D,0xEB,0xAC,0xA9,0x56,
+ 0xF9,0x2C,0x60,0xBB,0x66,0x77,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0xA1,0x30,0x81,
+ 0x9E,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,
+ 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,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,0xC6,0xED,0xD2,0x4E,0x23,0xC9,
+ 0xA9,0xC8,0x64,0x3A,0x55,0x51,0x0F,0x27,0x52,0xD6,0x18,0x12,0x66,0xC8,0x30,0x1F,
+ 0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xFD,0x26,0x89,0x9C,0xA6,
+ 0x9A,0xF6,0x33,0x48,0xA9,0x5D,0x0B,0xF6,0x90,0x2F,0xA6,0xC8,0x22,0x30,0x70,0x30,
+ 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,
+ 0x01,0x01,0x00,0xB1,0x56,0x55,0xC7,0x1F,0xF6,0x15,0x59,0xA6,0x0B,0xC4,0xBB,0x48,
+ 0x53,0x1B,0xE7,0xC1,0x7F,0x72,0x65,0x0E,0xE9,0x08,0x22,0xF6,0x30,0x9C,0xB3,0xCA,
+ 0xCF,0xDE,0x16,0x2C,0x90,0x30,0x59,0xC4,0xB2,0xE7,0x1E,0xD2,0xF3,0xD6,0x29,0x94,
+ 0xA3,0xD5,0xFA,0x98,0xC1,0xBF,0xD7,0xC3,0x52,0xBC,0xFF,0x6D,0xB6,0xE1,0xCE,0x1A,
+ 0x59,0xF9,0x68,0x6D,0x98,0x8B,0x48,0x7D,0xE6,0xD0,0x1F,0xFE,0xF7,0x9C,0x73,0x09,
+ 0x73,0x9B,0x5D,0xAF,0x88,0x37,0x35,0x1C,0x3F,0x9A,0x07,0xE0,0x3B,0x29,0x24,0x7F,
+ 0x04,0x9A,0xD2,0x3F,0xDE,0xF3,0x68,0x1D,0x16,0x8D,0xD0,0x4F,0xB6,0x83,0x19,0x70,
+ 0xBB,0x1F,0x21,0x91,0x49,0x3F,0x12,0x89,0xF6,0x88,0x8A,0x2F,0xDC,0x55,0x54,0xBE,
+ 0x78,0xDD,0x2F,0xC9,0x0C,0x7B,0x8C,0xA8,0x33,0x33,0x1D,0xA0,0x6D,0xA4,0xA6,0x6A,
+ 0xA4,0x49,0xD6,0x37,0x6D,0x95,0x15,0x0C,0xFA,0xA5,0xCF,0x5A,0x28,0xD9,0x37,0x5D,
+ 0xC5,0xC5,0x3A,0x30,0x8D,0x54,0xE4,0xAB,0x19,0x7A,0xF0,0x33,0xAE,0x64,0xA9,0x42,
+ 0x83,0xD2,0xF2,0x68,0x39,0xA2,0xE1,0x71,0x68,0x19,0x81,0x5A,0x9B,0xB4,0xDD,0xBC,
+ 0xA6,0xC7,0x19,0x40,0x87,0x50,0x6F,0x49,0xD2,0xC1,0x92,0x57,0xE4,0x5B,0x5F,0x41,
+ 0x85,0x22,0x33,0x8D,0xC7,0x0B,0x3F,0x55,0xC1,0x46,0x2C,0xB6,0xDE,0xF7,0x80,0x54,
+ 0xA5,0x62,0x0E,0xA3,0x24,0x14,0x9B,0xF1,0xEE,0x9D,0x7F,0x65,0xA2,0x1D,0x0C,0x32,
+ 0x86,0x81,0xDE,0xDC,0xD7,0xB6,0x06,0x3A,0xF6,0xF0,0x81,0x6A,0xBE,0xC4,0xA0,0x87,
+ 0xEA,0x6A,0x6C,
+};
+
+/* subject:/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=Trust Settings Test SMIME Leaf */
+/* issuer :/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=Trust Settings Test Sub CA */
+unsigned char _trustSettingsSMIMELeaf[1050]={
+ 0x30,0x82,0x04,0x16,0x30,0x82,0x02,0xFE,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00,
+ 0x81,0x94,0x54,0x10,0xDC,0xA5,0x98,0x18,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,
+ 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x7C,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,0x14,0x30,0x12,0x06,
+ 0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,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,0x54,0x72,0x75,0x73,0x74,
+ 0x20,0x53,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x20,0x54,0x65,0x73,0x74,0x20,0x53,
+ 0x75,0x62,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x36,0x30,0x33,0x32,0x30,0x30,
+ 0x30,0x31,0x31,0x35,0x32,0x5A,0x17,0x0D,0x31,0x37,0x30,0x33,0x32,0x30,0x30,0x30,
+ 0x31,0x31,0x35,0x32,0x5A,0x30,0x81,0x80,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,0x14,0x30,0x12,0x06,0x03,
+ 0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,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,0x75,0x73,0x74,0x20,
+ 0x53,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x20,0x54,0x65,0x73,0x74,0x20,0x53,0x4D,
+ 0x49,0x4D,0x45,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,0xE7,0x42,0xF7,0x3B,0x41,0xB4,0x91,
+ 0xF6,0xC3,0x4F,0x5B,0x52,0x9C,0x4D,0x1E,0x0D,0x1F,0x1A,0xE8,0x07,0x14,0x00,0x48,
+ 0x00,0x18,0x13,0xA6,0xD0,0xC4,0x49,0x6A,0xC7,0x47,0xBE,0xC6,0x07,0x9F,0xED,0x81,
+ 0xC8,0x49,0x7C,0xC8,0x69,0x14,0x2D,0xAD,0xD4,0x98,0x58,0x1A,0x6D,0xCC,0x28,0x54,
+ 0xA1,0x13,0xAF,0x2A,0xB5,0xF5,0x4B,0x6F,0x97,0x85,0x33,0xE0,0x12,0xF8,0x06,0x95,
+ 0xA0,0x57,0x81,0xD1,0x51,0x4E,0x1B,0x29,0x80,0x9F,0x3C,0x49,0x34,0x28,0x61,0x59,
+ 0x6A,0x56,0xA1,0x13,0x52,0x1B,0x41,0x6E,0xE2,0xA7,0xE1,0x6E,0x10,0xCC,0x07,0x48,
+ 0x0C,0x36,0x25,0x35,0xD3,0xBB,0x8F,0x45,0xF9,0x37,0x4D,0xB4,0xC7,0x9E,0xFA,0x7F,
+ 0x99,0xFC,0xB5,0x35,0xD7,0x96,0xC6,0xF7,0xF0,0x19,0x34,0xB6,0xD9,0x3C,0x82,0x38,
+ 0xBF,0x23,0x04,0x21,0x4A,0xFC,0xC1,0x8C,0x89,0xB1,0x45,0xFC,0x9B,0x4D,0xAE,0x28,
+ 0x4F,0xF6,0xD3,0x69,0xBB,0x3B,0xC5,0x5F,0x72,0xC7,0xD3,0xDF,0x70,0x97,0x7B,0xEE,
+ 0xD6,0x09,0xD6,0x21,0xF3,0xCF,0x8D,0x50,0xAF,0x48,0xDA,0x2C,0xEB,0x90,0x8E,0x1D,
+ 0xEE,0x94,0xA7,0xAB,0x21,0x0E,0xC8,0xE2,0xA1,0x7F,0x36,0x98,0x1A,0x99,0xDD,0x85,
+ 0x3A,0xEE,0xF0,0xE6,0x34,0x15,0x98,0x6D,0xA8,0x22,0x4E,0x4F,0x54,0x06,0xF1,0x1F,
+ 0xE0,0xDD,0x8E,0xB1,0xA5,0x94,0xA2,0xC5,0xD2,0xA3,0xEA,0xD9,0xD9,0x28,0x1B,0x4B,
+ 0x98,0x82,0x89,0x18,0x2D,0x7B,0x17,0xD6,0x92,0x5F,0x20,0x44,0xAF,0xD5,0x27,0x02,
+ 0x2C,0x2E,0x8F,0x14,0x20,0x70,0xA1,0xD4,0x65,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,
+ 0x95,0x30,0x81,0x92,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,
+ 0x30,0x00,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,
+ 0x06,0x01,0x05,0x05,0x07,0x03,0x04,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,
+ 0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x1D,0x06,0x03,0x55,0x1D,0x11,0x04,0x16,
+ 0x30,0x14,0x81,0x12,0x75,0x73,0x65,0x72,0x6E,0x61,0x6D,0x65,0x40,0x61,0x70,0x70,
+ 0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,
+ 0x14,0xC6,0xD8,0x0B,0xD7,0xD4,0x9E,0x84,0x41,0xB3,0x59,0x05,0x41,0xDF,0xC3,0x2A,
+ 0x77,0xBB,0x41,0x20,0x85,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,
+ 0x80,0x14,0xFD,0x26,0x89,0x9C,0xA6,0x9A,0xF6,0x33,0x48,0xA9,0x5D,0x0B,0xF6,0x90,
+ 0x2F,0xA6,0xC8,0x22,0x30,0x70,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,
+ 0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x4B,0x02,0x37,0x7F,0xBA,0x3D,
+ 0xD5,0xDF,0xE9,0xD6,0x52,0x6D,0x39,0x23,0x83,0x1B,0xFB,0x17,0x15,0x1A,0x45,0x9E,
+ 0xF2,0x55,0xA3,0x2C,0x18,0xF1,0x01,0xA1,0x2D,0xAA,0x78,0x39,0xA8,0x5A,0xD5,0x9E,
+ 0x37,0xE4,0x50,0x31,0x7A,0x07,0x61,0xD8,0xE9,0x2A,0x32,0x1F,0x04,0x3F,0x27,0x03,
+ 0xDC,0x77,0x7F,0x1B,0xD7,0x45,0x55,0x1F,0x5B,0xCC,0x7A,0xF1,0x5C,0x74,0x9E,0xA5,
+ 0x2A,0xA3,0xAC,0x63,0xBE,0x8B,0xEB,0x38,0x39,0xEC,0x53,0x9E,0x09,0x5A,0x86,0x2D,
+ 0x25,0x9C,0x78,0x85,0x02,0x07,0xE5,0xE2,0x98,0xB3,0x70,0x50,0x1A,0xAE,0x4F,0xF4,
+ 0x9F,0x89,0xA9,0x84,0xBF,0x6F,0x03,0x42,0x6B,0x12,0x0A,0x15,0x73,0x3F,0xC6,0x8B,
+ 0x32,0xDA,0x52,0x17,0xC5,0xC2,0x96,0x68,0xF7,0x31,0x1B,0x5D,0xB1,0x49,0x4C,0x2D,
+ 0xE7,0x3E,0x42,0xD6,0xF1,0x14,0xA9,0xBE,0x2F,0xD9,0x65,0xEB,0x0F,0x51,0x58,0x09,
+ 0x7D,0x4D,0x07,0x4B,0xE4,0x49,0x13,0x8B,0x70,0xA9,0x90,0x6C,0x9F,0x10,0xD2,0x8B,
+ 0x90,0xBE,0x63,0xF9,0x8E,0xF8,0x73,0x22,0xBE,0x54,0xEE,0x96,0x56,0x66,0xBC,0x2F,
+ 0x2A,0xC6,0x6B,0x84,0x67,0x4D,0xD8,0xF7,0xBA,0xCD,0x75,0x3B,0x73,0xEF,0x05,0x46,
+ 0x52,0xA4,0xF9,0xA7,0x03,0x29,0xA4,0x9A,0x11,0xAE,0x79,0xE5,0x53,0x3E,0xC5,0xD7,
+ 0x75,0x39,0x2D,0x82,0xC3,0x60,0x5F,0x12,0x9B,0x90,0x19,0xD6,0xB1,0xA4,0xF7,0x8B,
+ 0x62,0xF9,0x44,0x4E,0x15,0xA5,0xD3,0xFF,0x75,0x4E,0x44,0x84,0x78,0xCF,0x68,0x18,
+ 0xFE,0x46,0xEB,0xFE,0x0E,0x11,0xCB,0x34,0x53,0xAB,
+};
+
+/* subject:/CN=Apple Corporate Root CA/OU=Certification Authority/O=Apple Inc./C=US */
+/* issuer :/CN=Apple Corporate Root CA/OU=Certification Authority/O=Apple Inc./C=US */
+uint8_t _corporateRoot[] = {
+ 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,
+};
+
+/* subject:/CN=Apple Corporate Server CA 1/OU=Certification Authority/O=Apple Inc./C=US */
+/* issuer :/CN=Apple Corporate Root CA/OU=Certification Authority/O=Apple Inc./C=US */
+uint8_t _corporateServerCA[] = {
+ 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,
+};
+
+/* subject:/CN=bbasile-test.scv.apple.com/OU=management:idms.group.631731/O=Apple Inc./ST=California/C=US */
+/* issuer :/CN=Apple Corporate Server CA 1/OU=Certification Authority/O=Apple Inc./C=US */
+uint8_t _corporateServerCert[] = {
+ 0x30,0x82,0x05,0xF4,0x30,0x82,0x04,0xDC,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x54,
+ 0x32,0x9C,0xE6,0xE6,0xD7,0x87,0x7E,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,0x31,0x38,0x30,0x39,0x32,0x37,0x30,0x34,0x32,0x30,
+ 0x34,0x31,0x5A,0x17,0x0D,0x32,0x30,0x31,0x30,0x32,0x36,0x30,0x34,0x32,0x30,0x34,
+ 0x31,0x5A,0x30,0x81,0x83,0x31,0x23,0x30,0x21,0x06,0x03,0x55,0x04,0x03,0x0C,0x1A,
+ 0x62,0x62,0x61,0x73,0x69,0x6C,0x65,0x2D,0x74,0x65,0x73,0x74,0x2E,0x73,0x63,0x76,
+ 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,0x33,0x31,0x37,0x33,
+ 0x31,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,0xAF,0x8C,0xB9,0x3F,0x56,0x41,0xF9,
+ 0xA5,0x93,0x89,0x95,0x58,0x31,0x90,0x84,0xD5,0x3E,0xBB,0xE4,0x7C,0x68,0xD4,0x5B,
+ 0x95,0x97,0x04,0xEF,0xE6,0x3C,0x8E,0x6A,0x98,0xD0,0xAD,0xDD,0x7A,0xF1,0x5E,0x4D,
+ 0xCF,0x40,0xEF,0x05,0xF7,0x02,0x8C,0x01,0x0B,0x74,0x9D,0x0C,0x7E,0xD1,0xF8,0x80,
+ 0x6E,0xAA,0xBF,0x96,0xB3,0x50,0x8F,0xB4,0x68,0x0C,0xFA,0xD0,0xDB,0xE7,0x93,0xA0,
+ 0x6A,0x84,0xF2,0xA3,0x90,0x62,0x54,0xBD,0xB0,0xB3,0x1F,0xD6,0x0E,0xD1,0x2B,0xBA,
+ 0x13,0x38,0x0A,0xD1,0x84,0x36,0x75,0x77,0xFB,0x3B,0x1E,0x61,0x1B,0x85,0x22,0xA9,
+ 0xF9,0x42,0xD6,0xA2,0x9B,0xCB,0x34,0x76,0xC0,0xAE,0x2B,0xB0,0x64,0x95,0x5B,0xC7,
+ 0x61,0x2A,0x0B,0x81,0xE0,0x01,0x34,0xB8,0x50,0xDC,0x26,0x77,0x55,0xF7,0x95,0xE1,
+ 0xEC,0x01,0x4F,0xA8,0x0E,0x89,0x25,0xFE,0x8E,0xAB,0x40,0x6E,0x17,0x14,0xAA,0xA8,
+ 0x6C,0x79,0x52,0xDC,0xE3,0xDA,0x15,0xBF,0xAF,0x3C,0x96,0x2B,0xA3,0x4D,0xFA,0xC5,
+ 0xB5,0x36,0xCD,0x2F,0x88,0xFF,0xD1,0x1E,0xB1,0xE6,0x7C,0x0E,0xBD,0x60,0x0A,0x78,
+ 0xF7,0x8A,0x22,0x86,0xAD,0xC7,0x43,0x73,0xD7,0x22,0x64,0x32,0xA8,0xEC,0xEB,0x4F,
+ 0x41,0x90,0xCC,0x2F,0xB5,0x1A,0xA4,0xE6,0x91,0x34,0x86,0xCA,0x0A,0x17,0x0B,0x28,
+ 0x5F,0x94,0xAE,0x4C,0xDB,0x94,0x7A,0xD9,0xC3,0x4A,0x09,0x11,0xFA,0x33,0x6A,0x99,
+ 0x85,0x66,0x12,0x0A,0x70,0x7D,0x99,0x88,0xBE,0xC8,0x4E,0xCF,0x01,0xD8,0xD1,0x54,
+ 0x46,0x85,0x66,0x31,0x37,0xB3,0x7E,0x0F,0x45,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,
+ 0x02,0x82,0x30,0x82,0x02,0x7E,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,0x25,0x06,0x03,0x55,
+ 0x1D,0x11,0x04,0x1E,0x30,0x1C,0x82,0x1A,0x62,0x62,0x61,0x73,0x69,0x6C,0x65,0x2D,
+ 0x74,0x65,0x73,0x74,0x2E,0x73,0x63,0x76,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,
+ 0x62,0xF3,0x37,0xB1,0x58,0x48,0x8F,0x49,0xEA,0x12,0x39,0x93,0x4C,0x17,0x91,0x07,
+ 0x2F,0x71,0x09,0x4B,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,0xE3,0xCE,0x7C,0xAC,0x0A,0xDE,0x21,0xB9,
+ 0xB0,0x9E,0x1C,0xE9,0x6B,0xD5,0xBC,0xB7,0x53,0xE7,0x16,0x62,0xB0,0x1D,0x3E,0x53,
+ 0xFE,0x47,0x1A,0x1A,0xA3,0x7A,0x69,0xC5,0xC0,0x8B,0xC9,0x0B,0xE1,0xBC,0xF6,0xE6,
+ 0xAC,0x7E,0x05,0x60,0xC2,0xC2,0x3C,0xBA,0xB4,0x39,0xF7,0xDD,0xA4,0x60,0xC8,0x5B,
+ 0x29,0x90,0x59,0x29,0xCF,0xC1,0x6D,0x38,0x38,0x83,0x81,0xFA,0x8A,0xB6,0x13,0xE6,
+ 0xC6,0xDA,0x64,0xD5,0x19,0x40,0x82,0x8C,0x38,0xC9,0xBE,0xC4,0x81,0xBA,0x88,0xC6,
+ 0x62,0xEC,0x42,0xED,0xCE,0x22,0xD2,0x52,0xE2,0x96,0x8C,0x3C,0xBC,0xCA,0xD4,0xF0,
+ 0xC8,0x24,0x09,0xA1,0xC6,0xD3,0x44,0x4F,0x22,0x36,0xF8,0x6F,0x28,0x20,0x9C,0x0C,
+ 0x71,0x10,0xCC,0x13,0x46,0x40,0xCF,0x15,0xF6,0x16,0x59,0xB2,0xC4,0xE6,0xDA,0x3D,
+ 0x9C,0xB4,0x01,0x33,0x4E,0x01,0x87,0xFC,0xEB,0x4B,0x45,0x0E,0x6C,0x14,0x93,0x48,
+ 0xA0,0x78,0xFA,0x0C,0x01,0xB0,0xEB,0xF1,0x6F,0x7B,0xE9,0xF4,0xED,0x42,0x92,0x07,
+ 0x3B,0xFC,0x14,0x15,0x69,0xE7,0x1E,0x33,0xD8,0x7C,0xE1,0xD6,0x37,0xBB,0x13,0x50,
+ 0x3E,0x3C,0x4A,0xD4,0x29,0xC7,0x29,0x3B,0x99,0x79,0xD5,0x92,0x96,0x64,0x28,0x0A,
+ 0x7A,0x4F,0x8C,0x4A,0x32,0xC6,0x49,0x9D,0x05,0x0E,0x25,0x2F,0x46,0x6D,0x60,0x83,
+ 0xA6,0x06,0x05,0x07,0x3F,0x50,0xFF,0x01,0x6C,0x3E,0xE2,0x71,0x09,0x74,0xD2,0x94,
+ 0xEB,0x17,0xF4,0xE7,0x2B,0xB0,0xFD,0x41,0x52,0xEF,0x25,0x71,0x9C,0x1C,0x36,0xA6,
+ 0x05,0x15,0xA6,0xD5,0x1E,0x23,0xB7,0xC2,
+};
+
+#endif /* _TRUSTTESTS_EVALUATION_TRUST_SETTINGS_TESTS_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2017-2019 Apple Inc. All Rights Reserved.
+ *
+ */
+
+#import <XCTest/XCTest.h>
+#import <Foundation/Foundation.h>
+
+#include <Security/Security.h>
+#include <Security/SecTrust.h>
+#include <Security/SecPolicy.h>
+#include <Security/SecCertificatePriv.h>
+#include <utilities/SecCFWrappers.h>
+#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
@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;
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];
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));
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_ */
#include <utilities/SecCFRelease.h>
#include "../TestMacroConversions.h"
#include "TrustFrameworkTestCase.h"
+#include <libDER/oids.h>
#include "CertificateInterfaceTests_data.h"
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);
+}
+
@end
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,
+};
+
#endif /* _TRUSTTESTS_CERTIFICATE_INTERFACE_H_ */
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
}
}
+- (void)testUnparseableSubjectName {
+ /* A bunch of certificates with different parsing errors the subject name */
+ NSArray <NSURL *>* 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
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
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 . . .
}];
}
+- (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);
+}
+
@end
</dict>
</array>
</dict>
- <dict>
- <key>CertDirectory</key>
- <string>si-20-sectrust-policies-data</string>
- <key>BridgeOSDisable</key>
- <true/>
- <key>MajorTestName</key>
- <string>AnchorSHA1</string>
- <key>MinorTestName</key>
- <string>OnlyFailure</string>
- <key>Policies</key>
- <dict>
- <key>PolicyIdentifier</key>
- <string>1.2.840.113635.100.1.51</string>
- </dict>
- <key>Leaf</key>
- <string>escrow_service_key_049F9D11</string>
- <key>Intermediates</key>
- <string>EscrowServiceRootCA101</string>
- <key>Anchors</key>
- <string>EscrowServiceRootCA101</string>
- <key>ExpectedProperties</key>
- <array>
- <dict>
- <key>type</key>
- <string>error</string>
- <key>value</key>
- <string>Root certificate is not trusted.</string>
- </dict>
- </array>
- </dict>
<dict>
<key>CertDirectory</key>
<string>si-20-sectrust-policies-data</string>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
- <dependencies>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
- <capability name="Safe area layout guides" minToolsVersion="9.0"/>
- <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
- </dependencies>
- <scenes>
- <!--View Controller-->
- <scene sceneID="EHf-IW-A2E">
- <objects>
- <viewController id="01J-lp-oVM" sceneMemberID="viewController">
- <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
- <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
- <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
- <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
- <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
- </view>
- </viewController>
- <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
- </objects>
- <point key="canvasLocation" x="53" y="375"/>
- </scene>
- </scenes>
-</document>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
- <dependencies>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
- <capability name="Safe area layout guides" minToolsVersion="9.0"/>
- <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
- </dependencies>
- <scenes>
- <!--View Controller-->
- <scene sceneID="tne-QT-ifu">
- <objects>
- <viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="" sceneMemberID="viewController">
- <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
- <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
- <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
- <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
- <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
- </view>
- </viewController>
- <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
- </objects>
- </scene>
- </scenes>
-</document>
@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];
[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 : @"<unknown>"), ((unsigned long)((nil != filePath) ? lineNumber : 0)), testSuite.name, description];
}
[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 : @"<unknown>"), ((unsigned long)((nil != filePath) ? lineNumber : 0)), testCase.name, description];
}
<array>
<string>com.apple.MobileAsset.PKITrustSupplementals</string>
</array>
+ <key>com.apple.security.exception.files.absolute-path.read-only</key>
+ <array>
+ <string>/System/Library/Caches/apticket.der</string>
+ </array>
+ <key>com.apple.system.diagnostics.iokit-properties</key>
+ <true/>
+ <key>com.apple.private.AuthorizationServices</key>
+ <array>
+ <string>com.apple.trust-settings.admin</string>
+ </array>
</dict>
</plist>
#include <utilities/SecInternalReleasePriv.h>
#include <utilities/SecCFRelease.h>
+#include <utilities/SecCFWrappers.h>
#include <Security/SecCertificate.h>
#include <Security/SecCertificatePriv.h>
#include <Security/SecPolicyPriv.h>
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;
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;
}
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
+ (void)failNextDecryptRefKey:(NSError* _Nonnull) decryptRefKeyError;
+ (NSError * _Nullable)popDecryptRefKeyFailure;
++ (void)setOperationsUntilUnlock:(int)val;
+
@end
#endif // OBJC2
#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;
static dispatch_queue_t _mutabilityQueue = nil;
static keybag_state_t _keybag_state = keybag_state_unlocked | keybag_state_been_unlocked;
static NSMutableArray<NSError *>* _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
*/
return error;
}
++ (void)setOperationsUntilUnlock:(int)val {
+ _operationsUntilUnlock = val;
+}
+
++ (void)updateOperationsUntilUnlock {
+ if (_operationsUntilUnlock == -1) {
+ return;
+ }
+
+ if (_operationsUntilUnlock == 0) {
+ _operationsUntilUnlock = -1;
+ [SecMockAKS unlockAllClasses];
+ return;
+ }
+
+ --_operationsUntilUnlock;
+}
+
@end
return kAKSReturnBusy;
}
+ [SecMockAKS updateOperationsUntilUnlock];
+
// Assumes non-device keybags are asym
if ([SecMockAKS isLocked:key_class] && handle == KEYBAG_DEVICE) {
return kAKSReturnNoPermission;
return kAKSReturnBusy;
}
+ [SecMockAKS updateOperationsUntilUnlock];
+
if ([SecMockAKS isLocked:key_class]) {
return kAKSReturnNoPermission;
}
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;
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)
{
return kAKSReturnSuccess;
}
-CFStringRef kMKBDeviceModeMultiUser = CFSTR("kMKBDeviceModeMultiUser");
-CFStringRef kMKBDeviceModeSingleUser = CFSTR("kMKBDeviceModeSingleUser");
-CFStringRef kMKBDeviceModeKey = CFSTR("kMKBDeviceModeKey");
+kern_return_t
+aks_get_device_state(keybag_handle_t handle, aks_device_state_s *device_state)
+{
+ // Probably not legal
+ return kAKSReturnError;
+}
-static CFStringRef staticKeybagHandle = CFSTR("keybagHandle");
+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
-MKBKeyBagCreateWithData(CFDataRef keybagBlob, MKBKeyBagHandleRef* newHandle)
+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)
{
- *newHandle = (MKBKeyBagHandleRef)staticKeybagHandle;
- return kMobileKeyBagSuccess;
+ return kAKSReturnError;
}
int
-MKBKeyBagUnlock(MKBKeyBagHandleRef keybag, CFDataRef passcode)
+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)
{
- if (keybag == NULL || !CFEqual(keybag, staticKeybagHandle)) {
- abort();
- }
- return kMobileKeyBagSuccess;
+ return kAKSReturnError;
}
-int MKBKeyBagGetAKSHandle(MKBKeyBagHandleRef keybag, int32_t *handle)
+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)
{
- if (keybag == NULL || !CFEqual(keybag, staticKeybagHandle)) {
- abort();
- }
- *handle = 17;
- return kMobileKeyBagSuccess;
+ return kAKSReturnError;
}
-int MKBGetDeviceLockState(CFDictionaryRef options)
+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)
{
- if ([SecMockAKS isLocked:key_class_ak]) {
- return kMobileKeyBagDeviceIsLocked;
- }
- return kMobileKeyBagDeviceIsUnlocked;
+ return kAKSReturnError;
}
-CF_RETURNS_RETAINED CFDictionaryRef
-MKBUserTypeDeviceMode(CFDictionaryRef options, CFErrorRef * error)
+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 CFBridgingRetain(@{
- (__bridge NSString *)kMKBDeviceModeKey : (__bridge NSString *)kMKBDeviceModeSingleUser,
- });
+ return kAKSReturnError;
}
-int MKBForegroundUserSessionID( CFErrorRef * error)
+/* 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 kMobileKeyBagSuccess;
+ return kAKSReturnError;
}
-const CFTypeRef kAKSKeyAcl = (CFTypeRef)CFSTR("kAKSKeyAcl");
-const CFTypeRef kAKSKeyAclParamRequirePasscode = (CFTypeRef)CFSTR("kAKSKeyAclParamRequirePasscode");
+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;
+}
-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");
+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;
+}
-TKTokenRef TKTokenCreate(CFDictionaryRef attributes, CFErrorRef *error)
+keyclass_t
+aks_ref_key_get_key_class(aks_ref_key_t handle)
{
- return NULL;
+ return key_class_a;
}
-CFTypeRef TKTokenCopyObjectData(TKTokenRef token, CFDataRef objectID, CFErrorRef *error)
+aks_key_type_t
+aks_ref_key_get_type(aks_ref_key_t handle)
{
- return NULL;
+ return key_type_sym;
}
-CFDataRef TKTokenCreateOrUpdateObject(TKTokenRef token, CFDataRef objectID, CFMutableDictionaryRef attributes, CFErrorRef *error)
+/* AKS Params (unimplemented) */
+
+aks_params_t aks_params_create(const uint8_t *der_params, size_t der_params_len)
{
return NULL;
}
-CFDataRef TKTokenCopyObjectAccessControl(TKTokenRef token, CFDataRef objectID, CFErrorRef *error)
+int aks_params_free(aks_params_t *params)
{
- return NULL;
+ return kAKSReturnSuccess;
}
-bool TKTokenDeleteObject(TKTokenRef token, CFDataRef objectID, CFErrorRef *error)
+
+int
+aks_params_set_data(aks_params_t params, aks_params_key_t key, const void *value, size_t length)
{
- return false;
+ return kAKSReturnError;
}
-CFDataRef TKTokenCopyPublicKeyData(TKTokenRef token, CFDataRef objectID, CFErrorRef *error)
+int
+aks_params_get_der(aks_params_t params, uint8_t **out_der, size_t *out_der_len)
{
- return NULL;
+ return kAKSReturnError;
}
-CFTypeRef TKTokenCopyOperationResult(TKTokenRef token, CFDataRef objectID, CFIndex secKeyOperationType, CFArrayRef algorithm,
- CFIndex secKeyOperationMode, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error)
+int
+aks_params_set_number(aks_params_t params, aks_params_key_t key, int64_t *num)
{
- return NULL;
+ return kAKSReturnError;
}
-CF_RETURNS_RETAINED CFDictionaryRef TKTokenControl(TKTokenRef token, CFDictionaryRef attributes, CFErrorRef *error)
+// 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)
{
- return NULL;
+ abort();
+ return kAKSReturnError;
}
-CFTypeRef LACreateNewContextWithACMContext(CFDataRef acmContext, CFErrorRef *error)
+CFStringRef kMKBDeviceModeMultiUser = CFSTR("kMKBDeviceModeMultiUser");
+CFStringRef kMKBDeviceModeSingleUser = CFSTR("kMKBDeviceModeSingleUser");
+CFStringRef kMKBDeviceModeKey = CFSTR("kMKBDeviceModeKey");
+
+static CFStringRef staticKeybagHandle = CFSTR("keybagHandle");
+
+int
+MKBKeyBagCreateWithData(CFDataRef keybagBlob, MKBKeyBagHandleRef* newHandle)
{
- return NULL;
+ *newHandle = (MKBKeyBagHandleRef)staticKeybagHandle;
+ return kMobileKeyBagSuccess;
}
-CFDataRef LACopyACMContext(CFTypeRef context, CFErrorRef *error)
+int
+MKBKeyBagUnlock(MKBKeyBagHandleRef keybag, CFDataRef passcode)
{
- return NULL;
+ if (keybag == NULL || !CFEqual(keybag, staticKeybagHandle)) {
+ abort();
+ }
+ return kMobileKeyBagSuccess;
}
-bool LAEvaluateAndUpdateACL(CFTypeRef context, CFDataRef acl, CFTypeRef operation, CFDictionaryRef hints, CFDataRef *updatedACL, CFErrorRef *error)
+int MKBKeyBagGetAKSHandle(MKBKeyBagHandleRef keybag, int32_t *handle)
{
- return false;
+ if (keybag == NULL || !CFEqual(keybag, staticKeybagHandle)) {
+ abort();
+ }
+ *handle = 17;
+ return kMobileKeyBagSuccess;
+}
+
+int MKBGetDeviceLockState(CFDictionaryRef options)
+{
+ if ([SecMockAKS isLocked:key_class_ak]) {
+ return kMobileKeyBagDeviceIsLocked;
+ }
+ return kMobileKeyBagDeviceIsUnlocked;
+}
+
+CF_RETURNS_RETAINED CFDictionaryRef
+MKBUserTypeDeviceMode(CFDictionaryRef options, CFErrorRef * error)
+{
+ return CFBridgingRetain(@{
+ (__bridge NSString *)kMKBDeviceModeKey : (__bridge NSString *)kMKBDeviceModeSingleUser,
+ });
+}
+
+int MKBForegroundUserSessionID( CFErrorRef * error)
+{
+ return kMobileKeyBagSuccess;
}
ACMContextRef
#import <sqlite3.h>
#import "mockaks.h"
+#import <TargetConditionals.h>
+
+#import <LocalAuthentication/LocalAuthentication.h>
+
#import "secdmock_db_version_10_5.h"
#import "secdmock_db_version_11_1.h"
}
#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
{
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);
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
+ 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_IPHONE || 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 */
--- /dev/null
+#import <Foundation/Foundation.h>
+#import <Security/SecKeychainPriv.h>
+#include <MobileKeyBag/MobileKeyBag.h>
+
+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;
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>application-identifier</key>
+ <string>com.apple.security.private.stashtester</string>
+ <key>com.apple.private.securityd.stash</key>
+ <true/>
+ <key>com.apple.keystore.device</key>
+ <true/>
+</dict>
+</plist>
/*
- * Copyright (c) 2002-2017 Apple Inc. All Rights Reserved.
+ * Copyright (c) 2002-2020 Apple Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
*/
__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
/*!
*/
__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
@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
/*!
*/
__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
/*!
*/
__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
*/
__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
/*
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
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)
*/
*/
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.
*/
__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
__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
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));
/*!
@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);
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
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.
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.
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".
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
@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.
@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.
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".
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".
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:
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)
@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".
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.
@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.
@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".
@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".
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.
@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.
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.
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.
@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.
@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.
@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
@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
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.
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.
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
__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.
@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.
@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".
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".
/*!
@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.
*/
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
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
@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
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
* 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.
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
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
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
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
* 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.
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
@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
@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.
@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.
@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
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).
@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.
@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.
@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.
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
* 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.
@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,
@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.
@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.
@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 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
__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
API_AVAILABLE(macos(10.15.4), ios(13.4), watchos(6.2), tvos(13.4));
/*!
- @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
+ @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 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.
+ * 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 SecPolicyCreateEscrowServiceIdKeySigning(void)
- API_AVAILABLE(macos(10.15.6), ios(13.6));
+SecPolicyRef SecPolicyCreateApplePayQRCodeEncryption(void)
+ API_AVAILABLE(macos(10.16), ios(14.0), watchos(7.0), tvos(14.0));
/*!
- @function SecPolicyCreatePCSEscrowServiceIdKeySigning
- @abstract Returns a policy object for verifying PCS Escrow Service ID keys.
+ @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 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.
+ * 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 SecPolicyCreatePCSEscrowServiceIdKeySigning(void)
- API_AVAILABLE(macos(10.15.6), ios(13.6));
+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));
/*
* Legacy functions (OS X only)
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. */
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;
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;
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 kSecPolicyCheckNameConstraints;
extern const CFStringRef kSecPolicyCheckNoNetworkAccess;
extern const CFStringRef kSecPolicyCheckNonEmptySubject;
+extern const CFStringRef kSecPolicyCheckNotCA;
extern const CFStringRef kSecPolicyCheckNotValidBefore;
extern const CFStringRef kSecPolicyCheckPinningRequired;
extern const CFStringRef kSecPolicyCheckPolicyConstraints;
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
*/
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);
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
*/
__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
*/
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.
@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));
+ API_UNAVAILABLE(macos, macCatalyst) API_AVAILABLE(ios(12.0), tvos(12.0), watchos(5.0));
/*!
@function SecTrustIncrementExceptionResetCount
@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));
+ __API_UNAVAILABLE(macos, macCatalyst) __API_AVAILABLE(ios(12.0), tvos(12.0), watchos(5.0));
#endif
#ifdef __BLOCKS__
/*
- * Copyright (c) 2002-2017 Apple Inc. All Rights Reserved.
+ * Copyright (c) 2002-2020 Apple Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
/*
@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.
+ kSecCTExceptionsHashAlgorithmKey takes a string indicating the hash algorithm. Currently only "sha256" is supported.
+ kSecCTExceptionsSPKIHashKey takes a data containing hash of a certificate's SubjectPublicKeyInfo.
*/
bool SecTrustStoreSetCTExceptions(CFStringRef applicationIdentifier, CFDictionaryRef exceptions, CFErrorRef *error);
@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:
+ kSecCARevocationHashAlgorithmKey takes a string indicating the hash algorithm. Currently only "sha256" is supported.
+ kSecCARevocationSPKIHashKey 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);
+
#if SEC_OS_OSX
/*
*/
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
*
*/
+/* 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 <libDER/DERItem.h>
+#endif /* _LIB_DER_H_ */
+
#ifndef _SECURITY_OIDS_H_
#define _SECURITY_OIDS_H_
__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 */
#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
}
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) {
/*
- * Copyright (c) 2017 Apple Inc. All Rights Reserved.
+ * Copyright (c) 2017-2020 Apple Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <Security/SecCertificateInternal.h>
#include <Security/SecItem.h>
#include <Security/SecInternal.h>
+#include <Security/SecTrustSettingsPriv.h>
#include <utilities/SecIOFormat.h>
#include <utilities/SecCFError.h>
#include "trust/trustd/SecPolicyServer.h"
#include "trust/trustd/SecCertificateServer.h"
#include "trust/trustd/SecRevocationServer.h"
+#include "trust/trustd/SecTrustStoreServer.h"
// MARK: -
// MARK: SecCertificateVC
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;
*stop = true;
}
});
-
+
errOut:
CFReleaseSafe(keySizes);
CFReleaseSafe(rsaSize);
/* 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. */
/* 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;
}
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;
/*
- * Copyright (c) 2017 Apple Inc. All Rights Reserved.
+ * Copyright (c) 2017-2020 Apple Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
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);
const SecCertificateSourceRef kSecSystemAnchorSource = &_kSecSystemAnchorSource;
-
-#if TARGET_OS_IPHONE
// MARK: -
// MARK: SecUserAnchorSource
/********************************************************
};
const SecCertificateSourceRef kSecUserAnchorSource = &_kSecUserAnchorSource;
-#endif
// MARK: -
// MARK: SecMemoryCertificateSource
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;
}
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);
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 = {
/* SecSystemAnchorSource */
extern const SecCertificateSourceRef kSecSystemAnchorSource;
-#if TARGET_OS_IPHONE
/* SecUserAnchorSource */
extern const SecCertificateSourceRef kSecUserAnchorSource;
-#endif
/* SecCAIssuerCertificateSource */
extern const SecCertificateSourceRef kSecCAIssuerSource;
/* 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;
+}
SecCertificateRef SecOCSPResponseCopySigner(SecOCSPResponseRef this,
SecCertificateRef issuerPath);
+bool SecOCSPResponseIsWeakHash(SecOCSPResponseRef response);
+
__END_DECLS
#endif /* !_SECURITY_SECOCSPRESPONSE_H_ */
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) }];
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)}];
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)}];
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)}];
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)}];
CFDictionaryRef _Nullable SecPinningDbCopyMatching(CFDictionaryRef query) {
@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);
}
}
/*
- * Copyright (c) 2008-2018 Apple Inc. All Rights Reserved.
+ * Copyright (c) 2008-2020 Apple Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
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,
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.
*/
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.
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);
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--;
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:
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). */
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;
}
}
/* 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)) {
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);
}
}
+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);
+ }
+}
+
void SecPolicyServerInitialize(void) {
gSecPolicyLeafCallbacks = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks, NULL);
*/
#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 */
/* 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; }
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);
/* 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
+ SecCertificateSourceContains(kSecUserAnchorSource, cert)) {
+ pvc->result = kSecTrustResultProceed;
+ }
+#if TARGET_OS_OSX
if (SecPathBuilderIsAnchorSource(pvc->builder, kSecLegacyAnchorSource) &&
- SecCertificateSourceContains(kSecLegacyAnchorSource, cert))
-#endif
- {
+ SecCertificateSourceContains(kSecLegacyAnchorSource, cert)) {
pvc->result = kSecTrustResultProceed;
}
+#endif
}
}
}
}
}
-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;
}
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:
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 */
/* 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. */
if (ctp != kSecPathCTRequiredOverridable) {
/* Normally kSecPolicyCheckCTRequired is recoverable */
}
}
CFReleaseNull(otaref);
+ CFReleaseNull(trustedLogs);
}
/* "Deep" copy the details array */
/*
- * Copyright (c) 2016-2019 Apple Inc. All Rights Reserved.
+ * Copyright (c) 2016-2020 Apple Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
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
/* 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"
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);
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);
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);
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);
}
/* Prefer a in-process setting for the update server, as used in testing */
CFTypeRef value = CFPreferencesCopyAppValue(kUpdateServerKey, kSecPrefsDomain);
if (!value) {
- value = (CFStringRef)CFPreferencesCopyValue(kUpdateServerKey, kSecPrefsDomain, kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
+ value = CFPreferencesCopyValue(kUpdateServerKey, kSecPrefsDomain, kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
+ }
+ CFStringRef server = NULL;
+ if (isString(value)) {
+ server = (CFStringRef)value;
+ } else {
+ CFReleaseNull(value);
+ server = CFRetainSafe(SecRevocationDbGetDefaultServer());
}
- CFStringRef server = (isString(value)) ? (CFStringRef)value : CFRetainSafe(SecRevocationDbGetDefaultServer());
return server;
}
==============================================================================
*/
+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.
*/
// determine which server to query
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
- // 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;
}
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
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);
}
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");
}
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) {
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;
__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<issuerCount && groupId < 0; issuerIX++) {
CFErrorRef error = NULL;
CFDataRef issuerHash = NULL;
- require(dbc && certificate && issuer, errOut);
+ require_quiet(dbc && certificate && issuer, errOut);
require(issuerHash = SecCertificateCopySHA256Digest(issuer), errOut);
/* Check for the result in the cache. */
/* Return the update source as a retained CFStringRef.
If the value cannot be obtained, NULL is returned.
*/
-CFStringRef SecRevocationDbCopyUpdateSource(void) {
+CF_RETURNS_RETAINED CFStringRef SecRevocationDbCopyUpdateSource(void) {
__block CFStringRef result = NULL;
SecRevocationDbWith(^(SecRevocationDbRef db) {
(void) SecRevocationDbPerformRead(db, NULL, ^bool(SecRevocationDbConnectionRef dbc, CFErrorRef *blockError) {
#include <CoreFoundation/CFDate.h>
#include <CoreFoundation/CFDictionary.h>
#include <CoreFoundation/CFString.h>
+#include <CoreFoundation/CFError.h>
#include <dispatch/dispatch.h>
#include <Security/SecBase.h>
*/
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.
@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
#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_ */
(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) {
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];
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 */
@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;
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;
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 {
});
if (!self.backgroundSession) {
- [self createSession:updateQueue forServer:server];
+ [self createSessions:updateQueue forServer:server];
} else {
ValidDelegate *delegate = (ValidDelegate *)[self.backgroundSession delegate];
delegate.currentUpdateServer = [server copy];
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
SecORVCConsumeOCSPResponse(orvc, ocspResponse, self.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) --
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.
* 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);
if (localError) {
if (error) {
*error = localError;
+ } else {
+ CFReleaseNull(localError);
}
secerror("Permanent storage for the exceptions epoch is unavailable.");
return status;
* 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;
+ CFReleaseNull(localError);
}
- if (error && localError) {
- *error = localError;
+ if (localError) {
+ if (error) {
+ *error = localError;
+ } else {
+ CFReleaseNull(localError);
+ }
}
secinfo("trust", "exceptionResetCount: %llu (%s)", exceptionResetCount, error ? (*error ? "Error" : "OK") : "N/A");
return exceptionResetCount;
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);
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);
}
TrustAnalyticsBuilder *SecPathBuilderGetAnalyticsData(SecPathBuilderRef builder)
{
+ if (!builder) {
+ return NULL;
+ }
return builder->analyticsData;
}
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) {
__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) {
dispatch_semaphore_wait(done, DISPATCH_TIME_FOREVER);
dispatch_release(done);
dispatch_release_null(queue);
+ CFReleaseNull(audit_token);
return result;
}
typedef struct {
uint64_t start_time;
bool suspected_mitm;
+ bool ca_fail_eku_check;
// Certificate Transparency
TA_SCTSource sct_sources;
uint32_t number_scts;
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;
static dispatch_once_t kSecTrustStoreUserOnce;
static SecTrustStoreRef kSecTrustStoreUser = 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 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 countAllSQL[] = "SELECT COUNT(*) FROM tsettings";
+#endif
#define kSecTrustStoreName CFSTR("TrustStore")
#define kSecTrustStoreDbExtension CFSTR("sqlite3")
// MARK: -
// MARK: Trust store functions
-
+#if TARGET_OS_IPHONE
static int sec_create_path(const char *path)
{
char pathbuf[PATH_MAX];
errOutNotLocked:
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;
+ kSecTrustStoreUser = ts;
+}
+
+SecTrustStoreRef SecTrustStoreForDomainName(CFStringRef domainName, CFErrorRef *error) {
+ if (CFEqual(CFSTR("user"), domainName)) {
+ dispatch_once(&kSecTrustStoreUserOnce, ^{ SecTrustStoreInitUser(); });
+ return kSecTrustStoreUser;
+ } else {
+ SecError(errSecParam, error, CFSTR("unknown domain: %@"), domainName);
+ return NULL;
+ }
+}
+
+bool _SecTrustStoreSetTrustSettings(SecTrustStoreRef ts,
+ SecCertificateRef certificate,
+ CFTypeRef trustSettingsDictOrArray, CFErrorRef *error) {
+ return SecError(errSecUnimplemented, error, CFSTR("trust store is not modifiable on this platform"));
+}
+
+bool SecTrustStoreRemoveCertificateWithDigest(SecTrustStoreRef ts, CFDataRef digest, CFErrorRef *error) {
+ return SecError(errSecUnimplemented, error, CFSTR("trust store is not modifiable on this platform"));
+}
+
+bool _SecTrustStoreRemoveAll(SecTrustStoreRef ts, CFErrorRef *error) {
+ return SecError(errSecUnimplemented, error, CFSTR("trust store is not modifiable on this platform"));
+}
+
+CFArrayRef SecTrustStoreCopyParents(SecTrustStoreRef ts,
+ SecCertificateRef certificate, CFErrorRef *error) {
+ CFArrayRef parents = NULL;
+ return parents;
+}
+
+bool SecTrustStoreContainsCertificateWithDigest(SecTrustStoreRef ts, CFDataRef digest, bool *contains, CFErrorRef *error) {
+ if (contains) {
+ *contains = false;
+ }
+ return true;
+}
+
+bool _SecTrustStoreCopyUsageConstraints(SecTrustStoreRef ts, CFDataRef digest, CFArrayRef *usageConstraints, CFErrorRef *error) {
+ return true;
+}
+
+bool _SecTrustStoreCopyAll(SecTrustStoreRef ts, CFArrayRef *trustStoreContents, CFErrorRef *error) {
+ CFMutableArrayRef CertsAndSettings = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ if (CertsAndSettings) {
+ *trustStoreContents = CertsAndSettings;
+ }
+ return true;
+}
+#endif
/*
- * 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,
* 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@
*/
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);
+
__END_DECLS
#endif /* !_SECURITY_SECTRUSTSTORESERVER_H_ */
/*
- * Copyright (c) 2018 Apple Inc. All Rights Reserved.
+ * Copyright (c) 2018-2020 Apple Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#import "OTATrustUtilities.h"
#include "SecTrustStoreServer.h"
+//
+// MARK : CT Exceptions
+//
typedef bool(*exceptionsArrayValueChecker)(id _Nonnull obj);
static bool checkDomainsValuesCompliance(id _Nonnull obj) {
int check = 0;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
- /* initialize gHashCTExceptions cache */
+ /* initialize gHasCTExceptions cache */
NSError *read_error = nil;
NSDictionary <NSString*,NSDictionary*> *allExceptions = readExceptionsFromDisk(&read_error);
if (!allExceptions || [allExceptions count] == 0) {
status = notify_check(notify_token, NULL);
}
if (status != NOTIFY_STATUS_OK) {
- secerror("failed to establish notification for CT exceptions: %ud", status);
+ secerror("failed to establish notification for CT exceptions: %u", status);
notify_cancel(notify_token);
notify_token = 0;
}
return NULL;
}
}
+
+//
+// MARK: CA Revocation Additions
+//
+typedef bool(*additionsArrayValueChecker)(id _Nonnull obj);
+
+static bool checkCARevocationValuesCompliance(id _Nonnull obj) {
+ if (![obj isKindOfClass:[NSDictionary class]]) {
+ return false;
+ }
+ if (2 != [(NSDictionary*)obj count]) {
+ return false;
+ }
+ if (nil == ((NSDictionary*)obj)[(__bridge NSString*)kSecCARevocationHashAlgorithmKey] ||
+ nil == ((NSDictionary*)obj)[(__bridge NSString*)kSecCARevocationSPKIHashKey]) {
+ return false;
+ }
+ if (![((NSDictionary*)obj)[(__bridge NSString*)kSecCARevocationHashAlgorithmKey] isKindOfClass:[NSString class]] ||
+ ![((NSDictionary*)obj)[(__bridge NSString*)kSecCARevocationSPKIHashKey] isKindOfClass:[NSData class]]) {
+ return false;
+ }
+ if (![((NSDictionary*)obj)[(__bridge NSString*)kSecCARevocationHashAlgorithmKey] isEqualToString:@"sha256"]) {
+ return false;
+ }
+ return true;
+}
+
+static bool checkCARevocationValues(NSString *key, id value, additionsArrayValueChecker checker, CFErrorRef *error) {
+ if (![value isKindOfClass:[NSArray class]]) {
+ return SecError(errSecParam, error, CFSTR("value for %@ is not an array in revocation additions dictionary"), key);
+ }
+
+ __block bool result = true;
+ [(NSArray*)value enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+ if (!checker(obj)) {
+ result = SecError(errSecParam, error, CFSTR("value %lu for %@ is not the expected type"), (unsigned long)idx, key);
+ *stop = true;
+ }
+ }];
+ return result;
+}
+
+static bool checkInputAdditionsAndSetAppAdditions(NSDictionary *inAdditions, NSMutableDictionary *appAdditions, CFErrorRef *error) {
+ __block bool result = true;
+ [inAdditions enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
+ if ([key isEqualToString:(__bridge NSString*)kSecCARevocationAdditionsKey]) {
+ if (!checkCARevocationValues(key, obj, checkCARevocationValuesCompliance, 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 *CARevocationFileURL() {
+ return CFBridgingRelease(SecCopyURLForFileInSystemKeychainDirectory(CFSTR("CARevocation.plist")));
+}
+
+static NSDictionary <NSString*,NSDictionary*> *readRevocationAdditionsFromDisk(NSError **error) {
+ secdebug("ocsp", "reading CA revocation additions from disk");
+ NSDictionary <NSString*,NSDictionary*> *allAdditions = [NSDictionary dictionaryWithContentsOfURL:CARevocationFileURL()
+ error:error];
+ return allAdditions;
+}
+
+bool _SecTrustStoreSetCARevocationAdditions(CFStringRef appID, CFDictionaryRef additions, CFErrorRef *error) {
+ if (!SecOTAPKIIsSystemTrustd()) {
+ secerror("Unable to write CA revocation additions from user agent");
+ return SecError(errSecWrPerm, error, CFSTR("Unable to write CA revocation additions from user agent"));
+ }
+
+ if (!appID) {
+ secerror("application-identifier required to set CA revocation additions");
+ return SecError(errSecParam, error, CFSTR("application-identifier required to set CA revocation additions"));
+ }
+
+ @autoreleasepool {
+ NSError *nserror = nil;
+ NSMutableDictionary *allAdditions = [readRevocationAdditionsFromDisk(&nserror) mutableCopy];
+ NSMutableDictionary *appAdditions = NULL;
+ if (allAdditions && allAdditions[(__bridge NSString*)appID]) {
+ appAdditions = [allAdditions[(__bridge NSString*)appID] mutableCopy];
+ } else {
+ appAdditions = [NSMutableDictionary dictionary];
+ if (!allAdditions) {
+ allAdditions = [NSMutableDictionary dictionary];
+ }
+ }
+
+ if (additions && (CFDictionaryGetCount(additions) > 0)) {
+ NSDictionary *inAdditions = (__bridge NSDictionary*)additions;
+ if (!checkInputAdditionsAndSetAppAdditions(inAdditions, appAdditions, error)) {
+ secerror("input additions have error: %@", error ? *error : nil);
+ return false;
+ }
+ }
+
+ if (!additions || [appAdditions count] == 0) {
+ [allAdditions removeObjectForKey:(__bridge NSString*)appID];
+ } else {
+ allAdditions[(__bridge NSString*)appID] = appAdditions;
+ }
+
+ if (![allAdditions writeToURL:CARevocationFileURL() error:&nserror]) {
+ secerror("failed to write CA revocation additions: %@", nserror);
+ if (error) {
+ *error = CFRetainSafe((__bridge CFErrorRef)nserror);
+ }
+ return false;
+ }
+ secnotice("ocsp", "wrote %lu CA revocation additions", (unsigned long)[allAdditions count]);
+ atomic_store(&gHasCARevocationAdditions, [allAdditions count] != 0);
+ notify_post(kSecCARevocationChanged);
+ return true;
+ }
+}
+
+CFDictionaryRef _SecTrustStoreCopyCARevocationAdditions(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 gHasCARevocation cache */
+ NSError *read_error = nil;
+ NSDictionary <NSString*,NSDictionary*> *allAdditions = readRevocationAdditionsFromDisk(&read_error);
+ if (!allAdditions || [allAdditions count] == 0) {
+ secnotice("ocsp", "skipping further reads. no CA revocation additions found: %@", read_error);
+ atomic_store(&gHasCARevocationAdditions, false);
+ } else {
+ secnotice("ocsp", "have CA revocation additions. will need to read.");
+ atomic_store(&gHasCARevocationAdditions, true);
+ }
+
+ /* read-only trustds register for notfications from the read-write trustd */
+ if (!SecOTAPKIIsSystemTrustd()) {
+ uint32_t status = notify_register_check(kSecCARevocationChanged, ¬ify_token);
+ if (status == NOTIFY_STATUS_OK) {
+ status = notify_check(notify_token, NULL);
+ }
+ if (status != NOTIFY_STATUS_OK) {
+ secerror("failed to establish notification for CA revocation additions: %u", status);
+ notify_cancel(notify_token);
+ notify_token = 0;
+ }
+ }
+ });
+
+ /* Read the negative cached value as to whether there are any revocation additions to read */
+ if (!SecOTAPKIIsSystemTrustd()) {
+ /* Check whether we got a notification. If we didn't, and there are no additions 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(&gHasCARevocationAdditions)) {
+ return NULL;
+ }
+ } else if (!atomic_load(&gHasCARevocationAdditions)) {
+ return NULL;
+ }
+
+ /* We need to read the exceptions from disk */
+ NSError *read_error = nil;
+ NSDictionary <NSString*,NSDictionary*> *allAdditions = readRevocationAdditionsFromDisk(&read_error);
+ if (!allAdditions || [allAdditions count] == 0) {
+ secnotice("ocsp", "skipping further reads. no CA revocation additions found: %@", read_error);
+ atomic_store(&gHasCARevocationAdditions, false);
+ return NULL;
+ }
+
+ /* If the caller specified an appID, return only the exceptions for that appID */
+ if (appID) {
+ return CFBridgingRetain(allAdditions[(__bridge NSString*)appID]);
+ }
+
+ /* Otherwise, combine all the revocation additions into one array */
+ NSMutableArray *caAdditions = [NSMutableArray array];
+ [allAdditions enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull __unused key, NSDictionary * _Nonnull appAdditions,
+ BOOL * _Nonnull __unused stop) {
+ if (appAdditions[(__bridge NSString*)kSecCARevocationAdditionsKey] &&
+ checkCARevocationValues((__bridge NSString*)kSecCARevocationAdditionsKey,
+ appAdditions[(__bridge NSString*)kSecCARevocationAdditionsKey],
+ checkCARevocationValuesCompliance, error)) {
+ [caAdditions addObjectsFromArray:appAdditions[(__bridge NSString*)kSecCARevocationAdditionsKey]];
+ }
+ }];
+ NSMutableDictionary *additions = [NSMutableDictionary dictionaryWithCapacity:2];
+ 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;
+ }
+}
<string>com.apple.MobileAsset.PKITrustSupplementals</string>
<string>com.apple.MobileAsset.SecExperimentAssets</string>
</array>
+ <key>com.apple.private.security.storage.trustd</key>
+ <true/>
+ <key>com.apple.private.security.storage.trustd-private</key>
+ <true/>
+ <key>com.apple.private.security.storage.SFAnalytics</key>
+ <true/>
<key>seatbelt-profiles</key>
<array>
<string>trustd</string>
(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/"))
(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"))
(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"))
+
(allow network-outbound)
(allow system-socket)
<string>com.apple.MobileAsset.PKITrustSupplementals</string>
<string>com.apple.MobileAsset.SecExperimentAssets</string>
</array>
+ <key>com.apple.private.security.storage.trustd</key>
+ <true/>
+ <key>com.apple.private.security.storage.trustd-private</key>
+ <true/>
+ <key>com.apple.private.security.storage.SFAnalytics</key>
+ <true/>
</dict>
</plist>
/*
- * Copyright (c) 2017-2018 Apple Inc. All Rights Reserved.
+ * Copyright (c) 2017-2020 Apple Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
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);
return false;
}
+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;
+}
+
#if TARGET_OS_IPHONE
static bool SecXPCTrustGetExceptionResetCount(SecurityClient * __unused client, xpc_object_t event, xpc_object_t reply, CFErrorRef *error) {
uint64_t exceptionResetCount = SecTrustServerGetExceptionResetCount(error);
}
#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);
typedef struct {
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;
};
static struct trustd_operations trustd_ops = {
.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 },
};
static void trustd_xpc_dictionary_handler(const xpc_connection_t connection, xpc_object_t event) {
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;
default:
break;
}
/*
- * Copyright (c) 2018 Apple Inc. All Rights Reserved.
+ * Copyright (c) 2018-2020 Apple Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
.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,
};
#endif
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
-
-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
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
// 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*] =
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*] =
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*] =
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] =
// 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
+++ /dev/null
-ARCHS[sdk=macosx*] = $(ARCHS_STANDARD_32_64_BIT)
+++ /dev/null
-
-// 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
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
OTHER_SWIFT_FLAGS = $(OCTAGON_FLAG_$(OCTAGON_ON))
SWIFT_VERSION=5
+SWIFT_TREAT_WARNINGS_AS_ERRORS = YES
+
+TEST_BUILD_STYLE = _APPLEINTERNAL
+SYSTEM_FRAMEWORK_SEARCH_PATHS = $(inherited) ${PLATFORM_DIR}/Developer/AppleInternal/Library/Frameworks
if test -d "${a}/${framework}" ; then
dst="${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}"
- mkdir -p "{dst}" || { echo "mkdir failed with: $?" ; exit 1; }
+ mkdir -p "${dst}" || { echo "mkdir failed with: $?" ; exit 1; }
ditto "${a}/${framework}" "${dst}/${framework}" || { echo "ditto failed with: $?" ; exit 1; }
+ find "${dst}/${framework}" \( -name Headers -o -name Modules -o -name '*.tbd' \) -delete
xcrun codesign -s - -f "${dst}/${framework}" || { echo "codesign failed with: $?" ; exit 1; }
found=yes