Skip to content

Commit

Permalink
Security-59306.11.20
Browse files Browse the repository at this point in the history
Imported from Security-59306.11.20.tar.gz
  • Loading branch information
AppleOSSDistributions committed Oct 6, 2021
1 parent 1e21942 commit 5366a77
Show file tree
Hide file tree
Showing 2,896 changed files with 442,063 additions and 148,837 deletions.
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,12 @@
cscope.out
.DS_Store
xcuserdata
._*
build

# Swift Package Manager noise
.build
Package.resolved

# Not adding the SPM-generated .xcodeproj to the repo
keychain/Trieste/OctagonTriesteTests/OctagonTrieste.xcodeproj
33 changes: 33 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
indentation: 4
disabled_rules:
- file_length
- function_body_length
- function_parameter_count
- identifier_name
- line_length
- todo
- type_body_length
opt_in_rules:
- anyobject_protocol
- array_init
- attributes
#- closure_end_indentation ## commented as --format removes option
- closure_spacing
- conditional_returns_on_newline
- empty_count
- explicit_init
- implicit_return
- joined_default_parameter
#- literal_expression_end_indentation ## commented as --format removes option
- operator_usage_whitespace
- redundant_nil_coalescing
- redundant_type_annotation
- sorted_imports
- trailing_closure
- unneeded_parentheses_in_closure_argument
- untyped_error_in_catch
trailing_comma:
mandatory_comma: true
excluded:
- keychain/trust/cuttlefish/
- keychain/Trieste/OctagonTriesteTests/.build
55 changes: 55 additions & 0 deletions Analytics/Clients/LocalKeychainAnalytics.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#ifndef LocalKeychainAnalytics_h
#define LocalKeychainAnalytics_h

#include <CoreFoundation/CoreFoundation.h>

typedef enum {
LKAKeychainUpgradeOutcomeSuccess,
LKAKeychainUpgradeOutcomeUnknownFailure,
LKAKeychainUpgradeOutcomeLocked,
LKAKeychainUpgradeOutcomeInternal,
LKAKeychainUpgradeOutcomeNewDb,
LKAKeychainUpgradeOutcomeObsoleteDb,
LKAKeychainUpgradeOutcomeNoSchema,
LKAKeychainUpgradeOutcomeIndices,
LKAKeychainUpgradeOutcomePhase1AlterTables,
LKAKeychainUpgradeOutcomePhase1DropIndices,
LKAKeychainUpgradeOutcomePhase1CreateSchema,
LKAKeychainUpgradeOutcomePhase1Items,
LKAKeychainUpgradeOutcomePhase1NonItems,
LKAKeychainUpgradeOutcomePhase1DropOld,
LKAKeychainUpgradeOutcomePhase2,
} LKAKeychainUpgradeOutcome;

typedef enum {
LKAKeychainBackupTypeNeither,
LKAKeychainBackupTypeBag,
LKAKeychainBackupTypeCode,
LKAKeychainBackupTypeBagAndCode,
LKAKeychainBackupTypeEMCS,
} LKAKeychainBackupType;

void LKAReportKeychainUpgradeOutcome(int fromversion, int toversion, LKAKeychainUpgradeOutcome outcome);
void LKAReportKeychainUpgradeOutcomeWithError(int fromversion, int toversion, LKAKeychainUpgradeOutcome outcome, CFErrorRef error);

void LKABackupReportStart(bool hasKeybag, bool hasPasscode, bool isEMCS);
void LKABackupReportEnd(bool hasBackup, CFErrorRef error);

#if __OBJC2__

#import <Foundation/Foundation.h>
#import <Security/SFAnalytics.h>

typedef NSString* LKAnalyticsFailableEvent NS_STRING_ENUM;
typedef NSString* LKAnalyticsMetric NS_STRING_ENUM;

extern LKAnalyticsFailableEvent const LKAEventUpgrade;

@interface LocalKeychainAnalytics : SFAnalytics

- (void)reportKeychainUpgradeFrom:(int)oldVersion to:(int)newVersion outcome:(LKAKeychainUpgradeOutcome)result error:(NSError*)error;

@end

#endif // OBJC2
#endif // LocalKeychainAnalytics_h
205 changes: 205 additions & 0 deletions Analytics/Clients/LocalKeychainAnalytics.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
#include "LocalKeychainAnalytics.h"

#import "Security/SFAnalyticsDefines.h"

#include <sys/stat.h>
#include <notify.h>

#include <utilities/SecFileLocations.h>
#include <utilities/SecAKSWrappers.h>

@interface LKAUpgradeOutcomeReport : NSObject
@property LKAKeychainUpgradeOutcome outcome;
@property NSDictionary* attributes;
- (instancetype) initWithOutcome:(LKAKeychainUpgradeOutcome)outcome attributes:(NSDictionary*)attributes;
@end

@implementation LKAUpgradeOutcomeReport
- (instancetype) initWithOutcome:(LKAKeychainUpgradeOutcome)outcome attributes:(NSDictionary*)attributes {
if (self = [super init]) {
self.outcome = outcome;
self.attributes = attributes;
}
return self;
}
@end

// Approved event types
// rdar://problem/41745059 SFAnalytics: collect keychain upgrade outcome information
LKAnalyticsFailableEvent const LKAEventUpgrade = (LKAnalyticsFailableEvent)@"LKAEventUpgrade";

// <rdar://problem/52038208> SFAnalytics: collect keychain backup success rates and duration
LKAnalyticsFailableEvent const LKAEventBackup = (LKAnalyticsFailableEvent)@"LKAEventBackup";
LKAnalyticsMetric const LKAMetricBackupDuration = (LKAnalyticsMetric)@"LKAMetricBackupDuration";

// Internal consts
NSString* const LKAOldSchemaKey = @"oldschema";
NSString* const LKANewSchemaKey = @"newschema";
NSString* const LKAUpgradeOutcomeKey = @"upgradeoutcome";
NSString* const LKABackupLastSuccessDate = @"backupLastSuccess";

@implementation LocalKeychainAnalytics {
BOOL _probablyInClassD;
NSMutableArray<LKAUpgradeOutcomeReport*>* _pendingReports;
dispatch_queue_t _queue;
int _notificationToken;
NSDate* _backupStartTime;
LKAKeychainBackupType _backupType;
}

- (instancetype __nullable)init {
if (self = [super init]) {
_probablyInClassD = YES;
_pendingReports = [NSMutableArray<LKAUpgradeOutcomeReport*> new];
_queue = dispatch_queue_create("LKADataQueue", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL);
_notificationToken = NOTIFY_TOKEN_INVALID;
}
return self;
}

+ (NSString*)databasePath {
return [self defaultAnalyticsDatabasePath:@"localkeychain"];
}

// MARK: Client-specific functionality

- (BOOL)canPersistMetrics {
@synchronized(self) {
if (!_probablyInClassD) {
return YES;
}
}

// If this gets busy we should start caching if AKS tells us no
bool hasBeenUnlocked = false;
if (!SecAKSGetHasBeenUnlocked(&hasBeenUnlocked, NULL) || !hasBeenUnlocked) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
notify_register_dispatch(kUserKeybagStateChangeNotification, &self->_notificationToken, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(int token) {
// For side effect of processing pending messages if out of class D
[self canPersistMetrics];
});
});
return NO;
}

@synchronized(self) {
_probablyInClassD = NO;
if (_notificationToken != NOTIFY_TOKEN_INVALID) {
notify_cancel(_notificationToken);
}
}

[self processPendingMessages];
return YES;
}

- (void)processPendingMessages {
dispatch_async(_queue, ^{
for (LKAUpgradeOutcomeReport* report in self->_pendingReports) {
[self reportKeychainUpgradeOutcome:report.outcome attributes:report.attributes];
}
});
}

- (void)reportKeychainUpgradeFrom:(int)oldVersion to:(int)newVersion outcome:(LKAKeychainUpgradeOutcome)outcome error:(NSError*)error {

NSMutableDictionary* attributes = [@{LKAOldSchemaKey : @(oldVersion),
LKANewSchemaKey : @(newVersion),
LKAUpgradeOutcomeKey : @(outcome),
} mutableCopy];
if (error) {
[attributes addEntriesFromDictionary:@{SFAnalyticsAttributeErrorDomain : error.domain,
SFAnalyticsAttributeErrorCode : @(error.code)}];
}

if (![self canPersistMetrics]) {
dispatch_async(_queue, ^{
[self->_pendingReports addObject:[[LKAUpgradeOutcomeReport alloc] initWithOutcome:outcome attributes:attributes]];
});
} else {
[self reportKeychainUpgradeOutcome:outcome attributes:attributes];
}
}

- (void)reportKeychainUpgradeOutcome:(LKAKeychainUpgradeOutcome)outcome attributes:(NSDictionary*)attributes {
if (outcome == LKAKeychainUpgradeOutcomeSuccess) {
[self logSuccessForEventNamed:LKAEventUpgrade];
} else {
// I could try and pick out the recoverable errors but I think we're good treating these all the same
[self logHardFailureForEventNamed:LKAEventUpgrade withAttributes:attributes];
}
}

- (void)reportKeychainBackupStartWithType:(LKAKeychainBackupType)type {
_backupStartTime = [NSDate date];
_backupType = type;
}

// Don't attempt to add to pending reports, this should not happen in Class D
- (void)reportKeychainBackupEnd:(bool)hasBackup error:(NSError*)error {
NSDate* backupEndTime = [NSDate date];

// Get duration in milliseconds rounded to 100ms.
NSInteger backupDuration = (int)(([backupEndTime timeIntervalSinceDate:_backupStartTime] + 0.05) * 10) * 100;

// Generate statistics on backup duration separately so we know what the situation is in the field even when succeeding
[self logMetric:@(backupDuration) withName:LKAMetricBackupDuration];

if (hasBackup) {
[self setDateProperty:backupEndTime forKey:LKABackupLastSuccessDate];
[self logSuccessForEventNamed:LKAEventBackup timestampBucket:SFAnalyticsTimestampBucketHour];
} else {
NSInteger daysSinceSuccess = [SFAnalytics fuzzyDaysSinceDate:[self datePropertyForKey:LKABackupLastSuccessDate]];
[self logResultForEvent:LKAEventBackup
hardFailure:YES
result:error
withAttributes:@{@"daysSinceSuccess" : @(daysSinceSuccess),
@"duration" : @(backupDuration),
@"type" : @(_backupType),
}
timestampBucket:SFAnalyticsTimestampBucketHour];
}
}

@end

// MARK: C Bridging

void LKAReportKeychainUpgradeOutcome(int fromversion, int toversion, LKAKeychainUpgradeOutcome outcome) {
@autoreleasepool {
[[LocalKeychainAnalytics logger] reportKeychainUpgradeFrom:fromversion to:toversion outcome:outcome error:NULL];
}
}

void LKAReportKeychainUpgradeOutcomeWithError(int fromversion, int toversion, LKAKeychainUpgradeOutcome outcome, CFErrorRef error) {
@autoreleasepool {
[[LocalKeychainAnalytics logger] reportKeychainUpgradeFrom:fromversion to:toversion outcome:outcome error:(__bridge NSError*)error];
}
}

void LKABackupReportStart(bool hasKeybag, bool hasPasscode, bool isEMCS) {
LKAKeychainBackupType type;
if (isEMCS) {
type = LKAKeychainBackupTypeEMCS;
} else if (hasKeybag && hasPasscode) {
type = LKAKeychainBackupTypeBagAndCode;
} else if (hasKeybag) {
type = LKAKeychainBackupTypeBag;
} else if (hasPasscode) {
type = LKAKeychainBackupTypeCode;
} else {
type = LKAKeychainBackupTypeNeither;
}

// Keep track of backup type and start time
@autoreleasepool {
[[LocalKeychainAnalytics logger] reportKeychainBackupStartWithType:type];
}
}

void LKABackupReportEnd(bool hasBackup, CFErrorRef error) {
@autoreleasepool {
[[LocalKeychainAnalytics logger] reportKeychainBackupEnd:hasBackup error:(__bridge NSError*)error];
}
}
51 changes: 51 additions & 0 deletions Analytics/Clients/SOSAnalytics.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* 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 SOSAnalytics_h
#define SOSAnalytics_h

#import <Foundation/Foundation.h>
#import "Analytics/SFAnalytics.h"

extern NSString* const CKDKVSPerformanceCountersSampler;

@protocol CKDKVSPerformanceCounter <NSObject>
@end
typedef NSString<CKDKVSPerformanceCounter> CKDKVSPerformanceCounter;
extern CKDKVSPerformanceCounter* const CKDKVSPerfCounterSynchronize;
extern CKDKVSPerformanceCounter* const CKDKVSPerfCounterSynchronizeWithCompletionHandler;
extern CKDKVSPerformanceCounter* const CKDKVSPerfCounterIncomingMessages;
extern CKDKVSPerformanceCounter* const CKDKVSPerfCounterOutgoingMessages;
extern CKDKVSPerformanceCounter* const CKDKVSPerfCounterTotalWaitTimeSynchronize;
extern CKDKVSPerformanceCounter* const CKDKVSPerfCounterLongestWaitTimeSynchronize;
extern CKDKVSPerformanceCounter* const CKDKVSPerfCounterSynchronizeFailures;

@interface SOSAnalytics : SFAnalytics

+ (instancetype)logger;

@end

#endif
#endif
Loading

0 comments on commit 5366a77

Please sign in to comment.