diff --git a/.gitignore b/.gitignore index dfd386e40..7af1223e4 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 000000000..43c689e8c --- /dev/null +++ b/.swiftlint.yml @@ -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 diff --git a/Analytics/Clients/LocalKeychainAnalytics.h b/Analytics/Clients/LocalKeychainAnalytics.h new file mode 100644 index 000000000..f33440930 --- /dev/null +++ b/Analytics/Clients/LocalKeychainAnalytics.h @@ -0,0 +1,55 @@ +#ifndef LocalKeychainAnalytics_h +#define LocalKeychainAnalytics_h + +#include + +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 +#import + +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 diff --git a/Analytics/Clients/LocalKeychainAnalytics.m b/Analytics/Clients/LocalKeychainAnalytics.m new file mode 100644 index 000000000..8d97a540b --- /dev/null +++ b/Analytics/Clients/LocalKeychainAnalytics.m @@ -0,0 +1,205 @@ +#include "LocalKeychainAnalytics.h" + +#import "Security/SFAnalyticsDefines.h" + +#include +#include + +#include +#include + +@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"; + +// 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* _pendingReports; + dispatch_queue_t _queue; + int _notificationToken; + NSDate* _backupStartTime; + LKAKeychainBackupType _backupType; +} + +- (instancetype __nullable)init { + if (self = [super init]) { + _probablyInClassD = YES; + _pendingReports = [NSMutableArray 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]; + } +} diff --git a/Analytics/Clients/SOSAnalytics.h b/Analytics/Clients/SOSAnalytics.h new file mode 100644 index 000000000..53e813129 --- /dev/null +++ b/Analytics/Clients/SOSAnalytics.h @@ -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 +#import "Analytics/SFAnalytics.h" + +extern NSString* const CKDKVSPerformanceCountersSampler; + +@protocol CKDKVSPerformanceCounter +@end +typedef NSString 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 diff --git a/Analytics/Clients/SOSAnalytics.m b/Analytics/Clients/SOSAnalytics.m new file mode 100644 index 000000000..4fa217c7c --- /dev/null +++ b/Analytics/Clients/SOSAnalytics.m @@ -0,0 +1,67 @@ +/* + * 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 "SOSAnalytics.h" +#include +#include + +NSString* const CKDKVSPerformanceCountersSampler = @"CKDKVSPerformanceCounterSampler"; + +CKDKVSPerformanceCounter* const CKDKVSPerfCounterSynchronize = (CKDKVSPerformanceCounter*)@"CKDKVS-synchronize"; +CKDKVSPerformanceCounter* const CKDKVSPerfCounterSynchronizeWithCompletionHandler = (CKDKVSPerformanceCounter*)@"CKDKVS-synchronizeWithCompletionHandler"; +CKDKVSPerformanceCounter* const CKDKVSPerfCounterIncomingMessages = (CKDKVSPerformanceCounter*)@"CKDKVS-incomingMessages"; +CKDKVSPerformanceCounter* const CKDKVSPerfCounterOutgoingMessages = (CKDKVSPerformanceCounter*)@"CKDKVS-outgoingMessages"; +CKDKVSPerformanceCounter* const CKDKVSPerfCounterTotalWaitTimeSynchronize = (CKDKVSPerformanceCounter*)@"CKDKVS-totalWaittimeSynchronize"; +CKDKVSPerformanceCounter* const CKDKVSPerfCounterLongestWaitTimeSynchronize = (CKDKVSPerformanceCounter*)@"CKDKVS-longestWaittimeSynchronize"; +CKDKVSPerformanceCounter* const CKDKVSPerfCounterSynchronizeFailures = (CKDKVSPerformanceCounter*)@"CKDKVS-synchronizeFailures"; + +@implementation SOSAnalytics + ++ (NSString*)databasePath +{ + // This block exists because we moved database locations in 11.3 for easier sandboxing, so we're cleaning up. + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + WithPathInKeychainDirectory(CFSTR("sos_analytics.db"), ^(const char *filename) { + remove(filename); + }); + WithPathInKeychainDirectory(CFSTR("sos_analytics.db-wal"), ^(const char *filename) { + remove(filename); + }); + WithPathInKeychainDirectory(CFSTR("sos_analytics.db-shm"), ^(const char *filename) { + remove(filename); + }); + }); + return [SOSAnalytics defaultAnalyticsDatabasePath:@"sos_analytics"]; +} + ++ (instancetype)logger +{ + return [super logger]; +} + +@end + +#endif diff --git a/Analytics/NSDate+SFAnalytics.h b/Analytics/NSDate+SFAnalytics.h new file mode 100644 index 000000000..9d902e2ee --- /dev/null +++ b/Analytics/NSDate+SFAnalytics.h @@ -0,0 +1,38 @@ +/* + * 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 NSDate_SFAnalytics_h +#define NSDate_SFAnalytics_h + +#import +#import "SFAnalytics.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface NSDate (SFAnalytics) +- (NSTimeInterval)timeIntervalSince1970WithBucket:(SFAnalyticsTimestampBucket)bucket; +@end + +NS_ASSUME_NONNULL_END + +#endif /* NSDate_SFAnalytics_h */ diff --git a/Analytics/NSDate+SFAnalytics.m b/Analytics/NSDate+SFAnalytics.m new file mode 100644 index 000000000..c9979e8a3 --- /dev/null +++ b/Analytics/NSDate+SFAnalytics.m @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import +#import "NSDate+SFAnalytics.h" + +@implementation NSDate (SFAnalytics) + +- (NSTimeInterval)bucketToRoundingFactor:(SFAnalyticsTimestampBucket)bucket +{ + switch (bucket) { + case SFAnalyticsTimestampBucketSecond: + return 1; + case SFAnalyticsTimestampBucketMinute: + return 60; + case SFAnalyticsTimestampBucketHour: + return 60 * 60; + } +} + +- (NSTimeInterval)timeIntervalSince1970WithBucket:(SFAnalyticsTimestampBucket)bucket +{ + NSTimeInterval mask = [self bucketToRoundingFactor:bucket]; + NSTimeInterval now = [[NSDate date] timeIntervalSince1970]; + return (NSTimeInterval)(now + (mask - ((long)now % (long)mask))); +} + +@end + diff --git a/Analytics/SFAnalytics+Internal.h b/Analytics/SFAnalytics+Internal.h new file mode 100644 index 000000000..05aa19a79 --- /dev/null +++ b/Analytics/SFAnalytics+Internal.h @@ -0,0 +1,38 @@ +/* + * 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 SFAnalytics_Internal_h +#define SFAnalytics_Internal_h + +#if __OBJC2__ + +#import "SFAnalytics.h" + +@interface SFAnalytics (Internal) + +- (void)logMetric:(NSNumber*)metric withName:(NSString*)metricName oncePerReport:(BOOL)once; + +@end + +#endif // objc2 +#endif /* SFAnalytics_Internal_h */ diff --git a/Analytics/SFAnalytics+Signin.h b/Analytics/SFAnalytics+Signin.h new file mode 100644 index 000000000..44c437d73 --- /dev/null +++ b/Analytics/SFAnalytics+Signin.h @@ -0,0 +1,40 @@ +/* + * 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 SFAnalytics_Internal_h +#define SFAnalytics_Internal_h + +#if __OBJC2__ + +#import "SFAnalytics.h" +#import "SFAnalyticsSQLiteStore.h" +@interface SFAnalytics (SignIn) +/* Typical SFA clients do not need this. SignIn Metrics needs this */ +@property (nonatomic) SFAnalyticsSQLiteStore* database; +/*queue from SFA exposed for testing only, this queue is used to protected db accesses and should NOT be used directly*/ +@property (nonatomic) dispatch_queue_t queue; +@end + +#endif // objc2 +#endif /* SFAnalytics_Internal_h */ + diff --git a/Analytics/SFAnalytics.h b/Analytics/SFAnalytics.h new file mode 100644 index 000000000..55d35ba62 --- /dev/null +++ b/Analytics/SFAnalytics.h @@ -0,0 +1,155 @@ +/* + * 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 SFAnalytics_h +#define SFAnalytics_h + +#import +#import "SFAnalyticsSampler.h" +#import "SFAnalyticsMultiSampler.h" +#import "SFAnalyticsActivityTracker.h" + +NS_ASSUME_NONNULL_BEGIN + +// this sampling interval will cause the sampler to run only at data reporting time +extern const NSTimeInterval SFAnalyticsSamplerIntervalOncePerReport; + +typedef NS_ENUM(uint32_t, SFAnalyticsTimestampBucket) { + SFAnalyticsTimestampBucketSecond = 0, + SFAnalyticsTimestampBucketMinute = 1, + SFAnalyticsTimestampBucketHour = 2, +}; + +@protocol SFAnalyticsProtocol ++ (id _Nullable)logger; + +- (void)logResultForEvent:(NSString*)eventName + hardFailure:(bool)hardFailure + result:(NSError* _Nullable)eventResultError; +- (void)logResultForEvent:(NSString*)eventName + hardFailure:(bool)hardFailure + result:(NSError* _Nullable)eventResultError + withAttributes:(NSDictionary* _Nullable)attributes; + +- (SFAnalyticsMultiSampler* _Nullable)AddMultiSamplerForName:(NSString *)samplerName + withTimeInterval:(NSTimeInterval)timeInterval + block:(NSDictionary *(^)(void))block; + +- (SFAnalyticsActivityTracker* _Nullable)logSystemMetricsForActivityNamed:(NSString*)eventName + withAction:(void (^ _Nullable)(void))action; +- (SFAnalyticsActivityTracker* _Nullable)startLogSystemMetricsForActivityNamed:(NSString *)eventName; +@end + +@interface SFAnalytics : NSObject + ++ (instancetype _Nullable)logger; + ++ (NSInteger)fuzzyDaysSinceDate:(NSDate*)date; ++ (void)addOSVersionToEvent:(NSMutableDictionary*)event; +// Help for the subclass to pick a prefered location ++ (NSString *)defaultAnalyticsDatabasePath:(NSString *)basename; + +- (void)dailyCoreAnalyticsMetrics:(NSString *)eventName; + +// Log event-based metrics: create an event corresponding to some event in your feature +// and call the appropriate method based on the successfulness of that event +- (void)logSuccessForEventNamed:(NSString*)eventName; +- (void)logSuccessForEventNamed:(NSString*)eventName timestampBucket:(SFAnalyticsTimestampBucket)timestampBucket; + +- (void)logHardFailureForEventNamed:(NSString*)eventName withAttributes:(NSDictionary* _Nullable)attributes; +- (void)logHardFailureForEventNamed:(NSString*)eventName withAttributes:(NSDictionary* _Nullable)attributes timestampBucket:(SFAnalyticsTimestampBucket)timestampBucket; + +- (void)logSoftFailureForEventNamed:(NSString*)eventName withAttributes:(NSDictionary* _Nullable)attributes; +- (void)logSoftFailureForEventNamed:(NSString*)eventName withAttributes:(NSDictionary* _Nullable)attributes timestampBucket:(SFAnalyticsTimestampBucket)timestampBucket; + +// or just log an event if it is not failable +- (void)noteEventNamed:(NSString*)eventName; +- (void)noteEventNamed:(NSString*)eventName timestampBucket:(SFAnalyticsTimestampBucket)timestampBucket; + +- (void)logResultForEvent:(NSString*)eventName + hardFailure:(bool)hardFailure + result:(NSError* _Nullable)eventResultError; +- (void)logResultForEvent:(NSString*)eventName + hardFailure:(bool)hardFailure + result:(NSError* _Nullable)eventResultError + timestampBucket:(SFAnalyticsTimestampBucket)timestampBucket; +- (void)logResultForEvent:(NSString*)eventName + hardFailure:(bool)hardFailure + result:(NSError* _Nullable)eventResultError + withAttributes:(NSDictionary* _Nullable)attributes; +- (void)logResultForEvent:(NSString*)eventName + hardFailure:(bool)hardFailure + result:(NSError* _Nullable)eventResultError + withAttributes:(NSDictionary* _Nullable)attributes + timestampBucket:(SFAnalyticsTimestampBucket)timestampBucket; + +// Track the state of a named value over time +- (SFAnalyticsSampler* _Nullable)addMetricSamplerForName:(NSString*)samplerName + withTimeInterval:(NSTimeInterval)timeInterval + block:(NSNumber* (^)(void))block; +- (SFAnalyticsSampler* _Nullable)existingMetricSamplerForName:(NSString*)samplerName; +- (void)removeMetricSamplerForName:(NSString*)samplerName; +// Same idea, but log multiple named values in a single block +- (SFAnalyticsMultiSampler* _Nullable)AddMultiSamplerForName:(NSString*)samplerName + withTimeInterval:(NSTimeInterval)timeInterval + block:(NSDictionary* (^)(void))block; +- (SFAnalyticsMultiSampler*)existingMultiSamplerForName:(NSString*)samplerName; +- (void)removeMultiSamplerForName:(NSString*)samplerName; + +// Log measurements of arbitrary things +// System metrics measures how much time it takes to complete the action - possibly more in the future. The return value can be ignored if you only need to execute 1 block for your activity +- (SFAnalyticsActivityTracker* _Nullable)logSystemMetricsForActivityNamed:(NSString*)eventName + withAction:(void (^ _Nullable)(void))action; + +// Same as above, but automatically starts the tracker, since you haven't given it any action to perform +- (SFAnalyticsActivityTracker* _Nullable)startLogSystemMetricsForActivityNamed:(NSString *)eventName; + +- (void)logMetric:(NSNumber*)metric withName:(NSString*)metricName; + + +// -------------------------------- +// Things below are for subclasses + +// Override to create a concrete logger instance +@property (readonly, class, nullable) NSString* databasePath; + +// Storing dates +- (void)setDateProperty:(NSDate* _Nullable)date forKey:(NSString*)key; +- (NSDate* _Nullable)datePropertyForKey:(NSString*)key; + +- (void)incrementIntegerPropertyForKey:(NSString*)key; +- (void)setNumberProperty:(NSNumber* _Nullable)number forKey:(NSString*)key; +- (NSNumber * _Nullable)numberPropertyForKey:(NSString*)key; + + +// -------------------------------- +// Things below are for unit testing + +- (void)removeState; // removes DB object and any samplers + +@end + +NS_ASSUME_NONNULL_END +#endif +#endif diff --git a/Analytics/SFAnalytics.m b/Analytics/SFAnalytics.m new file mode 100644 index 000000000..4f6933a4b --- /dev/null +++ b/Analytics/SFAnalytics.m @@ -0,0 +1,735 @@ +/* + * 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 "SFAnalytics+Internal.h" +#import "SFAnalyticsDefines.h" +#import "SFAnalyticsActivityTracker+Internal.h" +#import "SFAnalyticsSampler+Internal.h" +#import "SFAnalyticsMultiSampler+Internal.h" +#import "SFAnalyticsSQLiteStore.h" +#import "NSDate+SFAnalytics.h" +#import "utilities/debugging.h" +#import +#import +#import +#import +#include +#include + +#import + +// SFAnalyticsDefines constants +NSString* const SFAnalyticsTableSuccessCount = @"success_count"; +NSString* const SFAnalyticsTableHardFailures = @"hard_failures"; +NSString* const SFAnalyticsTableSoftFailures = @"soft_failures"; +NSString* const SFAnalyticsTableSamples = @"samples"; +NSString* const SFAnalyticsTableNotes = @"notes"; + +NSString* const SFAnalyticsColumnSuccessCount = @"success_count"; +NSString* const SFAnalyticsColumnHardFailureCount = @"hard_failure_count"; +NSString* const SFAnalyticsColumnSoftFailureCount = @"soft_failure_count"; +NSString* const SFAnalyticsColumnSampleValue = @"value"; +NSString* const SFAnalyticsColumnSampleName = @"name"; + +NSString* const SFAnalyticsEventTime = @"eventTime"; +NSString* const SFAnalyticsEventType = @"eventType"; +NSString* const SFAnalyticsEventTypeErrorEvent = @"errorEvent"; +NSString* const SFAnalyticsEventErrorDestription = @"errorDescription"; +NSString* const SFAnalyticsEventClassKey = @"eventClass"; + +NSString* const SFAnalyticsAttributeErrorUnderlyingChain = @"errorChain"; +NSString* const SFAnalyticsAttributeErrorDomain = @"errorDomain"; +NSString* const SFAnalyticsAttributeErrorCode = @"errorCode"; + +NSString* const SFAnalyticsAttributeLastUploadTime = @"lastUploadTime"; + +NSString* const SFAnalyticsUserDefaultsSuite = @"com.apple.security.analytics"; + +char* const SFAnalyticsFireSamplersNotification = "com.apple.security.sfanalytics.samplers"; + +NSString* const SFAnalyticsTopicCloudServices = @"CloudServicesTopic"; +NSString* const SFAnalyticsTopicKeySync = @"KeySyncTopic"; +NSString* const SFAnalyticsTopicTrust = @"TrustTopic"; +NSString* const SFAnalyticsTopicTransparency = @"TransparencyTopic"; + +NSString* const SFAnalyticsTableSchema = @"CREATE TABLE IF NOT EXISTS hard_failures (\n" + @"id INTEGER PRIMARY KEY AUTOINCREMENT,\n" + @"timestamp REAL," + @"data BLOB\n" + @");\n" + @"DROP TRIGGER IF EXISTS maintain_ring_buffer_hard_failures;\n" + @"CREATE TRIGGER IF NOT EXISTS maintain_ring_buffer_hard_failures_v2 AFTER INSERT ON hard_failures\n" + @"BEGIN\n" + @"DELETE FROM hard_failures WHERE id <= NEW.id - 1000;\n" + @"END;\n" + @"CREATE TABLE IF NOT EXISTS soft_failures (\n" + @"id INTEGER PRIMARY KEY AUTOINCREMENT,\n" + @"timestamp REAL," + @"data BLOB\n" + @");\n" + @"DROP TRIGGER IF EXISTS maintain_ring_buffer_soft_failures;\n" + @"CREATE TRIGGER IF NOT EXISTS maintain_ring_buffer_soft_failures_v2 AFTER INSERT ON soft_failures\n" + @"BEGIN\n" + @"DELETE FROM soft_failures WHERE id <= NEW.id - 1000;\n" + @"END;\n" + @"CREATE TABLE IF NOT EXISTS notes (\n" + @"id INTEGER PRIMARY KEY AUTOINCREMENT,\n" + @"timestamp REAL," + @"data BLOB\n" + @");\n" + @"DROP TRIGGER IF EXISTS maintain_ring_buffer_notes;\n" + @"CREATE TRIGGER IF NOT EXISTS maintain_ring_buffer_notes_v2 AFTER INSERT ON notes\n" + @"BEGIN\n" + @"DELETE FROM notes WHERE id <= NEW.id - 1000;\n" + @"END;\n" + @"CREATE TABLE IF NOT EXISTS samples (\n" + @"id INTEGER PRIMARY KEY AUTOINCREMENT,\n" + @"timestamp REAL,\n" + @"name STRING,\n" + @"value REAL\n" + @");\n" + @"DROP TRIGGER IF EXISTS maintain_ring_buffer_samples;\n" + @"CREATE TRIGGER IF NOT EXISTS maintain_ring_buffer_samples_v2 AFTER INSERT ON samples\n" + @"BEGIN\n" + @"DELETE FROM samples WHERE id <= NEW.id - 1000;\n" + @"END;\n" + @"CREATE TABLE IF NOT EXISTS success_count (\n" + @"event_type STRING PRIMARY KEY,\n" + @"success_count INTEGER,\n" + @"hard_failure_count INTEGER,\n" + @"soft_failure_count INTEGER\n" + @");\n" + @"DROP TABLE IF EXISTS all_events;\n"; + +NSUInteger const SFAnalyticsMaxEventsToReport = 1000; + +NSString* const SFAnalyticsErrorDomain = @"com.apple.security.sfanalytics"; + +// Local constants +NSString* const SFAnalyticsEventBuild = @"build"; +NSString* const SFAnalyticsEventProduct = @"product"; +NSString* const SFAnalyticsEventInternal = @"internal"; +const NSTimeInterval SFAnalyticsSamplerIntervalOncePerReport = -1.0; + +@interface SFAnalytics () +@property (nonatomic) SFAnalyticsSQLiteStore* database; +@property (nonatomic) dispatch_queue_t queue; +@end + +@implementation SFAnalytics { + SFAnalyticsSQLiteStore* _database; + dispatch_queue_t _queue; + NSMutableDictionary* _samplers; + NSMutableDictionary* _multisamplers; + unsigned int _disableLogging:1; +} + ++ (instancetype)logger +{ + if (self == [SFAnalytics class]) { + secerror("attempt to instatiate abstract class SFAnalytics"); + return nil; + } + + SFAnalytics* logger = nil; + @synchronized(self) { + logger = objc_getAssociatedObject(self, "SFAnalyticsInstance"); + if (!logger) { + logger = [[self alloc] init]; + objc_setAssociatedObject(self, "SFAnalyticsInstance", logger, OBJC_ASSOCIATION_RETAIN); + } + } + + [logger database]; // For unit testing so there's always a database. DB shouldn't be nilled in production though + return logger; +} + ++ (NSString*)databasePath +{ + return nil; +} + ++ (NSString *)defaultAnalyticsDatabasePath:(NSString *)basename +{ + WithPathInKeychainDirectory(CFSTR("Analytics"), ^(const char *path) { +#if TARGET_OS_IPHONE + mode_t permissions = 0775; +#else + mode_t permissions = 0700; +#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:@"Analytics/%@.db", basename]; + return [(__bridge_transfer NSURL*)SecCopyURLForFileInKeychainDirectory((__bridge CFStringRef)path) path]; +} + ++ (NSInteger)fuzzyDaysSinceDate:(NSDate*)date +{ + // Sentinel: it didn't happen at all + if (!date) { + return -1; + } + + // Sentinel: it happened but we don't know when because the date doesn't make sense + // Magic number represents January 1, 2017. + if ([date compare:[NSDate dateWithTimeIntervalSince1970:1483228800]] == NSOrderedAscending) { + return 1000; + } + + NSInteger secondsPerDay = 60 * 60 * 24; + + NSTimeInterval timeIntervalSinceDate = [[NSDate date] timeIntervalSinceDate:date]; + if (timeIntervalSinceDate < secondsPerDay) { + return 0; + } + else if (timeIntervalSinceDate < (secondsPerDay * 7)) { + return 1; + } + else if (timeIntervalSinceDate < (secondsPerDay * 30)) { + return 7; + } + else if (timeIntervalSinceDate < (secondsPerDay * 365)) { + return 30; + } + else { + return 365; + } +} + +// Instantiate lazily so unit tests can have clean databases each +- (SFAnalyticsSQLiteStore*)database +{ + if (!_database) { + _database = [SFAnalyticsSQLiteStore storeWithPath:self.class.databasePath schema:SFAnalyticsTableSchema]; + if (!_database) { + seccritical("Did not get a database! (Client %@)", NSStringFromClass([self class])); + } + } + return _database; +} + +- (void)removeState +{ + [_samplers removeAllObjects]; + [_multisamplers removeAllObjects]; + + __weak __typeof(self) weakSelf = self; + dispatch_sync(_queue, ^{ + __strong __typeof(self) strongSelf = weakSelf; + if (strongSelf) { + [strongSelf.database close]; + strongSelf->_database = nil; + } + }); +} + +- (void)setDateProperty:(NSDate*)date forKey:(NSString*)key +{ + __weak __typeof(self) weakSelf = self; + dispatch_sync(_queue, ^{ + __strong __typeof(self) strongSelf = weakSelf; + if (strongSelf) { + [strongSelf.database setDateProperty:date forKey:key]; + } + }); +} + +- (NSDate*)datePropertyForKey:(NSString*)key +{ + __block NSDate* result = nil; + __weak __typeof(self) weakSelf = self; + dispatch_sync(_queue, ^{ + __strong __typeof(self) strongSelf = weakSelf; + if (strongSelf) { + result = [strongSelf.database datePropertyForKey:key]; + } + }); + return result; +} + + +- (void)incrementIntegerPropertyForKey:(NSString*)key +{ + __weak __typeof(self) weakSelf = self; + dispatch_sync(_queue, ^{ + __strong __typeof(self) strongSelf = weakSelf; + if (strongSelf == nil) { + return; + } + NSInteger integer = [[strongSelf.database propertyForKey:key] integerValue]; + [strongSelf.database setProperty:[NSString stringWithFormat:@"%ld", (long)integer + 1] forKey:key]; + }); +} + +- (void)setNumberProperty:(NSNumber* _Nullable)number forKey:(NSString*)key +{ + __weak __typeof(self) weakSelf = self; + dispatch_sync(_queue, ^{ + __strong __typeof(self) strongSelf = weakSelf; + if (strongSelf) { + [strongSelf.database setProperty:[number stringValue] forKey:key]; + } + }); +} + +- (NSNumber* _Nullable)numberPropertyForKey:(NSString*)key +{ + __block NSNumber* result = nil; + __weak __typeof(self) weakSelf = self; + dispatch_sync(_queue, ^{ + __strong __typeof(self) strongSelf = weakSelf; + if (strongSelf) { + NSString *property = [strongSelf.database propertyForKey:key]; + if (property) { + result = [NSNumber numberWithInteger:[property integerValue]]; + } + } + }); + return result; +} + + ++ (void)addOSVersionToEvent:(NSMutableDictionary*)eventDict { + static dispatch_once_t onceToken; + static NSString *build = NULL; + static NSString *product = NULL; + static BOOL internal = NO; + dispatch_once(&onceToken, ^{ + NSDictionary *version = CFBridgingRelease(_CFCopySystemVersionDictionary()); + if (version == NULL) + return; + build = version[(__bridge NSString *)_kCFSystemVersionBuildVersionKey]; + product = version[(__bridge NSString *)_kCFSystemVersionProductNameKey]; + internal = os_variant_has_internal_diagnostics("com.apple.security"); + }); + if (build) { + eventDict[SFAnalyticsEventBuild] = build; + } + if (product) { + eventDict[SFAnalyticsEventProduct] = product; + } + if (internal) { + eventDict[SFAnalyticsEventInternal] = @YES; + } +} + +- (instancetype)init +{ + if (self = [super init]) { + _queue = dispatch_queue_create("SFAnalytics data access queue", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); + _samplers = [NSMutableDictionary new]; + _multisamplers = [NSMutableDictionary new]; + [self database]; // for side effect of instantiating DB object. Used for testing. + } + + return self; +} + +- (NSDictionary *)coreAnalyticsKeyFilter:(NSDictionary *)info +{ + NSMutableDictionary *filtered = [NSMutableDictionary dictionary]; + [info enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { + filtered[[key stringByReplacingOccurrencesOfString:@"-" withString:@"_"]] = obj; + }]; + return filtered; +} + +// Daily CoreAnalytics metrics +// Call this once per say if you want to have the once per day sampler collect their data and submit it + +- (void)dailyCoreAnalyticsMetrics:(NSString *)eventName +{ + NSMutableDictionary *dailyMetrics = [NSMutableDictionary dictionary]; + __block NSDictionary* multisamplers; + __block NSDictionary* samplers; + + dispatch_sync(_queue, ^{ + multisamplers = [self->_multisamplers copy]; + samplers = [self->_samplers copy]; + }); + + [multisamplers enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, SFAnalyticsMultiSampler * _Nonnull obj, BOOL * _Nonnull stop) { + if (obj.oncePerReport == FALSE) { + return; + } + NSDictionary *samples = [obj sampleNow]; + if (samples == nil) { + return; + } + [dailyMetrics addEntriesFromDictionary:samples]; + }]; + + [samplers enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, SFAnalyticsSampler * _Nonnull obj, BOOL * _Nonnull stop) { + if (obj.oncePerReport == FALSE) { + return; + } + dailyMetrics[key] = [obj sampleNow]; + }]; + + [SecCoreAnalytics sendEvent:eventName event:[self coreAnalyticsKeyFilter:dailyMetrics]]; +} + +// MARK: Event logging + +- (void)logSuccessForEventNamed:(NSString*)eventName timestampBucket:(SFAnalyticsTimestampBucket)timestampBucket +{ + [self logEventNamed:eventName class:SFAnalyticsEventClassSuccess attributes:nil timestampBucket:timestampBucket]; +} + +- (void)logSuccessForEventNamed:(NSString*)eventName +{ + [self logSuccessForEventNamed:eventName timestampBucket:SFAnalyticsTimestampBucketSecond]; +} + +- (void)logHardFailureForEventNamed:(NSString*)eventName withAttributes:(NSDictionary*)attributes timestampBucket:(SFAnalyticsTimestampBucket)timestampBucket +{ + [self logEventNamed:eventName class:SFAnalyticsEventClassHardFailure attributes:attributes timestampBucket:timestampBucket]; +} + +- (void)logHardFailureForEventNamed:(NSString*)eventName withAttributes:(NSDictionary*)attributes +{ + [self logHardFailureForEventNamed:eventName withAttributes:attributes timestampBucket:SFAnalyticsTimestampBucketSecond]; +} + +- (void)logSoftFailureForEventNamed:(NSString*)eventName withAttributes:(NSDictionary*)attributes timestampBucket:(SFAnalyticsTimestampBucket)timestampBucket +{ + [self logEventNamed:eventName class:SFAnalyticsEventClassSoftFailure attributes:attributes timestampBucket:timestampBucket]; +} + +- (void)logSoftFailureForEventNamed:(NSString*)eventName withAttributes:(NSDictionary*)attributes +{ + [self logSoftFailureForEventNamed:eventName withAttributes:attributes timestampBucket:SFAnalyticsTimestampBucketSecond]; +} + +- (void)logResultForEvent:(NSString*)eventName hardFailure:(bool)hardFailure result:(NSError*)eventResultError timestampBucket:(SFAnalyticsTimestampBucket)timestampBucket +{ + [self logResultForEvent:eventName hardFailure:hardFailure result:eventResultError withAttributes:nil timestampBucket:SFAnalyticsTimestampBucketSecond]; +} + +- (void)logResultForEvent:(NSString*)eventName hardFailure:(bool)hardFailure result:(NSError*)eventResultError +{ + [self logResultForEvent:eventName hardFailure:hardFailure result:eventResultError timestampBucket:SFAnalyticsTimestampBucketSecond]; +} + +- (void)logResultForEvent:(NSString*)eventName hardFailure:(bool)hardFailure result:(NSError*)eventResultError withAttributes:(NSDictionary*)attributes timestampBucket:(SFAnalyticsTimestampBucket)timestampBucket +{ + if(!eventResultError) { + [self logSuccessForEventNamed:eventName]; + } else { + // Make an Attributes dictionary + NSMutableDictionary* eventAttributes = nil; + if (attributes) { + eventAttributes = [attributes mutableCopy]; + } else { + eventAttributes = [NSMutableDictionary dictionary]; + } + + /* if we have underlying errors, capture the chain below the top-most error */ + NSError *underlyingError = eventResultError.userInfo[NSUnderlyingErrorKey]; + if ([underlyingError isKindOfClass:[NSError class]]) { + NSMutableString *chain = [NSMutableString string]; + int count = 0; + do { + [chain appendFormat:@"%@-%ld:", underlyingError.domain, (long)underlyingError.code]; + underlyingError = underlyingError.userInfo[NSUnderlyingErrorKey]; + } while (count++ < 5 && [underlyingError isKindOfClass:[NSError class]]); + + eventAttributes[SFAnalyticsAttributeErrorUnderlyingChain] = chain; + } + + eventAttributes[SFAnalyticsAttributeErrorDomain] = eventResultError.domain; + eventAttributes[SFAnalyticsAttributeErrorCode] = @(eventResultError.code); + + if(hardFailure) { + [self logHardFailureForEventNamed:eventName withAttributes:eventAttributes]; + } else { + [self logSoftFailureForEventNamed:eventName withAttributes:eventAttributes]; + } + } +} + +- (void)logResultForEvent:(NSString*)eventName hardFailure:(bool)hardFailure result:(NSError*)eventResultError withAttributes:(NSDictionary*)attributes +{ + [self logResultForEvent:eventName hardFailure:hardFailure result:eventResultError withAttributes:attributes timestampBucket:SFAnalyticsTimestampBucketSecond]; +} + +- (void)noteEventNamed:(NSString*)eventName timestampBucket:(SFAnalyticsTimestampBucket)timestampBucket +{ + [self logEventNamed:eventName class:SFAnalyticsEventClassNote attributes:nil timestampBucket:timestampBucket]; +} + +- (void)noteEventNamed:(NSString*)eventName +{ + [self noteEventNamed:eventName timestampBucket:SFAnalyticsTimestampBucketSecond]; +} + +- (void)logEventNamed:(NSString*)eventName class:(SFAnalyticsEventClass)class attributes:(NSDictionary*)attributes timestampBucket:(SFAnalyticsTimestampBucket)timestampBucket +{ + if (!eventName) { + secerror("SFAnalytics: attempt to log an event with no name"); + return; + } + + __weak __typeof(self) weakSelf = self; + dispatch_sync(_queue, ^{ + __strong __typeof(self) strongSelf = weakSelf; + if (!strongSelf || strongSelf->_disableLogging) { + return; + } + + [strongSelf.database begin]; + + NSDictionary* eventDict = [self eventDictForEventName:eventName withAttributes:attributes eventClass:class timestampBucket:timestampBucket]; + + if (class == SFAnalyticsEventClassHardFailure) { + [strongSelf.database addEventDict:eventDict toTable:SFAnalyticsTableHardFailures timestampBucket:timestampBucket]; + [strongSelf.database incrementHardFailureCountForEventType:eventName]; + } + else if (class == SFAnalyticsEventClassSoftFailure) { + [strongSelf.database addEventDict:eventDict toTable:SFAnalyticsTableSoftFailures timestampBucket:timestampBucket]; + [strongSelf.database incrementSoftFailureCountForEventType:eventName]; + } + else if (class == SFAnalyticsEventClassNote) { + [strongSelf.database addEventDict:eventDict toTable:SFAnalyticsTableNotes timestampBucket:timestampBucket]; + [strongSelf.database incrementSuccessCountForEventType:eventName]; + } + else if (class == SFAnalyticsEventClassSuccess) { + [strongSelf.database incrementSuccessCountForEventType:eventName]; + } + + [strongSelf.database end]; + }); +} + +- (void)logEventNamed:(NSString*)eventName class:(SFAnalyticsEventClass)class attributes:(NSDictionary*)attributes +{ + [self logEventNamed:eventName class:class attributes:attributes timestampBucket:SFAnalyticsTimestampBucketSecond]; +} + +- (NSDictionary*) eventDictForEventName:(NSString*)eventName withAttributes:(NSDictionary*)attributes eventClass:(SFAnalyticsEventClass)eventClass timestampBucket:(NSTimeInterval)timestampBucket +{ + NSMutableDictionary* eventDict = attributes ? attributes.mutableCopy : [NSMutableDictionary dictionary]; + eventDict[SFAnalyticsEventType] = eventName; + + NSTimeInterval timestamp = [[NSDate date] timeIntervalSince1970WithBucket:timestampBucket]; + + // our backend wants timestamps in milliseconds + eventDict[SFAnalyticsEventTime] = @(timestamp * 1000); + eventDict[SFAnalyticsEventClassKey] = @(eventClass); + [SFAnalytics addOSVersionToEvent:eventDict]; + + return eventDict; +} + +// MARK: Sampling + +- (SFAnalyticsSampler*)addMetricSamplerForName:(NSString *)samplerName withTimeInterval:(NSTimeInterval)timeInterval block:(NSNumber *(^)(void))block +{ + if (!samplerName) { + secerror("SFAnalytics: cannot add sampler without name"); + return nil; + } + if (timeInterval < 1.0f && timeInterval != SFAnalyticsSamplerIntervalOncePerReport) { + secerror("SFAnalytics: cannot add sampler with interval %f", timeInterval); + return nil; + } + if (!block) { + secerror("SFAnalytics: cannot add sampler without block"); + return nil; + } + + __block SFAnalyticsSampler* sampler = nil; + + __weak __typeof(self) weakSelf = self; + dispatch_sync(_queue, ^{ + __strong __typeof(self) strongSelf = weakSelf; + if (strongSelf->_samplers[samplerName]) { + secerror("SFAnalytics: sampler \"%@\" already exists", samplerName); + } else { + sampler = [[SFAnalyticsSampler alloc] initWithName:samplerName interval:timeInterval block:block clientClass:[self class]]; + strongSelf->_samplers[samplerName] = sampler; // If sampler did not init because of bad data this 'removes' it from the dict, so a noop + } + }); + + return sampler; +} + +- (SFAnalyticsMultiSampler*)AddMultiSamplerForName:(NSString *)samplerName withTimeInterval:(NSTimeInterval)timeInterval block:(NSDictionary *(^)(void))block +{ + if (!samplerName) { + secerror("SFAnalytics: cannot add sampler without name"); + return nil; + } + if (timeInterval < 1.0f && timeInterval != SFAnalyticsSamplerIntervalOncePerReport) { + secerror("SFAnalytics: cannot add sampler with interval %f", timeInterval); + return nil; + } + if (!block) { + secerror("SFAnalytics: cannot add sampler without block"); + return nil; + } + + __block SFAnalyticsMultiSampler* sampler = nil; + __weak __typeof(self) weakSelf = self; + dispatch_sync(_queue, ^{ + __strong __typeof(self) strongSelf = weakSelf; + if (strongSelf->_multisamplers[samplerName]) { + secerror("SFAnalytics: multisampler \"%@\" already exists", samplerName); + } else { + sampler = [[SFAnalyticsMultiSampler alloc] initWithName:samplerName interval:timeInterval block:block clientClass:[self class]]; + strongSelf->_multisamplers[samplerName] = sampler; + } + + }); + + return sampler; +} + +- (SFAnalyticsSampler*)existingMetricSamplerForName:(NSString *)samplerName +{ + __block SFAnalyticsSampler* sampler = nil; + + __weak __typeof(self) weakSelf = self; + dispatch_sync(_queue, ^{ + __strong __typeof(self) strongSelf = weakSelf; + if (strongSelf) { + sampler = strongSelf->_samplers[samplerName]; + } + }); + return sampler; +} + +- (SFAnalyticsMultiSampler*)existingMultiSamplerForName:(NSString *)samplerName +{ + __block SFAnalyticsMultiSampler* sampler = nil; + + __weak __typeof(self) weakSelf = self; + dispatch_sync(_queue, ^{ + __strong __typeof(self) strongSelf = weakSelf; + if (strongSelf) { + sampler = strongSelf->_multisamplers[samplerName]; + } + }); + return sampler; +} + +- (void)removeMetricSamplerForName:(NSString *)samplerName +{ + if (!samplerName) { + secerror("Attempt to remove sampler without specifying samplerName"); + return; + } + + __weak __typeof(self) weakSelf = self; + dispatch_async(_queue, ^{ + os_transaction_t transaction = os_transaction_create("com.apple.security.sfanalytics.samplerGC"); + __strong __typeof(self) strongSelf = weakSelf; + if (strongSelf) { + [strongSelf->_samplers[samplerName] pauseSampling]; // when dealloced it would also stop, but we're not sure when that is so let's stop it right away + [strongSelf->_samplers removeObjectForKey:samplerName]; + } + (void)transaction; + transaction = nil; + }); +} + +- (void)removeMultiSamplerForName:(NSString *)samplerName +{ + if (!samplerName) { + secerror("Attempt to remove multisampler without specifying samplerName"); + return; + } + + __weak __typeof(self) weakSelf = self; + dispatch_async(_queue, ^{ + os_transaction_t transaction = os_transaction_create("com.apple.security.sfanalytics.samplerGC"); + __strong __typeof(self) strongSelf = weakSelf; + if (strongSelf) { + [strongSelf->_multisamplers[samplerName] pauseSampling]; // when dealloced it would also stop, but we're not sure when that is so let's stop it right away + [strongSelf->_multisamplers removeObjectForKey:samplerName]; + } + (void)transaction; + transaction = nil; + }); +} + +- (SFAnalyticsActivityTracker*)logSystemMetricsForActivityNamed:(NSString *)eventName withAction:(void (^)(void))action +{ + if (![eventName isKindOfClass:[NSString class]]) { + secerror("Cannot log system metrics without name"); + return nil; + } + SFAnalyticsActivityTracker* tracker = [[SFAnalyticsActivityTracker alloc] initWithName:eventName clientClass:[self class]]; + if (action) { + [tracker performAction:action]; + } + return tracker; +} + +- (SFAnalyticsActivityTracker*)startLogSystemMetricsForActivityNamed:(NSString *)eventName +{ + if (![eventName isKindOfClass:[NSString class]]) { + secerror("Cannot log system metrics without name"); + return nil; + } + SFAnalyticsActivityTracker* tracker = [[SFAnalyticsActivityTracker alloc] initWithName:eventName clientClass:[self class]]; + [tracker start]; + return tracker; +} + +- (void)logMetric:(NSNumber *)metric withName:(NSString *)metricName +{ + [self logMetric:metric withName:metricName oncePerReport:NO]; +} + +- (void)logMetric:(NSNumber*)metric withName:(NSString*)metricName oncePerReport:(BOOL)once +{ + if (![metric isKindOfClass:[NSNumber class]] || ![metricName isKindOfClass:[NSString class]]) { + secerror("SFAnalytics: Need a valid result and name to log result"); + return; + } + + __weak __typeof(self) weakSelf = self; + dispatch_async(_queue, ^{ + os_transaction_t transaction = os_transaction_create("com.apple.security.sfanalytics.samplerGC"); + __strong __typeof(self) strongSelf = weakSelf; + if (strongSelf && !strongSelf->_disableLogging) { + if (once) { + [strongSelf.database removeAllSamplesForName:metricName]; + } + [strongSelf.database addSample:metric forName:metricName]; + } + (void)transaction; + transaction = nil; + }); +} + +@end + +#endif // __OBJC2__ diff --git a/Analytics/SFAnalytics.plist b/Analytics/SFAnalytics.plist new file mode 100644 index 000000000..76b0892bf --- /dev/null +++ b/Analytics/SFAnalytics.plist @@ -0,0 +1,46 @@ + + + + + KeySyncTopic + + splunk_allowInsecureCertificate + + splunk_topic + xp_sear_keysync + splunk_bagURL + https://xp.apple.com/config/1/report/xp_sear_keysync + + CloudServicesTopic + + splunk_allowInsecureCertificate + + splunk_topic + xp_coreos_securebackup + splunk_bagURL + https://xp.apple.com/config/1/report/xp_coreos_securebackup + splunk_uploadURL + https://xp.apple.com/report/2/xp_coreos_securebackup + + TrustTopic + + splunk_allowInsecureCertificate + + splunk_topic + xp_sear_trust + splunk_bagURL + https://xp.apple.com/config/1/report/xp_sear_trust + disableClientId + + + TransparencyTopic + + splunk_allowInsecureCertificate + + splunk_topic + TransparencyAnalytics + splunk_bagURL + https://metrics-config.icloud.com/config/TransparencyAnalytics + + + diff --git a/Analytics/SFAnalyticsActivityTracker+Internal.h b/Analytics/SFAnalyticsActivityTracker+Internal.h new file mode 100644 index 000000000..3d24b00cf --- /dev/null +++ b/Analytics/SFAnalyticsActivityTracker+Internal.h @@ -0,0 +1,39 @@ +/* + * 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 SFAnalyticsActivityTracker_Internal_h +#define SFAnalyticsActivityTracker_Internal_h + +#if __OBJC2__ + +#import "SFAnalyticsActivityTracker.h" + +@interface SFAnalyticsActivityTracker(Internal) + +- (instancetype)initWithName:(NSString*)name clientClass:(Class)className; + +@end + +#endif // objc2 + +#endif /* SFAnalyticsActivityTracker_private_h */ diff --git a/Analytics/SFAnalyticsActivityTracker.h b/Analytics/SFAnalyticsActivityTracker.h new file mode 100644 index 000000000..7a58f5a49 --- /dev/null +++ b/Analytics/SFAnalyticsActivityTracker.h @@ -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 SFAnalyticsActivityTracker_h +#define SFAnalyticsActivityTracker_h + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface SFAnalyticsActivityTracker : NSObject + +@property (readonly, nullable) NSNumber * measurement; + +- (instancetype)init NS_UNAVAILABLE; +- (void)performAction:(void (^)(void))action; +- (void)cancel; + +- (void)start; +- (void)stop; + +- (void)stopWithEvent:(NSString*)eventName + result:(NSError* _Nullable)eventResultError; + +@end + +NS_ASSUME_NONNULL_END + +#endif +#endif diff --git a/Analytics/SFAnalyticsActivityTracker.m b/Analytics/SFAnalyticsActivityTracker.m new file mode 100644 index 000000000..07c954ddd --- /dev/null +++ b/Analytics/SFAnalyticsActivityTracker.m @@ -0,0 +1,125 @@ +/* + * 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 "SFAnalyticsActivityTracker.h" +#import "SFAnalyticsActivityTracker+Internal.h" +#import "SFAnalytics.h" +#import +#import "utilities/debugging.h" + +@interface SFAnalyticsActivityTracker () +@property (readwrite) NSNumber * measurement; +@end + +@implementation SFAnalyticsActivityTracker { + dispatch_queue_t _queue; + NSString* _name; + Class _clientClass; + uint64_t _start; + BOOL _canceled; +} + +@synthesize measurement = _measurement; + +- (instancetype)initWithName:(NSString*)name clientClass:(Class)className { + if (![name isKindOfClass:[NSString class]] || ![className isSubclassOfClass:[SFAnalytics class]] ) { + secerror("Cannot instantiate SFActivityTracker without name and client class"); + return nil; + } + + if (self = [super init]) { + _queue = dispatch_queue_create("SFAnalyticsActivityTracker queue", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); + _name = name; + _clientClass = className; + _measurement = nil; + _canceled = NO; + _start = 0; + } + return self; +} + +- (void)performAction:(void (^)(void))action +{ + [self start]; + dispatch_sync(_queue, ^{ + action(); + }); + [self stop]; +} + +- (void)start +{ + if (_canceled) { + return; + } + NSAssert(_start == 0, @"SFAnalyticsActivityTracker user called start twice"); + _start = mach_absolute_time(); +} + +- (void)stop +{ + uint64_t end = mach_absolute_time(); + + if (_canceled) { + _start = 0; + return; + } + NSAssert(_start != 0, @"SFAnalyticsActivityTracker user called stop w/o calling start"); + + static mach_timebase_info_data_t sTimebaseInfo; + if ( sTimebaseInfo.denom == 0 ) { + (void)mach_timebase_info(&sTimebaseInfo); + } + + _measurement = @([_measurement doubleValue] + (1.0f * (end - _start) * (1.0f * sTimebaseInfo.numer / sTimebaseInfo.denom))); + _start = 0; +} + +- (void)stopWithEvent:(NSString*)eventName + result:(NSError* _Nullable)eventResultError +{ + [self stop]; + + [[_clientClass logger] logResultForEvent:eventName hardFailure:false result:eventResultError]; +} + +- (void)cancel +{ + _canceled = YES; +} + +- (void)dealloc +{ + if (_start != 0) { + [self stop]; + } + if (!_canceled && _measurement != nil) { + [[_clientClass logger] logMetric:_measurement withName:_name]; + } +} + +@end + +#endif diff --git a/Analytics/SFAnalyticsDefines.h b/Analytics/SFAnalyticsDefines.h new file mode 100644 index 000000000..2291ca024 --- /dev/null +++ b/Analytics/SFAnalyticsDefines.h @@ -0,0 +1,80 @@ +/* + * 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 SFAnalyticsDefines_h +#define SFAnalyticsDefines_h + +#if __OBJC2__ + +extern NSString* const SFAnalyticsTableSuccessCount; +extern NSString* const SFAnalyticsTableHardFailures; +extern NSString* const SFAnalyticsTableSoftFailures; +extern NSString* const SFAnalyticsTableSamples; +extern NSString* const SFAnalyticsTableNotes; + +extern NSString* const SFAnalyticsColumnSuccessCount; +extern NSString* const SFAnalyticsColumnHardFailureCount; +extern NSString* const SFAnalyticsColumnSoftFailureCount; +extern NSString* const SFAnalyticsColumnSampleValue; +extern NSString* const SFAnalyticsColumnSampleName; + +extern NSString* const SFAnalyticsEventTime; +extern NSString* const SFAnalyticsEventType; +extern NSString* const SFAnalyticsEventTypeErrorEvent; +extern NSString* const SFAnalyticsEventErrorDestription; +extern NSString* const SFAnalyticsEventClassKey; + +// Helpers for logging NSErrors +extern NSString* const SFAnalyticsAttributeErrorUnderlyingChain; +extern NSString* const SFAnalyticsAttributeErrorDomain; +extern NSString* const SFAnalyticsAttributeErrorCode; + +extern NSString* const SFAnalyticsAttributeLastUploadTime; + +extern NSString* const SFAnalyticsUserDefaultsSuite; + +extern char* const SFAnalyticsFireSamplersNotification; + +/* Internal Topic Names */ +extern NSString* const SFAnalyticsTopicCloudServices; +extern NSString* const SFAnalyticsTopicKeySync; +extern NSString* const SFAnalyticsTopicTrust; +extern NSString* const SFAnalyticsTopicTransparency; + +typedef NS_ENUM(NSInteger, SFAnalyticsEventClass) { + SFAnalyticsEventClassSuccess, + SFAnalyticsEventClassHardFailure, + SFAnalyticsEventClassSoftFailure, + SFAnalyticsEventClassNote +}; + +extern NSString* const SFAnalyticsTableSchema; + +// We can only send this many events in total to splunk per upload +extern NSUInteger const SFAnalyticsMaxEventsToReport; + +extern NSString* const SFAnalyticsErrorDomain; + +#endif /* __OBJC2__ */ + +#endif /* SFAnalyticsDefines_h */ diff --git a/Analytics/SFAnalyticsLogger.h b/Analytics/SFAnalyticsLogger.h deleted file mode 100644 index ebdba8b7d..000000000 --- a/Analytics/SFAnalyticsLogger.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2017 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#import - -#if __OBJC2__ - -@interface SFAnalyticsLogger : NSObject - -+ (instancetype)logger; - -+ (NSInteger)fuzzyDaysSinceDate:(NSDate*)date; - -- (void)logSuccessForEventNamed:(NSString*)eventName; -- (void)logHardFailureForEventNamed:(NSString*)eventName withAttributes:(NSDictionary*)attributes; -- (void)logSoftFailureForEventNamed:(NSString*)eventName withAttributes:(NSDictionary*)attributes; - -- (void)noteEventNamed:(NSString*)eventName; - -// -------------------------------- -// Things below are for subclasses - -// Override to create a concrete logger instance -@property (readonly, class) NSString* databasePath; - -// Storing dates -- (void)setDateProperty:(NSDate*)date forKey:(NSString*)key; -- (NSDate*)datePropertyForKey:(NSString*)key; - -- (NSDictionary*)extraValuesToUploadToServer; -- (NSString*)sysdiagnoseStringForEventRecord:(NSDictionary*)eventRecord; - -// -------------------------------- -// Things below are for utilities to drive and/or test the system - -- (NSString*)getSysdiagnoseDumpWithError:(NSError**)error; -- (NSData*)getLoggingJSONWithError:(NSError**)error; -- (BOOL)forceUploadWithError:(NSError**)error; - -// -------------------------------- -// Things below are for unit testing - -@property (readonly) dispatch_queue_t splunkLoggingQueue; -@property (readonly) NSURL* splunkUploadURL; -@property (readonly) NSString* splunkTopicName; -@property (readonly) NSURL* splunkBagURL; -@property (readonly) BOOL allowsInsecureSplunkCert; -@property BOOL ignoreServerDisablingMessages; - -@end - -#endif diff --git a/Analytics/SFAnalyticsLogger.m b/Analytics/SFAnalyticsLogger.m deleted file mode 100644 index 2a750ca56..000000000 --- a/Analytics/SFAnalyticsLogger.m +++ /dev/null @@ -1,878 +0,0 @@ -/* - * Copyright (c) 2017 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#if __OBJC2__ - -#import "SFAnalyticsLogger.h" -#import "SFSQLite.h" -#import "CKKSViewManager.h" -#import "debugging.h" -#import - -NSString* const SFAnalyticsLoggerTableSuccessCount = @"success_count"; -NSString* const SFAnalyticsLoggerColumnEventType = @"event_type"; -NSString* const SFAnalyticsLoggerColumnSuccessCount = @"success_count"; -NSString* const SFAnalyticsLoggerColumnHardFailureCount = @"hard_failure_count"; -NSString* const SFAnalyticsLoggerColumnSoftFailureCount = @"soft_failure_count"; - -NSString* const SFAnalyticsLoggerTableHardFailures = @"hard_failures"; -NSString* const SFAnalyticsLoggerTableSoftFailures = @"soft_failures"; -NSString* const SFAnalyticsLoggerTableAllEvents = @"all_events"; -NSString* const SFAnalyticsLoggerColumnDate = @"timestamp"; -NSString* const SFAnalyticsLoggerColumnData = @"data"; - -NSString* const SFAnalyticsLoggerUploadDate = @"upload_date"; - -NSString* const SFAnalyticsLoggerSplunkTopic = @"topic"; -NSString* const SFAnalyticsLoggerSplunkEventTime = @"eventTime"; -NSString* const SFAnalyticsLoggerSplunkPostTime = @"postTime"; -NSString* const SFAnalyticsLoggerSplunkEventType = @"eventType"; -NSString* const SFAnalyticsLoggerMetricsBase = @"metricsBase"; -NSString* const SFAnalyticsLoggerEventClassKey = @"eventClass"; - -NSString* const SFAnalyticsUserDefaultsSuite = @"com.apple.security.analytics"; - -static NSString* const SFAnalyticsLoggerTableSchema = @"CREATE TABLE IF NOT EXISTS hard_failures (\n" - @"id INTEGER PRIMARY KEY AUTOINCREMENT,\n" - @"timestamp REAL," - @"data BLOB\n" - @");\n" - @"CREATE TRIGGER IF NOT EXISTS maintain_ring_buffer_hard_failures AFTER INSERT ON hard_failures\n" - @"BEGIN\n" - @"DELETE FROM hard_failures WHERE id != NEW.id AND id % 999 = NEW.id % 999;\n" - @"END;\n" - @"CREATE TABLE IF NOT EXISTS soft_failures (\n" - @"id INTEGER PRIMARY KEY AUTOINCREMENT,\n" - @"timestamp REAL," - @"data BLOB\n" - @");\n" - @"CREATE TRIGGER IF NOT EXISTS maintain_ring_buffer_soft_failures AFTER INSERT ON soft_failures\n" - @"BEGIN\n" - @"DELETE FROM soft_failures WHERE id != NEW.id AND id % 999 = NEW.id % 999;\n" - @"END;\n" - @"CREATE TABLE IF NOT EXISTS all_events (\n" - @"id INTEGER PRIMARY KEY AUTOINCREMENT,\n" - @"timestamp REAL," - @"data BLOB\n" - @");\n" - @"CREATE TRIGGER IF NOT EXISTS maintain_ring_buffer_all_events AFTER INSERT ON all_events\n" - @"BEGIN\n" - @"DELETE FROM all_events WHERE id != NEW.id AND id % 10000 = NEW.id % 10000;\n" - @"END;\n" - @"CREATE TABLE IF NOT EXISTS success_count (\n" - @"event_type STRING PRIMARY KEY,\n" - @"success_count INTEGER,\n" - @"hard_failure_count INTEGER,\n" - @"soft_failure_count INTEGER\n" - @");\n"; - -#define SFANALYTICS_SPLUNK_DEV 0 -#define SFANALYTICS_MAX_EVENTS_TO_REPORT 999 - -#if SFANALYTICS_SPLUNK_DEV -#define SECONDS_BETWEEN_UPLOADS 10 -#else -// three days = 60 seconds times 60 minutes * 72 hours -#define SECONDS_BETWEEN_UPLOADS (60 * 60 * 72) -#endif - -#define SECONDS_PER_DAY (60 * 60 * 24) - -typedef NS_ENUM(NSInteger, SFAnalyticsEventClass) { - SFAnalyticsEventClassSuccess, - SFAnalyticsEventClassHardFailure, - SFAnalyticsEventClassSoftFailure, - SFAnalyticsEventClassNote -}; - -@interface SFAnalyticsLoggerSQLiteStore : SFSQLite - -@property (readonly, strong) NSArray* failureRecords; -@property (readonly, strong) NSArray* allEvents; -@property (readwrite, strong) NSDate* uploadDate; - -+ (instancetype)storeWithPath:(NSString*)path schema:(NSString*)schema; - -- (void)incrementSuccessCountForEventType:(NSString*)eventType; -- (void)incrementHardFailureCountForEventType:(NSString*)eventType; -- (void)incrementSoftFailureCountForEventType:(NSString*)eventType; -- (NSInteger)successCountForEventType:(NSString*)eventType; -- (NSInteger)hardFailureCountForEventType:(NSString*)eventType; -- (NSInteger)softFailureCountForEventType:(NSString*)eventType; -- (void)addEventDict:(NSDictionary*)eventDict toTable:(NSString*)table; -- (void)clearAllData; - -- (NSDictionary*)summaryCounts; - -@end - -@implementation SFAnalyticsLogger { - SFAnalyticsLoggerSQLiteStore* _database; - NSURL* _splunkUploadURL; - NSString* _splunkTopicName; - NSURL* _splunkBagURL; - dispatch_queue_t _queue; - NSInteger _secondsBetweenUploads; - NSDictionary* _metricsBase; // data the server provides and wants us to send back - NSArray* _blacklistedFields; - NSArray* _blacklistedEvents; - - unsigned int _allowInsecureSplunkCert:1; - unsigned int _disableLogging:1; - unsigned int _disableUploads:1; - unsigned int _ignoreServersMessagesTellingUsToGoAway:1; -} - -@synthesize splunkUploadURL = _splunkUploadURL; -@synthesize splunkBagURL = _splunkBagURL; -@synthesize splunkTopicName = _splunkTopicName; -@synthesize splunkLoggingQueue = _queue; - -+ (instancetype)logger -{ -#if TARGET_OS_SIMULATOR - return nil; -#else - - if (self == [SFAnalyticsLogger class]) { - secerror("attempt to instatiate abstract class SFAnalyticsLogger"); - return nil; - } - - SFAnalyticsLogger* logger = nil; - @synchronized(self) { - logger = objc_getAssociatedObject(self, "SFAnalyticsLoggerInstance"); - if (!logger) { - logger = [[self alloc] init]; - objc_setAssociatedObject(self, "SFAnalyticsLoggerInstance", logger, OBJC_ASSOCIATION_RETAIN); - } - } - return logger; -#endif -} - -+ (NSString*)databasePath -{ - return nil; -} - -+ (NSInteger)fuzzyDaysSinceDate:(NSDate*)date -{ - NSTimeInterval timeIntervalSinceDate = [[NSDate date] timeIntervalSinceDate:date]; - if (timeIntervalSinceDate < SECONDS_PER_DAY) { - return 0; - } - else if (timeIntervalSinceDate < (SECONDS_PER_DAY * 7)) { - return 1; - } - else if (timeIntervalSinceDate < (SECONDS_PER_DAY * 30)) { - return 7; - } - else if (timeIntervalSinceDate < (SECONDS_PER_DAY * 365)) { - return 30; - } - else { - return 365; - } -} - -- (instancetype)init -{ - if (self = [super init]) { - _database = [SFAnalyticsLoggerSQLiteStore storeWithPath:self.class.databasePath schema:SFAnalyticsLoggerTableSchema]; - _queue = dispatch_queue_create("com.apple.security.analytics", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); - _secondsBetweenUploads = SECONDS_BETWEEN_UPLOADS; - - NSDictionary* systemDefaultValues = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle bundleWithPath:@"/System/Library/Frameworks/Security.framework"] pathForResource:@"SFAnalyticsLogging" ofType:@"plist"]]; - _splunkTopicName = systemDefaultValues[@"splunk_topic"]; - _splunkUploadURL = [NSURL URLWithString:systemDefaultValues[@"splunk_uploadURL"]]; - _splunkBagURL = [NSURL URLWithString:systemDefaultValues[@"splunk_bagURL"]]; - _allowInsecureSplunkCert = [[systemDefaultValues valueForKey:@"splunk_allowInsecureCertificate"] boolValue]; - NSString* splunkEndpoint = systemDefaultValues[@"splunk_endpointDomain"]; - - NSUserDefaults* defaults = [[NSUserDefaults alloc] initWithSuiteName:SFAnalyticsUserDefaultsSuite]; - NSString* userDefaultsSplunkTopic = [defaults stringForKey:@"splunk_topic"]; - if (userDefaultsSplunkTopic) { - _splunkTopicName = userDefaultsSplunkTopic; - } - - NSURL* userDefaultsSplunkUploadURL = [NSURL URLWithString:[defaults stringForKey:@"splunk_uploadURL"]]; - if (userDefaultsSplunkUploadURL) { - _splunkUploadURL = userDefaultsSplunkUploadURL; - } - - NSURL* userDefaultsSplunkBagURL = [NSURL URLWithString:[defaults stringForKey:@"splunk_bagURL"]]; - if (userDefaultsSplunkUploadURL) { - _splunkBagURL = userDefaultsSplunkBagURL; - } - - BOOL userDefaultsAllowInsecureSplunkCert = [defaults boolForKey:@"splunk_allowInsecureCertificate"]; - _allowInsecureSplunkCert |= userDefaultsAllowInsecureSplunkCert; - - NSString* userDefaultsSplunkEndpoint = [defaults stringForKey:@"splunk_endpointDomain"]; - if (userDefaultsSplunkEndpoint) { - splunkEndpoint = userDefaultsSplunkEndpoint; - } - -#if SFANALYTICS_SPLUNK_DEV - _ignoreServersMessagesTellingUsToGoAway = YES; - - if (!_splunkUploadURL && splunkEndpoint) { - NSString* urlString = [NSString stringWithFormat:@"https://%@/report/2/%@", splunkEndpoint, _splunkTopicName]; - _splunkUploadURL = [NSURL URLWithString:urlString]; - } -#else - (void)splunkEndpoint; -#endif - } - - return self; -} - -- (void)logSuccessForEventNamed:(NSString*)eventName -{ - [self logEventNamed:eventName class:SFAnalyticsEventClassSuccess attributes:nil]; -} - -- (void)logHardFailureForEventNamed:(NSString*)eventName withAttributes:(NSDictionary*)attributes -{ - [self logEventNamed:eventName class:SFAnalyticsEventClassSoftFailure attributes:attributes]; -} - -- (void)logSoftFailureForEventNamed:(NSString*)eventName withAttributes:(NSDictionary*)attributes -{ - [self logEventNamed:eventName class:SFAnalyticsEventClassHardFailure attributes:attributes]; -} - -- (void)noteEventNamed:(NSString*)eventName -{ - [self logEventNamed:eventName class:SFAnalyticsEventClassNote attributes:nil]; -} - -- (void)logEventNamed:(NSString*)eventName class:(SFAnalyticsEventClass)class attributes:(NSDictionary*)attributes -{ - if (!eventName) { - secinfo("SFAnalytics", "attempt to log an event with no name"); - return; - } - - __block NSDate* uploadDate = nil; - __weak __typeof(self) weakSelf = self; - dispatch_sync(_queue, ^{ - __strong __typeof(self) strongSelf = weakSelf; - if (!strongSelf || strongSelf->_disableLogging || [strongSelf->_blacklistedEvents containsObject:eventName]) { - return; - } - - NSDictionary* eventDict = [self eventDictForEventName:eventName withAttributes:attributes eventClass:class]; - [strongSelf->_database addEventDict:eventDict toTable:SFAnalyticsLoggerTableAllEvents]; - - if (class == SFAnalyticsEventClassHardFailure) { - NSDictionary* strippedDict = [self eventDictWithBlacklistedFieldsStrippedFrom:eventDict]; - [strongSelf->_database addEventDict:strippedDict toTable:SFAnalyticsLoggerTableHardFailures]; - [strongSelf->_database incrementHardFailureCountForEventType:eventName]; - } - else if (class == SFAnalyticsEventClassSoftFailure) { - NSDictionary* strippedDict = [self eventDictWithBlacklistedFieldsStrippedFrom:eventDict]; - [strongSelf->_database addEventDict:strippedDict toTable:SFAnalyticsLoggerTableSoftFailures]; - [strongSelf->_database incrementSoftFailureCountForEventType:eventName]; - } - else if (class == SFAnalyticsEventClassSuccess || class == SFAnalyticsEventClassNote) { - [strongSelf->_database incrementSuccessCountForEventType:eventName]; - } - - uploadDate = strongSelf->_database.uploadDate; - }); - - NSDate* nowDate = [NSDate date]; - if (uploadDate) { - if ([nowDate compare:uploadDate] == NSOrderedDescending) { - NSError* error = nil; - BOOL uploadSuccess = [self forceUploadWithError:&error]; - if (uploadSuccess) { - secinfo("SFAnalytics", "uploaded sync health data"); - [self resetUploadDate:YES]; - } - - if (error) { - secerror("SFAnalytics: failed to upload json to analytics server with error: %@", error); - } - } - } - else { - [self resetUploadDate:NO]; - } -} - -- (void)resetUploadDate:(BOOL)clearData -{ - __weak __typeof(self) weakSelf = self; - dispatch_sync(_queue, ^{ - __strong __typeof(self) strongSelf = weakSelf; - if (!strongSelf) { - return; - } - - if (clearData) { - [strongSelf->_database clearAllData]; - } - strongSelf->_database.uploadDate = [NSDate dateWithTimeIntervalSinceNow:strongSelf->_secondsBetweenUploads]; - }); -} - -- (NSDictionary*)eventDictForEventName:(NSString*)eventName withAttributes:(NSDictionary*)attributes eventClass:(SFAnalyticsEventClass)eventClass -{ - NSMutableDictionary* eventDict = attributes ? attributes.mutableCopy : [NSMutableDictionary dictionary]; - eventDict[SFAnalyticsLoggerSplunkTopic] = _splunkTopicName; - eventDict[SFAnalyticsLoggerSplunkEventType] = eventName; - eventDict[SFAnalyticsLoggerSplunkEventTime] = @([[NSDate date] timeIntervalSince1970] * 1000); - eventDict[SFAnalyticsLoggerEventClassKey] = @(eventClass); - - [_metricsBase enumerateKeysAndObjectsUsingBlock:^(NSString* key, id object, BOOL* stop) { - if (!eventDict[key]) { - eventDict[key] = object; - } - }]; - - return eventDict; -} - -- (NSDictionary*)eventDictWithBlacklistedFieldsStrippedFrom:(NSDictionary*)eventDict -{ - NSMutableDictionary* strippedDict = eventDict.mutableCopy; - for (NSString* blacklistedField in _blacklistedFields) { - [strippedDict removeObjectForKey:blacklistedField]; - } - return strippedDict; -} - -- (void)setDateProperty:(NSDate*)date forKey:(NSString*)key -{ - dispatch_sync(_queue, ^{ - [self->_database setDateProperty:date forKey:key]; - }); -} - -- (NSDate*)datePropertyForKey:(NSString*)key -{ - __block NSDate* result = nil; - dispatch_sync(_queue, ^{ - result = [self->_database datePropertyForKey:key]; - }); - return result; -} - -- (NSDictionary*)extraValuesToUploadToServer -{ - return [NSDictionary dictionary]; -} - -// this method is kind of evil for the fact that it has side-effects in pulling other things besides the metricsURL from the server, and as such should NOT be memoized. -// TODO redo this, probably to return a dictionary. -- (NSURL*)splunkUploadURL -{ - dispatch_assert_queue(_queue); - - if (_splunkUploadURL) { - return _splunkUploadURL; - } - - __weak __typeof(self) weakSelf = self; - dispatch_semaphore_t sem = dispatch_semaphore_create(0); - - __block NSError* error = nil; - NSURLSessionConfiguration *defaultConfiguration = [NSURLSessionConfiguration ephemeralSessionConfiguration]; - NSURLSession* storeBagSession = [NSURLSession sessionWithConfiguration:defaultConfiguration - delegate:self - delegateQueue:nil]; - - NSURL* requestEndpoint = _splunkBagURL; - __block NSURL* result = nil; - NSURLSessionDataTask* storeBagTask = [storeBagSession dataTaskWithURL:requestEndpoint completionHandler:^(NSData * _Nullable data, - NSURLResponse * _Nullable __unused response, - NSError * _Nullable responseError) { - - __strong __typeof(self) strongSelf = weakSelf; - if (!strongSelf) { - return; - } - - if (data && !responseError) { - NSData *responseData = data; // shut up compiler - NSDictionary* responseDict = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&error]; - if([responseDict isKindOfClass:NSDictionary.class] && !error) { - if (!self->_ignoreServersMessagesTellingUsToGoAway) { - strongSelf->_disableLogging = [[responseDict valueForKey:@"disabled"] boolValue]; - if (strongSelf->_disableLogging || [[responseDict valueForKey:@"sendDisabled"] boolValue]) { - // then don't upload anything right now - secerror("not returning a splunk URL because uploads are disabled"); - dispatch_semaphore_signal(sem); - return; - } - - NSUInteger millisecondsBetweenUploads = [[responseDict valueForKey:@"postFrequency"] unsignedIntegerValue] / 1000; - if (millisecondsBetweenUploads > 0) { - strongSelf->_secondsBetweenUploads = millisecondsBetweenUploads; - } - - strongSelf->_blacklistedEvents = responseDict[@"blacklistedEvents"]; - strongSelf->_blacklistedFields = responseDict[@"blacklistedFields"]; - } - - strongSelf->_metricsBase = responseDict[@"metricsBase"]; - - NSString* metricsEndpoint = responseDict[@"metricsUrl"]; - if([metricsEndpoint isKindOfClass:NSString.class]) { - /* Lives our URL */ - NSString* endpoint = [metricsEndpoint stringByAppendingFormat:@"/2/%@", strongSelf->_splunkTopicName]; - secnotice("ckks", "got metrics endpoint: %@", endpoint); - NSURL* endpointURL = [NSURL URLWithString:endpoint]; - if([endpointURL.scheme isEqualToString:@"https"]) { - result = endpointURL; - } - } - } - } - else { - error = responseError; - } - if(error) { - secnotice("ckks", "Unable to fetch splunk endpoint at URL: %@ -- error: %@", requestEndpoint, error.description); - } - else if(!result) { - secnotice("ckks", "Malformed iTunes config payload!"); - } - - dispatch_semaphore_signal(sem); - }]; - - [storeBagTask resume]; - dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); - - return result; -} - -- (BOOL)forceUploadWithError:(NSError**)error -{ - __block BOOL result = NO; - NSData* json = [self getLoggingJSONWithError:error]; - dispatch_sync(_queue, ^{ - if (json && [self _onQueuePostJSON:json error:error]) { - secinfo("ckks", "uploading sync health data: %@", json); - - [self->_database clearAllData]; - self->_database.uploadDate = [NSDate dateWithTimeIntervalSinceNow:self->_secondsBetweenUploads]; - result = YES; - } - else { - result = NO; - } - }); - - return result; -} - -- (BOOL)_onQueuePostJSON:(NSData*)json error:(NSError**)error -{ - dispatch_assert_queue(_queue); - - /* - * Create the NSURLSession - * We use the ephemeral session config because we don't need cookies or cache - */ - NSURLSessionConfiguration *defaultConfiguration = [NSURLSessionConfiguration ephemeralSessionConfiguration]; - NSURLSession* postSession = [NSURLSession sessionWithConfiguration:defaultConfiguration - delegate:self - delegateQueue:nil]; - - /* - * Create the request - */ - NSURL* postEndpoint = self.splunkUploadURL; - if (!postEndpoint) { - secerror("failed to get a splunk upload endpoint - not uploading"); - return NO; - } - - NSMutableURLRequest* postRequest = [[NSMutableURLRequest alloc] init]; - postRequest.URL = postEndpoint; - postRequest.HTTPMethod = @"POST"; - postRequest.HTTPBody = json; - - /* - * Create the upload task. - */ - dispatch_semaphore_t sem = dispatch_semaphore_create(0); - __block BOOL uploadSuccess = NO; - NSURLSessionDataTask* uploadTask = [postSession dataTaskWithRequest:postRequest - completionHandler:^(NSData * _Nullable __unused data, NSURLResponse * _Nullable response, NSError * _Nullable requestError) { - if(requestError) { - secerror("Error in uploading the events to splunk: %@", requestError); - } - else if (![response isKindOfClass:NSHTTPURLResponse.class]){ - Class class = response.class; - secerror("Received the wrong kind of response: %@", NSStringFromClass(class)); - } - else { - NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response; - if(httpResponse.statusCode >= 200 && httpResponse.statusCode < 300) { - /* Success */ - uploadSuccess = YES; - secnotice("ckks", "Splunk upload success"); - } - else { - secnotice("ckks", "Splunk upload unexpected status to URL: %@ -- status: %d", postEndpoint, (int)(httpResponse.statusCode)); - } - } - dispatch_semaphore_signal(sem); - }]; - - secnotice("ckks", "Splunk upload start"); - [uploadTask resume]; - dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); - return uploadSuccess; -} - -- (NSString*)stringForEventClass:(SFAnalyticsEventClass)eventClass -{ - if (eventClass == SFAnalyticsEventClassNote) { - return @"EventNote"; - } - else if (eventClass == SFAnalyticsEventClassSuccess) { - return @"EventSuccess"; - } - else if (eventClass == SFAnalyticsEventClassHardFailure) { - return @"EventHardFailure"; - } - else if (eventClass == SFAnalyticsEventClassSoftFailure) { - return @"EventSoftFailure"; - } - else { - return @"EventUnknown"; - } -} - -- (NSString*)sysdiagnoseStringForEventRecord:(NSDictionary*)eventRecord -{ - NSMutableDictionary* mutableEventRecord = eventRecord.mutableCopy; - [mutableEventRecord removeObjectForKey:SFAnalyticsLoggerSplunkTopic]; - - NSDate* eventDate = [NSDate dateWithTimeIntervalSince1970:[[eventRecord valueForKey:SFAnalyticsLoggerSplunkEventTime] doubleValue] / 1000]; - [mutableEventRecord removeObjectForKey:SFAnalyticsLoggerSplunkEventTime]; - - NSString* eventName = eventRecord[SFAnalyticsLoggerSplunkEventType]; - [mutableEventRecord removeObjectForKey:SFAnalyticsLoggerSplunkEventType]; - - SFAnalyticsEventClass eventClass = [[eventRecord valueForKey:SFAnalyticsLoggerEventClassKey] integerValue]; - NSString* eventClassString = [self stringForEventClass:eventClass]; - [mutableEventRecord removeObjectForKey:SFAnalyticsLoggerEventClassKey]; - - NSMutableString* additionalAttributesString = [NSMutableString string]; - if (mutableEventRecord.count > 0) { - [additionalAttributesString appendString:@" - Attributes: {" ]; - __block BOOL firstAttribute = YES; - [mutableEventRecord enumerateKeysAndObjectsUsingBlock:^(NSString* key, id object, BOOL* stop) { - NSString* openingString = firstAttribute ? @"" : @", "; - [additionalAttributesString appendString:[NSString stringWithFormat:@"%@%@ : %@", openingString, key, object]]; - firstAttribute = NO; - }]; - [additionalAttributesString appendString:@" }"]; - } - - return [NSString stringWithFormat:@"%@ %@: %@%@", eventDate, eventClassString, eventName, additionalAttributesString]; -} - -- (NSString*)getSysdiagnoseDumpWithError:(NSError**)error -{ - NSMutableString* sysdiagnose = [[NSMutableString alloc] init]; - - NSDictionary* extraValues = self.extraValuesToUploadToServer; - [extraValues enumerateKeysAndObjectsUsingBlock:^(NSString* key, id object, BOOL* stop) { - [sysdiagnose appendFormat:@"Key: %@, Value: %@\n", key, object]; - }]; - - [sysdiagnose appendString:@"\n"]; - - dispatch_sync(_queue, ^{ - NSArray* allEvents = self->_database.allEvents; - for (NSDictionary* eventRecord in allEvents) { - [sysdiagnose appendFormat:@"%@\n", [self sysdiagnoseStringForEventRecord:eventRecord]]; - } - }); - - return sysdiagnose; -} - -- (NSData*)getLoggingJSONWithError:(NSError**)error -{ - __block NSData* json = nil; - NSDictionary* extraValues = self.extraValuesToUploadToServer; - dispatch_sync(_queue, ^{ - NSArray* failureRecords = self->_database.failureRecords; - - NSDictionary* successCounts = self->_database.summaryCounts; - NSInteger totalSuccessCount = 0; - NSInteger totalHardFailureCount = 0; - NSInteger totalSoftFailureCount = 0; - for (NSDictionary* perEventTypeSuccessCounts in successCounts.objectEnumerator) { - totalSuccessCount += [perEventTypeSuccessCounts[SFAnalyticsLoggerColumnSuccessCount] integerValue]; - totalHardFailureCount += [perEventTypeSuccessCounts[SFAnalyticsLoggerColumnHardFailureCount] integerValue]; - totalSoftFailureCount += [perEventTypeSuccessCounts[SFAnalyticsLoggerColumnSoftFailureCount] integerValue]; - } - - NSDate* now = [NSDate date]; - - NSMutableDictionary* healthSummaryEvent = extraValues ? extraValues.mutableCopy : [[NSMutableDictionary alloc] init]; - healthSummaryEvent[SFAnalyticsLoggerSplunkTopic] = self->_splunkTopicName ?: [NSNull null]; - healthSummaryEvent[SFAnalyticsLoggerSplunkEventTime] = @([now timeIntervalSince1970] * 1000); - healthSummaryEvent[SFAnalyticsLoggerSplunkEventType] = @"ckksHealthSummary"; - healthSummaryEvent[SFAnalyticsLoggerColumnSuccessCount] = @(totalSuccessCount); - healthSummaryEvent[SFAnalyticsLoggerColumnHardFailureCount] = @(totalHardFailureCount); - healthSummaryEvent[SFAnalyticsLoggerColumnSoftFailureCount] = @(totalSoftFailureCount); - - NSMutableArray* splunkRecords = failureRecords.mutableCopy; - [splunkRecords addObject:healthSummaryEvent]; - - NSDictionary* jsonDict = @{SFAnalyticsLoggerSplunkPostTime : @([now timeIntervalSince1970] * 1000), @"events" : splunkRecords}; - - json = [NSJSONSerialization dataWithJSONObject:jsonDict options:NSJSONWritingPrettyPrinted error:error]; - }); - - return json; -} - -- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge - completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler { - assert(completionHandler); - (void)session; - secnotice("ckks", "Splunk upload challenge"); - NSURLCredential *cred = nil; - SecTrustResultType result = kSecTrustResultInvalid; - - if ([challenge previousFailureCount] > 0) { - // Previous failures occurred, bail - completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); - - } else if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { - /* - * Evaluate trust for the certificate - */ - - SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; - SecTrustEvaluate(serverTrust, &result); - if (_allowInsecureSplunkCert || (result == kSecTrustResultProceed) || (result == kSecTrustResultUnspecified)) { - /* - * All is well, accept the credentials - */ - if(_allowInsecureSplunkCert) { - secnotice("ckks", "Force Accepting Splunk Credential"); - } - cred = [NSURLCredential credentialForTrust:serverTrust]; - completionHandler(NSURLSessionAuthChallengeUseCredential, cred); - - } else { - /* - * An error occurred in evaluating trust, bail - */ - completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); - } - } else { - /* - * Just perform the default handling - */ - completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); - } - -} - -- (BOOL)ignoreServerDisablingMessages -{ - return _ignoreServersMessagesTellingUsToGoAway; -} - -- (void)setIgnoreServerDisablingMessages:(BOOL)ignoreServer -{ - _ignoreServersMessagesTellingUsToGoAway = ignoreServer ? YES : NO; -} - -- (BOOL)allowsInsecureSplunkCert -{ - return _allowInsecureSplunkCert; -} - -- (void)setAllowsInsecureSplunkCert:(BOOL)allowsInsecureSplunkCert -{ - _allowInsecureSplunkCert = allowsInsecureSplunkCert ? YES : NO; -} - -@end - -@implementation SFAnalyticsLoggerSQLiteStore - -+ (instancetype)storeWithPath:(NSString*)path schema:(NSString*)schema -{ - SFAnalyticsLoggerSQLiteStore* store = nil; - @synchronized([SFAnalyticsLoggerSQLiteStore class]) { - static NSMutableDictionary* loggingStores = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - loggingStores = [[NSMutableDictionary alloc] init]; - }); - - NSString* standardizedPath = path.stringByStandardizingPath; - store = loggingStores[standardizedPath]; - if (!store) { - store = [[self alloc] initWithPath:standardizedPath schema:schema]; - loggingStores[standardizedPath] = store; - } - - [store open]; - } - - return store; -} - -- (void)dealloc -{ - [self close]; -} - -- (NSInteger)successCountForEventType:(NSString*)eventType -{ - return [[[[self select:@[SFAnalyticsLoggerColumnSuccessCount] from:SFAnalyticsLoggerTableSuccessCount where:@"event_type = ?" bindings:@[eventType]] firstObject] valueForKey:SFAnalyticsLoggerColumnSuccessCount] integerValue]; -} - -- (void)incrementSuccessCountForEventType:(NSString*)eventType -{ - NSInteger successCount = [self successCountForEventType:eventType]; - NSInteger hardFailureCount = [self hardFailureCountForEventType:eventType]; - NSInteger softFailureCount = [self softFailureCountForEventType:eventType]; - [self insertOrReplaceInto:SFAnalyticsLoggerTableSuccessCount values:@{SFAnalyticsLoggerColumnEventType : eventType, SFAnalyticsLoggerColumnSuccessCount : @(successCount + 1), SFAnalyticsLoggerColumnHardFailureCount : @(hardFailureCount), SFAnalyticsLoggerColumnSoftFailureCount : @(softFailureCount)}]; -} - -- (NSInteger)hardFailureCountForEventType:(NSString*)eventType -{ - return [[[[self select:@[SFAnalyticsLoggerColumnHardFailureCount] from:SFAnalyticsLoggerTableSuccessCount where:@"event_type = ?" bindings:@[eventType]] firstObject] valueForKey:SFAnalyticsLoggerColumnHardFailureCount] integerValue]; -} - -- (NSInteger)softFailureCountForEventType:(NSString*)eventType -{ - return [[[[self select:@[SFAnalyticsLoggerColumnSoftFailureCount] from:SFAnalyticsLoggerTableSuccessCount where:@"event_type = ?" bindings:@[eventType]] firstObject] valueForKey:SFAnalyticsLoggerColumnSoftFailureCount] integerValue]; -} - -- (void)incrementHardFailureCountForEventType:(NSString*)eventType -{ - NSInteger successCount = [self successCountForEventType:eventType]; - NSInteger hardFailureCount = [self hardFailureCountForEventType:eventType]; - NSInteger softFailureCount = [self softFailureCountForEventType:eventType]; - [self insertOrReplaceInto:SFAnalyticsLoggerTableSuccessCount values:@{SFAnalyticsLoggerColumnEventType : eventType, SFAnalyticsLoggerColumnSuccessCount : @(successCount), SFAnalyticsLoggerColumnHardFailureCount : @(hardFailureCount + 1), SFAnalyticsLoggerColumnSoftFailureCount : @(softFailureCount)}]; -} - -- (void)incrementSoftFailureCountForEventType:(NSString*)eventType -{ - NSInteger successCount = [self successCountForEventType:eventType]; - NSInteger hardFailureCount = [self hardFailureCountForEventType:eventType]; - NSInteger softFailureCount = [self softFailureCountForEventType:eventType]; - [self insertOrReplaceInto:SFAnalyticsLoggerTableSuccessCount values:@{SFAnalyticsLoggerColumnEventType : eventType, SFAnalyticsLoggerColumnSuccessCount : @(successCount), SFAnalyticsLoggerColumnHardFailureCount : @(hardFailureCount), SFAnalyticsLoggerColumnSoftFailureCount : @(softFailureCount + 1)}]; -} - -- (NSDictionary*)summaryCounts -{ - NSMutableDictionary* successCountsDict = [NSMutableDictionary dictionary]; - NSArray* rows = [self selectAllFrom:SFAnalyticsLoggerTableSuccessCount where:nil bindings:nil]; - for (NSDictionary* rowDict in rows) { - NSString* eventName = rowDict[SFAnalyticsLoggerColumnEventType]; - if (!eventName) { - secinfo("SFAnalytics", "ignoring entry in success counts table without an event name"); - continue; - } - - successCountsDict[eventName] = @{SFAnalyticsLoggerTableSuccessCount : rowDict[SFAnalyticsLoggerColumnSuccessCount], SFAnalyticsLoggerColumnHardFailureCount : rowDict[SFAnalyticsLoggerColumnHardFailureCount], SFAnalyticsLoggerColumnSoftFailureCount : rowDict[SFAnalyticsLoggerColumnSoftFailureCount]}; - } - - return successCountsDict; -} - -- (NSArray*)failureRecords -{ - NSArray* recordBlobs = [self select:@[SFAnalyticsLoggerColumnData] from:SFAnalyticsLoggerTableHardFailures]; - if (recordBlobs.count < SFANALYTICS_MAX_EVENTS_TO_REPORT) { - NSArray* softFailureBlobs = [self select:@[SFAnalyticsLoggerColumnData] from:SFAnalyticsLoggerTableSoftFailures]; - if (softFailureBlobs.count > 0) { - NSInteger numSoftFailuresToReport = SFANALYTICS_MAX_EVENTS_TO_REPORT - recordBlobs.count; - recordBlobs = [recordBlobs arrayByAddingObjectsFromArray:[softFailureBlobs subarrayWithRange:NSMakeRange(softFailureBlobs.count - numSoftFailuresToReport, numSoftFailuresToReport)]]; - } - } - - NSMutableArray* failureRecords = [[NSMutableArray alloc] init]; - for (NSDictionary* row in recordBlobs) { - NSDictionary* deserializedRecord = [NSPropertyListSerialization propertyListWithData:row[SFAnalyticsLoggerColumnData] options:0 format:nil error:nil]; - [failureRecords addObject:deserializedRecord]; - } - - return failureRecords; -} - -- (NSArray*)allEvents -{ - NSArray* recordBlobs = [self select:@[SFAnalyticsLoggerColumnData] from:SFAnalyticsLoggerTableAllEvents]; - NSMutableArray* records = [[NSMutableArray alloc] init]; - for (NSDictionary* row in recordBlobs) { - NSDictionary* deserializedRecord = [NSPropertyListSerialization propertyListWithData:row[SFAnalyticsLoggerColumnData] options:0 format:nil error:nil]; - [records addObject:deserializedRecord]; - } - return records; -} - -- (void)addEventDict:(NSDictionary*)eventDict toTable:(NSString*)table -{ - NSError* error = nil; - NSData* serializedRecord = [NSPropertyListSerialization dataWithPropertyList:eventDict format:NSPropertyListBinaryFormat_v1_0 options:0 error:&error]; - if(!error && serializedRecord) { - [self insertOrReplaceInto:table values:@{SFAnalyticsLoggerColumnDate : [NSDate date], SFAnalyticsLoggerColumnData : serializedRecord}]; - } - if(error && !serializedRecord) { - secerror("Couldn't serialize failure record: %@", error); - } -} - -- (NSDate*)uploadDate -{ - return [self datePropertyForKey:SFAnalyticsLoggerUploadDate]; -} - -- (void)setUploadDate:(NSDate*)uploadDate -{ - [self setDateProperty:uploadDate forKey:SFAnalyticsLoggerUploadDate]; -} - -- (void)clearAllData -{ - [self deleteFrom:SFAnalyticsLoggerTableSuccessCount where:@"event_type like ?" bindings:@[@"%"]]; - [self deleteFrom:SFAnalyticsLoggerTableHardFailures where:@"id >= 0" bindings:nil]; - [self deleteFrom:SFAnalyticsLoggerTableSoftFailures where:@"id >= 0" bindings:nil]; -} - -@end - -#endif // __OBJC2__ diff --git a/Analytics/SFAnalyticsLogging.plist b/Analytics/SFAnalyticsLogging.plist deleted file mode 100644 index 060222c34..000000000 --- a/Analytics/SFAnalyticsLogging.plist +++ /dev/null @@ -1,16 +0,0 @@ - - - - - splunk_topic - xp_sear_keysync - splunk_allowInsecureCertificate - - splunk_bagURL - https://xp.apple.com/config/1/report/xp_sear_keysync - SyncManifests - - EnforceManifests - - - diff --git a/Analytics/SFAnalyticsMultiSampler+Internal.h b/Analytics/SFAnalyticsMultiSampler+Internal.h new file mode 100644 index 000000000..cc3657442 --- /dev/null +++ b/Analytics/SFAnalyticsMultiSampler+Internal.h @@ -0,0 +1,39 @@ +/* + * 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 SFAnalyticsMultiSampler_Internal_h +#define SFAnalyticsMultiSampler_Internal_h + +#if __OBJC2__ + +#import "SFAnalyticsMultiSampler.h" + +typedef NSDictionary* MultiSamplerDictionary; + +@interface SFAnalyticsMultiSampler(Internal) +- (instancetype)initWithName:(NSString*)name interval:(NSTimeInterval)interval block:(MultiSamplerDictionary (^)(void))block clientClass:(Class)clientClass; +@end + +#endif // objc2 + +#endif /* SFAnalyticsSampler_private_h */ diff --git a/Analytics/SFAnalyticsMultiSampler.h b/Analytics/SFAnalyticsMultiSampler.h new file mode 100644 index 000000000..3eb8a627d --- /dev/null +++ b/Analytics/SFAnalyticsMultiSampler.h @@ -0,0 +1,44 @@ +/* + * 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 SFAnalyticsMultiSampler_h +#define SFAnalyticsMultiSampler_h + +#import + +@interface SFAnalyticsMultiSampler : NSObject + +@property (nonatomic) NSTimeInterval samplingInterval; +@property (nonatomic, readonly) NSString* name; +@property (nonatomic, readonly) BOOL oncePerReport; + +- (instancetype)init NS_UNAVAILABLE; +- (NSDictionary*)sampleNow; +- (void)pauseSampling; +- (void)resumeSampling; + +@end + +#endif +#endif diff --git a/Analytics/SFAnalyticsMultiSampler.m b/Analytics/SFAnalyticsMultiSampler.m new file mode 100644 index 000000000..fed390ecc --- /dev/null +++ b/Analytics/SFAnalyticsMultiSampler.m @@ -0,0 +1,177 @@ +/* + * 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 "SFAnalyticsMultiSampler+Internal.h" +#import "SFAnalytics+Internal.h" +#import "SFAnalyticsDefines.h" +#import "utilities/debugging.h" +#include +#include + +@implementation SFAnalyticsMultiSampler { + NSTimeInterval _samplingInterval; + dispatch_source_t _timer; + NSString* _name; + MultiSamplerDictionary (^_block)(void); + int _notificationToken; + Class _clientClass; + BOOL _oncePerReport; + BOOL _activeTimer; +} + +@synthesize name = _name; +@synthesize samplingInterval = _samplingInterval; +@synthesize oncePerReport = _oncePerReport; + +- (instancetype)initWithName:(NSString*)name interval:(NSTimeInterval)interval block:(MultiSamplerDictionary (^)(void))block clientClass:(Class)clientClass +{ + if (self = [super init]) { + if (![clientClass isSubclassOfClass:[SFAnalytics class]]) { + secerror("SFAnalyticsSampler created without valid client class (%@)", clientClass); + return nil; + } + + if (!name || (interval < 1.0f && interval != SFAnalyticsSamplerIntervalOncePerReport) || !block) { + secerror("SFAnalyticsSampler created without proper data"); + return nil; + } + + _clientClass = clientClass; + _block = block; + _name = name; + _samplingInterval = interval; + [self newTimer]; + } + return self; +} + +- (void)newTimer +{ + if (_activeTimer) { + [self pauseSampling]; + } + + _oncePerReport = (_samplingInterval == SFAnalyticsSamplerIntervalOncePerReport); + if (_oncePerReport) { + [self setupOnceTimer]; + } else { + [self setupPeriodicTimer]; + } +} + +- (void)setupOnceTimer +{ + __weak __typeof(self) weakSelf = self; + notify_register_dispatch(SFAnalyticsFireSamplersNotification, &_notificationToken, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(int token) { + __strong __typeof(self) strongSelf = weakSelf; + if (!strongSelf) { + secnotice("SFAnalyticsSampler", "sampler went away before we could run its once-per-report block"); + notify_cancel(token); + return; + } + + MultiSamplerDictionary data = strongSelf->_block(); + [data enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSNumber * _Nonnull obj, BOOL * _Nonnull stop) { + [[strongSelf->_clientClass logger] logMetric:obj withName:key oncePerReport:strongSelf->_oncePerReport]; + }]; + }); + _activeTimer = YES; +} + +- (void)setupPeriodicTimer +{ + _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); + dispatch_source_set_timer(_timer, dispatch_walltime(0, _samplingInterval * NSEC_PER_SEC), _samplingInterval * NSEC_PER_SEC, _samplingInterval * NSEC_PER_SEC / 50.0); // give 2% leeway on timer + + __weak __typeof(self) weakSelf = self; + dispatch_source_set_event_handler(_timer, ^{ + __strong __typeof(self) strongSelf = weakSelf; + if (!strongSelf) { + secnotice("SFAnalyticsSampler", "sampler went away before we could run its once-per-report block"); + return; + } + + MultiSamplerDictionary data = strongSelf->_block(); + [data enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSNumber * _Nonnull obj, BOOL * _Nonnull stop) { + [[strongSelf->_clientClass logger] logMetric:obj withName:key oncePerReport:strongSelf->_oncePerReport]; + }]; + }); + dispatch_resume(_timer); + + _activeTimer = YES; +} + +- (void)setSamplingInterval:(NSTimeInterval)interval +{ + if (interval < 1.0f && !(interval == SFAnalyticsSamplerIntervalOncePerReport)) { + secerror("SFAnalyticsSampler: interval %f is not supported", interval); + return; + } + + _samplingInterval = interval; + [self newTimer]; +} + +- (NSTimeInterval)samplingInterval { + return _samplingInterval; +} + +- (MultiSamplerDictionary)sampleNow +{ + MultiSamplerDictionary data = _block(); + [data enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSNumber * _Nonnull obj, BOOL * _Nonnull stop) { + [[self->_clientClass logger] logMetric:obj withName:key oncePerReport:self->_oncePerReport]; + }]; + return data; +} + +- (void)pauseSampling +{ + if (!_activeTimer) { + return; + } + + if (_oncePerReport) { + notify_cancel(_notificationToken); + _notificationToken = 0; + } else { + dispatch_source_cancel(_timer); + } + _activeTimer = NO; +} + +- (void)resumeSampling +{ + [self newTimer]; +} + +- (void)dealloc +{ + [self pauseSampling]; +} + +@end + +#endif diff --git a/Analytics/SFAnalyticsSQLiteStore.h b/Analytics/SFAnalyticsSQLiteStore.h new file mode 100644 index 000000000..16531fa5a --- /dev/null +++ b/Analytics/SFAnalyticsSQLiteStore.h @@ -0,0 +1,56 @@ +/* + * 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 "Analytics/SQLite/SFSQLite.h" +#import "SFAnalytics.h" + +@interface SFAnalyticsSQLiteStore : SFSQLite + +@property (readonly, strong) NSArray* hardFailures; +@property (readonly, strong) NSArray* softFailures; +@property (readonly, strong) NSArray* allEvents; +@property (readonly, strong) NSArray* samples; +@property (readwrite, strong) NSDate* uploadDate; + ++ (instancetype)storeWithPath:(NSString*)path schema:(NSString*)schema; + +- (BOOL)tryToOpenDatabase; +- (void)incrementSuccessCountForEventType:(NSString*)eventType; +- (void)incrementHardFailureCountForEventType:(NSString*)eventType; +- (void)incrementSoftFailureCountForEventType:(NSString*)eventType; +- (NSInteger)successCountForEventType:(NSString*)eventType; +- (NSInteger)hardFailureCountForEventType:(NSString*)eventType; +- (NSInteger)softFailureCountForEventType:(NSString*)eventType; +- (void)addEventDict:(NSDictionary*)eventDict toTable:(NSString*)table; +- (void)addEventDict:(NSDictionary*)eventDict toTable:(NSString*)table timestampBucket:(SFAnalyticsTimestampBucket)timestampBucket; +- (void)addSample:(NSNumber*)value forName:(NSString*)name; +- (void)removeAllSamplesForName:(NSString*)name; +- (void)clearAllData; + +- (NSDictionary*)summaryCounts; + +@end + +#endif diff --git a/Analytics/SFAnalyticsSQLiteStore.m b/Analytics/SFAnalyticsSQLiteStore.m new file mode 100644 index 000000000..872b0d2ba --- /dev/null +++ b/Analytics/SFAnalyticsSQLiteStore.m @@ -0,0 +1,302 @@ +/* + * 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 "SFAnalyticsSQLiteStore.h" +#import "NSDate+SFAnalytics.h" +#import "Analytics/SFAnalyticsDefines.h" +#import "utilities/debugging.h" + +NSString* const SFAnalyticsColumnEventType = @"event_type"; +NSString* const SFAnalyticsColumnDate = @"timestamp"; +NSString* const SFAnalyticsColumnData = @"data"; +NSString* const SFAnalyticsUploadDate = @"upload_date"; + +@implementation SFAnalyticsSQLiteStore + ++ (instancetype)storeWithPath:(NSString*)path schema:(NSString*)schema +{ + if (![path length]) { + seccritical("Cannot init db with empty path"); + return nil; + } + if (![schema length]) { + seccritical("Cannot init db without schema"); + return nil; + } + + SFAnalyticsSQLiteStore* store = nil; + @synchronized([SFAnalyticsSQLiteStore class]) { + static NSMutableDictionary* loggingStores = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + loggingStores = [[NSMutableDictionary alloc] init]; + }); + + NSString* standardizedPath = path.stringByStandardizingPath; + store = loggingStores[standardizedPath]; + if (!store) { + store = [[self alloc] initWithPath:standardizedPath schema:schema]; + loggingStores[standardizedPath] = store; + } + NSError* error = nil; + if (![store openWithError:&error] && !(error && error.code == SQLITE_AUTH)) { + secerror("SFAnalytics: could not open db at init, will try again later. Error: %@", error); + } + } + + return store; +} + +- (void)dealloc +{ + [self close]; +} + +- (BOOL)tryToOpenDatabase +{ + if (!self.isOpen) { + NSError* error = nil; + if (![self openWithError:&error]) { + return NO; + } + secnotice("SFAnalytics", "successfully opened analytics db"); + } + return YES; +} + +- (NSInteger)successCountForEventType:(NSString*)eventType +{ + if (![self tryToOpenDatabase]) { + return 0; + } + return [[[[self select:@[SFAnalyticsColumnSuccessCount] from:SFAnalyticsTableSuccessCount where:@"event_type = ?" bindings:@[eventType]] firstObject] valueForKey:SFAnalyticsColumnSuccessCount] integerValue]; +} + +- (void)incrementSuccessCountForEventType:(NSString*)eventType +{ + if (![self tryToOpenDatabase]) { + return; + } + NSInteger successCount = [self successCountForEventType:eventType]; + NSInteger hardFailureCount = [self hardFailureCountForEventType:eventType]; + NSInteger softFailureCount = [self softFailureCountForEventType:eventType]; + [self insertOrReplaceInto:SFAnalyticsTableSuccessCount values:@{SFAnalyticsColumnEventType : eventType, SFAnalyticsColumnSuccessCount : @(successCount + 1), SFAnalyticsColumnHardFailureCount : @(hardFailureCount), SFAnalyticsColumnSoftFailureCount : @(softFailureCount)}]; +} + +- (NSInteger)hardFailureCountForEventType:(NSString*)eventType +{ + if (![self tryToOpenDatabase]) { + return 0; + } + return [[[[self select:@[SFAnalyticsColumnHardFailureCount] from:SFAnalyticsTableSuccessCount where:@"event_type = ?" bindings:@[eventType]] firstObject] valueForKey:SFAnalyticsColumnHardFailureCount] integerValue]; +} + +- (NSInteger)softFailureCountForEventType:(NSString*)eventType +{ + if (![self tryToOpenDatabase]) { + return 0; + } + return [[[[self select:@[SFAnalyticsColumnSoftFailureCount] from:SFAnalyticsTableSuccessCount where:@"event_type = ?" bindings:@[eventType]] firstObject] valueForKey:SFAnalyticsColumnSoftFailureCount] integerValue]; +} + +- (void)incrementHardFailureCountForEventType:(NSString*)eventType +{ + if (![self tryToOpenDatabase]) { + return; + } + NSInteger successCount = [self successCountForEventType:eventType]; + NSInteger hardFailureCount = [self hardFailureCountForEventType:eventType]; + NSInteger softFailureCount = [self softFailureCountForEventType:eventType]; + [self insertOrReplaceInto:SFAnalyticsTableSuccessCount values:@{SFAnalyticsColumnEventType : eventType, SFAnalyticsColumnSuccessCount : @(successCount), SFAnalyticsColumnHardFailureCount : @(hardFailureCount + 1), SFAnalyticsColumnSoftFailureCount : @(softFailureCount)}]; +} + +- (void)incrementSoftFailureCountForEventType:(NSString*)eventType +{ + if (![self tryToOpenDatabase]) { + return; + } + NSInteger successCount = [self successCountForEventType:eventType]; + NSInteger hardFailureCount = [self hardFailureCountForEventType:eventType]; + NSInteger softFailureCount = [self softFailureCountForEventType:eventType]; + [self insertOrReplaceInto:SFAnalyticsTableSuccessCount values:@{SFAnalyticsColumnEventType : eventType, SFAnalyticsColumnSuccessCount : @(successCount), SFAnalyticsColumnHardFailureCount : @(hardFailureCount), SFAnalyticsColumnSoftFailureCount : @(softFailureCount + 1)}]; +} + +- (NSDictionary*)summaryCounts +{ + if (![self tryToOpenDatabase]) { + return [NSDictionary new]; + } + NSMutableDictionary* successCountsDict = [NSMutableDictionary dictionary]; + NSArray* rows = [self selectAllFrom:SFAnalyticsTableSuccessCount where:nil bindings:nil]; + for (NSDictionary* rowDict in rows) { + NSString* eventName = rowDict[SFAnalyticsColumnEventType]; + if (!eventName) { + secinfo("SFAnalytics", "ignoring entry in success counts table without an event name"); + continue; + } + + successCountsDict[eventName] = @{SFAnalyticsTableSuccessCount : rowDict[SFAnalyticsColumnSuccessCount], SFAnalyticsColumnHardFailureCount : rowDict[SFAnalyticsColumnHardFailureCount], SFAnalyticsColumnSoftFailureCount : rowDict[SFAnalyticsColumnSoftFailureCount]}; + } + + return successCountsDict; +} + +- (NSArray*)deserializedRecords:(NSArray*)recordBlobs +{ + if (![self tryToOpenDatabase]) { + return [NSArray new]; + } + NSMutableArray* records = [NSMutableArray new]; + for (NSDictionary* row in recordBlobs) { + NSMutableDictionary* deserializedRecord = [NSPropertyListSerialization propertyListWithData:row[SFAnalyticsColumnData] options:NSPropertyListMutableContainers format:nil error:nil]; + [records addObject:deserializedRecord]; + } + return records; +} + +- (NSArray*)hardFailures +{ + if (![self tryToOpenDatabase]) { + return [NSArray new]; + } + return [self deserializedRecords:[self select:@[SFAnalyticsColumnData] from:SFAnalyticsTableHardFailures]]; +} + +- (NSArray*)softFailures +{ + if (![self tryToOpenDatabase]) { + return [NSArray new]; + } + return [self deserializedRecords:[self select:@[SFAnalyticsColumnData] from:SFAnalyticsTableSoftFailures]]; +} + +- (NSArray*)allEvents +{ + if (![self tryToOpenDatabase]) { + return [NSArray new]; + } + + [self begin]; + + NSMutableArray *all = [NSMutableArray new]; + + NSArray *hard = [self select:@[SFAnalyticsColumnDate, SFAnalyticsColumnData] from:SFAnalyticsTableHardFailures]; + [all addObjectsFromArray:hard]; + hard = nil; + + NSArray *soft = [self select:@[SFAnalyticsColumnDate, SFAnalyticsColumnData] from:SFAnalyticsTableSoftFailures]; + [all addObjectsFromArray:soft]; + soft = nil; + + NSArray *notes = [self select:@[SFAnalyticsColumnDate, SFAnalyticsColumnData] from:SFAnalyticsTableNotes]; + [all addObjectsFromArray:notes]; + notes = nil; + + [self end]; + + [all sortUsingComparator:^NSComparisonResult(NSDictionary *_Nonnull obj1, NSDictionary *_Nonnull obj2) { + NSDate *date1 = obj1[SFAnalyticsColumnDate]; + NSDate *date2 = obj2[SFAnalyticsColumnDate]; + return [date1 compare:date2]; + }]; + return [self deserializedRecords:all]; +} + +- (NSArray*)samples +{ + if (![self tryToOpenDatabase]) { + return [NSArray new]; + } + return [self select:@[SFAnalyticsColumnSampleName, SFAnalyticsColumnSampleValue] from:SFAnalyticsTableSamples]; +} + +- (void)addEventDict:(NSDictionary*)eventDict toTable:(NSString*)table timestampBucket:(SFAnalyticsTimestampBucket)bucket +{ + if (![self tryToOpenDatabase]) { + return; + } + + NSTimeInterval timestamp = [[NSDate date] timeIntervalSince1970WithBucket:bucket]; + NSError* error = nil; + NSData* serializedRecord = [NSPropertyListSerialization dataWithPropertyList:eventDict format:NSPropertyListBinaryFormat_v1_0 options:0 error:&error]; + if(!error && serializedRecord) { + [self insertOrReplaceInto:table values:@{SFAnalyticsColumnDate : @(timestamp), SFAnalyticsColumnData : serializedRecord}]; + } + if(error && !serializedRecord) { + secerror("Couldn't serialize failure record: %@", error); + } +} + +- (void)addEventDict:(NSDictionary*)eventDict toTable:(NSString*)table +{ + [self addEventDict:eventDict toTable:table timestampBucket:SFAnalyticsTimestampBucketSecond]; +} + +- (void)addSample:(NSNumber*)value forName:(NSString*)name +{ + if (![self tryToOpenDatabase]) { + return; + } + [self insertOrReplaceInto:SFAnalyticsTableSamples values:@{SFAnalyticsColumnDate : @([[NSDate date] timeIntervalSince1970]), SFAnalyticsColumnSampleName : name, SFAnalyticsColumnSampleValue : value}]; +} + +- (void)removeAllSamplesForName:(NSString*)name +{ + if (![self tryToOpenDatabase]) { + return; + } + [self deleteFrom:SFAnalyticsTableSamples where:[NSString stringWithFormat:@"name == '%@'", name] bindings:nil]; +} + +- (NSDate*)uploadDate +{ + if (![self tryToOpenDatabase]) { + return nil; // In other cases return default object but nil is better here to avoid entering the upload flow + } + return [self datePropertyForKey:SFAnalyticsUploadDate]; +} + +- (void)setUploadDate:(NSDate*)uploadDate +{ + if (![self tryToOpenDatabase]) { + return; + } + [self setDateProperty:uploadDate forKey:SFAnalyticsUploadDate]; +} + +- (void)clearAllData +{ + if (![self tryToOpenDatabase]) { + return; + } + [self deleteFrom:SFAnalyticsTableSuccessCount where:@"event_type like ?" bindings:@[@"%"]]; + [self deleteFrom:SFAnalyticsTableHardFailures where:@"id >= 0" bindings:nil]; + [self deleteFrom:SFAnalyticsTableSoftFailures where:@"id >= 0" bindings:nil]; + [self deleteFrom:SFAnalyticsTableSamples where:@"id >= 0" bindings:nil]; +} + +@end + +#endif // OBJC2 diff --git a/Analytics/SFAnalyticsSampler+Internal.h b/Analytics/SFAnalyticsSampler+Internal.h new file mode 100644 index 000000000..fdf3d3d1b --- /dev/null +++ b/Analytics/SFAnalyticsSampler+Internal.h @@ -0,0 +1,37 @@ +/* + * 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 SFAnalyticsSampler_Internal_h +#define SFAnalyticsSampler_Internal_h + +#if __OBJC2__ + +#import "SFAnalyticsSampler.h" + +@interface SFAnalyticsSampler(Internal) +- (instancetype)initWithName:(NSString*)name interval:(NSTimeInterval)interval block:(NSNumber* (^)(void))block clientClass:(Class)clientClass; +@end + +#endif // objc2 + +#endif /* SFAnalyticsSampler_private_h */ diff --git a/Analytics/SFAnalyticsSampler.h b/Analytics/SFAnalyticsSampler.h new file mode 100644 index 000000000..ddfb75f36 --- /dev/null +++ b/Analytics/SFAnalyticsSampler.h @@ -0,0 +1,44 @@ +/* + * 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 SFAnalyticsSampler_h +#define SFAnalyticsSampler_h + +#import + +@interface SFAnalyticsSampler : NSObject + +@property (nonatomic) NSTimeInterval samplingInterval; +@property (nonatomic, readonly) NSString* name; +@property (nonatomic, readonly) BOOL oncePerReport; + +- (instancetype)init NS_UNAVAILABLE; +- (NSNumber*)sampleNow; +- (void)pauseSampling; +- (void)resumeSampling; + +@end + +#endif +#endif diff --git a/Analytics/SFAnalyticsSampler.m b/Analytics/SFAnalyticsSampler.m new file mode 100644 index 000000000..034efc30b --- /dev/null +++ b/Analytics/SFAnalyticsSampler.m @@ -0,0 +1,169 @@ +/* + * 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 "SFAnalyticsSampler+Internal.h" +#import "SFAnalytics+Internal.h" +#import "SFAnalyticsDefines.h" +#import "utilities/debugging.h" +#include +#include + +@implementation SFAnalyticsSampler { + NSTimeInterval _samplingInterval; + dispatch_source_t _timer; + NSString* _name; + NSNumber* (^_block)(void); + int _notificationToken; + Class _clientClass; + BOOL _oncePerReport; + BOOL _activeTimer; +} + +@synthesize name = _name; +@synthesize samplingInterval = _samplingInterval; +@synthesize oncePerReport = _oncePerReport; + + +- (instancetype)initWithName:(NSString*)name interval:(NSTimeInterval)interval block:(NSNumber* (^)(void))block clientClass:(Class)clientClass +{ + if (self = [super init]) { + if (![clientClass isSubclassOfClass:[SFAnalytics class]]) { + secerror("SFAnalyticsSampler created without valid client class (%@)", clientClass); + return nil; + } + + if (!name || (interval < 1.0f && interval != SFAnalyticsSamplerIntervalOncePerReport) || !block) { + secerror("SFAnalyticsSampler created without proper data"); + return nil; + } + + _clientClass = clientClass; + _block = block; + _name = name; + _samplingInterval = interval; + [self newTimer]; + } + return self; +} + +- (void)newTimer +{ + if (_activeTimer) { + [self pauseSampling]; + } + + _oncePerReport = (_samplingInterval == SFAnalyticsSamplerIntervalOncePerReport); + if (_oncePerReport) { + [self setupOnceTimer]; + } else { + [self setupPeriodicTimer]; + } +} + +- (void)setupOnceTimer +{ + __weak __typeof(self) weakSelf = self; + notify_register_dispatch(SFAnalyticsFireSamplersNotification, &_notificationToken, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(int token) { + __strong __typeof(self) strongSelf = weakSelf; + if (!strongSelf) { + secnotice("SFAnalyticsSampler", "sampler went away before we could run its once-per-report block"); + notify_cancel(token); + return; + } + [[strongSelf->_clientClass logger] logMetric:strongSelf->_block() withName:strongSelf->_name oncePerReport:strongSelf->_oncePerReport]; + }); + _activeTimer = YES; +} + +- (void)setupPeriodicTimer +{ + _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); + dispatch_source_set_timer(_timer, dispatch_walltime(0, _samplingInterval * NSEC_PER_SEC), _samplingInterval * NSEC_PER_SEC, _samplingInterval * NSEC_PER_SEC / 50.0); // give 2% leeway on timer + + __weak __typeof(self) weakSelf = self; + dispatch_source_set_event_handler(_timer, ^{ + __strong __typeof(self) strongSelf = weakSelf; + if (!strongSelf) { + // TODO: can we cancel this thing from here? + secnotice("SFAnalyticsSampler", "sampler went away before we could run its once-per-report block"); + return; + } + [[strongSelf->_clientClass logger] logMetric:strongSelf->_block() withName:strongSelf->_name oncePerReport:strongSelf->_oncePerReport]; + }); + dispatch_resume(_timer); + + _activeTimer = YES; +} + +- (void)setSamplingInterval:(NSTimeInterval)interval +{ + if (interval < 1.0f && !(interval == SFAnalyticsSamplerIntervalOncePerReport)) { + secerror("SFAnalyticsSampler: interval %f is not supported", interval); + return; + } + + _samplingInterval = interval; + [self newTimer]; +} + +- (NSTimeInterval)samplingInterval { + return _samplingInterval; +} + +- (NSNumber*)sampleNow +{ + NSNumber* result = _block(); + [[_clientClass logger] logMetric:result withName:_name oncePerReport:_oncePerReport]; + return result; +} + +- (void)pauseSampling +{ + if (!_activeTimer) { + return; + } + + if (_oncePerReport) { + notify_cancel(_notificationToken); + _notificationToken = 0; + } else { + dispatch_source_cancel(_timer); + } + _activeTimer = NO; +} + +- (void)resumeSampling +{ + [self newTimer]; +} + +- (void)dealloc +{ + [self pauseSampling]; +} + +@end + +#endif diff --git a/Analytics/SQLite/SFObjCType.h b/Analytics/SQLite/SFObjCType.h index 61acd4b6c..adafb7a2f 100644 --- a/Analytics/SQLite/SFObjCType.h +++ b/Analytics/SQLite/SFObjCType.h @@ -21,6 +21,11 @@ * @APPLE_LICENSE_HEADER_END@ */ +#ifndef SECURITY_SFSQL_OBJCTYPE_H +#define SECURITY_SFSQL_OBJCTYPE_H 1 + +#if __OBJC2__ + #import typedef NS_ENUM(NSInteger, SFObjCTypeCode) { @@ -86,3 +91,6 @@ typedef NS_ENUM(NSInteger, SFObjCTypeFlag) { - (void)getBytes:(void *)bytes forObject:(id)object; @end + +#endif +#endif /* SECURITY_SFSQL_OBJCTYPE_H */ diff --git a/Analytics/SQLite/SFObjCType.m b/Analytics/SQLite/SFObjCType.m index 98257f2b3..dcc27ff5e 100644 --- a/Analytics/SQLite/SFObjCType.m +++ b/Analytics/SQLite/SFObjCType.m @@ -21,8 +21,9 @@ * @APPLE_LICENSE_HEADER_END@ */ -#import "SFObjCType.h" +#if __OBJC2__ +#import "SFObjCType.h" static NSArray *_SFObjCTypesByCode = nil; @@ -167,3 +168,5 @@ - (void)getBytes:(void *)bytes forObject:(id)object { } @end + +#endif diff --git a/Analytics/SQLite/SFSQLite.h b/Analytics/SQLite/SFSQLite.h index 9a5a4b200..0ced94718 100644 --- a/Analytics/SQLite/SFSQLite.h +++ b/Analytics/SQLite/SFSQLite.h @@ -23,6 +23,11 @@ // Header exposed for unit testing only +#ifndef SECURITY_SFSQL_H +#define SECURITY_SFSQL_H 1 + +#if __OBJC2__ + #import #import @@ -39,7 +44,7 @@ typedef NS_ENUM(NSInteger, SFSQLiteSynchronousMode) { SFSQLiteSynchronousModeFull = 2 }; -@protocol SFSQLiteDelegate +@protocol SFSQLiteDelegate @property (nonatomic, readonly) SInt32 userVersion; - (BOOL)migrateDatabase:(SFSQLite *)db fromVersion:(SInt32)version; @@ -47,6 +52,7 @@ typedef NS_ENUM(NSInteger, SFSQLiteSynchronousMode) { // Wrapper around the SQLite API. Typically subclassed to add table accessor methods. @interface SFSQLite : NSObject { +@private id _delegate; NSString* _path; NSString* _schema; @@ -62,7 +68,6 @@ typedef NS_ENUM(NSInteger, SFSQLiteSynchronousMode) { NSMutableDictionary* _unitTestOverrides; #endif BOOL _hasMigrated; - BOOL _shouldVacuum; BOOL _corrupt; BOOL _traced; } @@ -77,7 +82,6 @@ typedef NS_ENUM(NSInteger, SFSQLiteSynchronousMode) { @property (nonatomic, assign) SFSQLiteSynchronousMode synchronousMode; @property (nonatomic, readonly) BOOL isOpen; @property (nonatomic, readonly) BOOL hasMigrated; -@property (nonatomic, assign) BOOL shouldVacuum; // vacuum the db on open (default:YES) @property (nonatomic, assign) BOOL traced; @property (nonatomic, strong) id delegate; @@ -103,9 +107,6 @@ typedef NS_ENUM(NSInteger, SFSQLiteSynchronousMode) { - (void)analyze; - (void)vacuum; -// Raise an exception. Including any database error in the description and removing the databse if it's corrupt. -- (void)raise:(NSString *)format, ... NS_FORMAT_FUNCTION(1, 2); - // The rowID assigned to the last record inserted into the database. - (SFSQLiteRowID)lastInsertRowID; @@ -113,8 +114,8 @@ typedef NS_ENUM(NSInteger, SFSQLiteSynchronousMode) { - (int)changes; // Execute one-or-more queries. Use prepared statements for anything performance critical. -- (void)executeSQL:(NSString *)format, ... NS_FORMAT_FUNCTION(1, 2); -- (void)executeSQL:(NSString *)format arguments:(va_list)args NS_FORMAT_FUNCTION(1, 0); +- (BOOL)executeSQL:(NSString *)format, ... NS_FORMAT_FUNCTION(1, 2); +- (BOOL)executeSQL:(NSString *)format arguments:(va_list)args NS_FORMAT_FUNCTION(1, 0); // Prepared statement pool accessors. Statements must be reset after they're used. - (SFSQLiteStatement *)statementForSQL:(NSString *)SQL; @@ -150,3 +151,6 @@ typedef NS_ENUM(NSInteger, SFSQLiteSynchronousMode) { - (SInt32)dbUserVersion; @end + +#endif /* __OBJC2__ */ +#endif /* SECURITY_SFSQL_H */ diff --git a/Analytics/SQLite/SFSQLite.m b/Analytics/SQLite/SFSQLite.m index 4590e889a..fcde86f7f 100644 --- a/Analytics/SQLite/SFSQLite.m +++ b/Analytics/SQLite/SFSQLite.m @@ -21,20 +21,20 @@ * @APPLE_LICENSE_HEADER_END@ */ +#if __OBJC2__ + #import "SFSQLite.h" #import "SFSQLiteStatement.h" #include #include - +#import "utilities/debugging.h" +#include #define kSFSQLiteBusyTimeout (5*60*1000) -// Vaccuum our databases approximately once a week -#define kCKSQLVacuumInterval ((60*60*24)*7) -#define kSFSQLiteLastVacuumKey @"LastVacuum" - #define kSFSQLiteSchemaVersionKey @"SchemaVersion" #define kSFSQLiteCreatedDateKey @"Created" +#define kSFSQLiteAutoVacuumFull 1 static NSString *const kSFSQLiteCreatePropertiesTableSQL = @"create table if not exists Properties (\n" @@ -42,10 +42,6 @@ @" value text\n" @");\n"; -@interface SFSQLiteError : NSObject -+ (void)raise:(NSString *)reason code:(int)code extended:(int)extended; -@end - NSArray *SFSQLiteJournalSuffixes() { return @[@"-journal", @"-wal", @"-shm"]; @@ -68,6 +64,7 @@ @interface SFSQLite () @property (nonatomic, assign) BOOL corrupt; @property (nonatomic, readonly, strong) NSMutableDictionary *statementsBySQL; @property (nonatomic, strong) NSDateFormatter *dateFormatter; +@property (nonatomic, strong) NSDateFormatter *oldDateFormatter; @end @@ -224,20 +221,28 @@ @implementation SFSQLite @synthesize userVersion = _userVersion; @synthesize synchronousMode = _synchronousMode; @synthesize hasMigrated = _hasMigrated; -@synthesize shouldVacuum = _shouldVacuum; @synthesize traced = _traced; @synthesize db = _db; @synthesize openCount = _openCount; @synthesize corrupt = _corrupt; @synthesize statementsBySQL = _statementsBySQL; @synthesize dateFormatter = _dateFormatter; +@synthesize oldDateFormatter = _oldDateFormatter; #if DEBUG @synthesize unitTestOverrides = _unitTestOverrides; #endif - (instancetype)initWithPath:(NSString *)path schema:(NSString *)schema { + if (![path length]) { + seccritical("Cannot init db with empty path"); + return nil; + } + if (![schema length]) { + seccritical("Cannot init db without schema"); + return nil; + } + if ((self = [super init])) { - NSAssert([path length], @"Can't init a database with a zero-length path"); _path = path; _schema = schema; _schemaVersion = [self _createSchemaHash]; @@ -245,7 +250,6 @@ - (instancetype)initWithPath:(NSString *)path schema:(NSString *)schema { _objectClassPrefix = @"CK"; _synchronousMode = SFSQLiteSynchronousModeNormal; _hasMigrated = NO; - _shouldVacuum = YES; } return self; } @@ -289,18 +293,25 @@ - (BOOL)isOpen { return _db != NULL; } -- (void)_periodicVacuum { - // "When the auto-vacuum mode is 1 or "full", the freelist pages are moved to the end of the database file and the database file is truncated to remove the freelist pages at every transaction commit. - // Note, however, that auto-vacuum only truncates the freelist pages from the file. Auto-vacuum does not defragment the database nor repack individual database pages the way that the VACUUM command does. - // In fact, because it moves pages around within the file, auto-vacuum can actually make fragmentation worse." - // https://sqlite.org/pragma.html#pragma_auto_vacuum - NSDate *lastVacuumDate = [NSDate dateWithTimeIntervalSinceReferenceDate:[[self propertyForKey:kSFSQLiteLastVacuumKey] floatValue]]; - if ([lastVacuumDate timeIntervalSinceNow] < -(kCKSQLVacuumInterval)) { - [self executeSQL:@"VACUUM"]; - - NSString *vacuumDateString = [NSString stringWithFormat:@"%f", [[NSDate date] timeIntervalSinceReferenceDate]]; - [self setProperty:vacuumDateString forKey:kSFSQLiteLastVacuumKey]; - } +/* + Best-effort attempts to set/correct filesystem permissions. + May fail when we don't own DB which means we must wait for them to update permissions, + or file does not exist yet which is okay because db will exist and the aux files inherit permissions +*/ +- (void)attemptProperDatabasePermissions +{ +#if TARGET_OS_IPHONE + NSFileManager* fm = [NSFileManager defaultManager]; + [fm setAttributes:@{NSFilePosixPermissions : [NSNumber numberWithShort:0666]} + ofItemAtPath:_path + error:nil]; + [fm setAttributes:@{NSFilePosixPermissions : [NSNumber numberWithShort:0666]} + ofItemAtPath:[NSString stringWithFormat:@"%@-wal",_path] + error:nil]; + [fm setAttributes:@{NSFilePosixPermissions : [NSNumber numberWithShort:0666]} + ofItemAtPath:[NSString stringWithFormat:@"%@-shm",_path] + error:nil]; +#endif } - (BOOL)openWithError:(NSError **)error { @@ -329,9 +340,13 @@ - (BOOL)openWithError:(NSError **)error { #endif int rc = sqlite3_open_v2([arcSafePath fileSystemRepresentation], &_db, flags, NULL); if (rc != SQLITE_OK) { - localError = [NSError errorWithDomain:NSCocoaErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Error opening db at %@, rc=%d(0x%x)", _path, rc, rc]}]; + localError = [NSError errorWithDomain:NSCocoaErrorDomain code:rc userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Error opening db at %@, rc=%d(0x%x)", _path, rc, rc]}]; goto done; } + + // Filesystem foo for multiple daemons from different users + [self attemptProperDatabasePermissions]; + sqlite3_extended_result_codes(_db, 1); rc = sqlite3_busy_timeout(_db, kSFSQLiteBusyTimeout); if (rc != SQLITE_OK) { @@ -339,9 +354,18 @@ - (BOOL)openWithError:(NSError **)error { } // You don't argue with the Ben: rdar://12685305 - [self executeSQL:@"pragma journal_mode = WAL"]; - [self executeSQL:@"pragma synchronous = %@", [self _synchronousModeString]]; - [self executeSQL:@"pragma auto_vacuum = FULL"]; + if (![self executeSQL:@"pragma journal_mode = WAL"]) { + goto done; + } + if (![self executeSQL:@"pragma synchronous = %@", [self _synchronousModeString]]) { + goto done; + } + if ([self autoVacuumSetting] != kSFSQLiteAutoVacuumFull) { + /* After changing the auto_vacuum setting the DB must be vacuumed */ + if (![self executeSQL:@"pragma auto_vacuum = FULL"] || ![self executeSQL:@"VACUUM"]) { + goto done; + } + } // rdar://problem/32168789 // [self executeSQL:@"pragma foreign_keys = 1"]; @@ -397,8 +421,6 @@ - (BOOL)openWithError:(NSError **)error { } #endif - if (self.shouldVacuum) [self _periodicVacuum]; - if (create || _hasMigrated) { [self setProperty:self.schemaVersion forKey:kSFSQLiteSchemaVersionKey]; if (self.userVersion) { @@ -410,7 +432,15 @@ - (BOOL)openWithError:(NSError **)error { success = YES; done: + if (!success) { + sqlite3_close_v2(_db); + _db = nil; + } + if (!success && error) { + if (!localError) { + localError = [NSError errorWithDomain:NSCocoaErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Error opening db at %@", _path]}]; + } *error = localError; } return success; @@ -418,8 +448,9 @@ - (BOOL)openWithError:(NSError **)error { - (void)open { NSError *error; - if (![self openWithError:&error]) { - [self raise:@"Error opening db at %@: %@", self.path, error]; + if (![self openWithError:&error] && !(error && error.code == SQLITE_AUTH)) { + secerror("sfsqlite: Error opening db at %@: %@", self.path, error); + return; } } @@ -432,7 +463,8 @@ - (void)close { [self removeAllStatements]; if (sqlite3_close(_db)) { - [self raise:@"Error closing database"]; + secerror("sfsqlite: Error closing database"); + return; } _db = NULL; } @@ -468,44 +500,10 @@ - (void)vacuum { [self executeSQL:@"vacuum"]; } -- (void)raise:(NSString *)format, ... { - va_list args; - va_start(args, format); - - NSString *reason = [[NSString alloc] initWithFormat:format arguments:args]; - - int code = 0; - int extendedCode = 0; - if (_db) { - code = sqlite3_errcode(_db) & 0xFF; - extendedCode = sqlite3_extended_errcode(_db); - const char *errmsg = sqlite3_errmsg(_db); - - NSDictionary *dbAttrs = [[NSFileManager defaultManager] attributesOfItemAtPath:self.path error:NULL]; - NSDictionary *fsAttrs = [[NSFileManager defaultManager] attributesOfFileSystemForPath:self.path error:NULL]; - reason = [reason stringByAppendingFormat:@" - errcode:%04x, msg:\"%s\", size: %@, path:%@, fs:%@/%@", extendedCode, errmsg, dbAttrs[NSFileSize], _path, fsAttrs[NSFileSystemFreeSize], fsAttrs[NSFileSystemSize]]; - - if (!_corrupt && (code == SQLITE_CORRUPT || code == SQLITE_NOTADB)) { - _corrupt = YES; - - @try { - [self close]; - } @catch (NSException *x) { - NSLog(@"Warn: Error closing corrupt db: %@", x); - } - - [self remove]; - } - } - - va_end(args); - - [SFSQLiteError raise:reason code:code extended:extendedCode]; -} - - (SFSQLiteRowID)lastInsertRowID { if (!_db) { - [self raise:@"Database is closed"]; + secerror("sfsqlite: Database is closed"); + return -1; } return sqlite3_last_insert_rowid(_db); @@ -514,33 +512,42 @@ - (SFSQLiteRowID)lastInsertRowID { - (int)changes { if (!_db) { - [self raise:@"Database is closed"]; + secerror("sfsqlite: Database is closed"); + return -1; } return sqlite3_changes(_db); } -- (void)executeSQL:(NSString *)format, ... { +- (BOOL)executeSQL:(NSString *)format, ... { va_list args; va_start(args, format); - [self executeSQL:format arguments:args]; + BOOL result = [self executeSQL:format arguments:args]; va_end(args); + return result; } -- (void)executeSQL:(NSString *)format arguments:(va_list)args { +- (BOOL)executeSQL:(NSString *)format arguments:(va_list)args { NS_VALID_UNTIL_END_OF_SCOPE NSString *SQL = [[NSString alloc] initWithFormat:format arguments:args]; if (!_db) { - [self raise:@"Database is closed"]; + secerror("sfsqlite: Database is closed"); + return NO; } int execRet = sqlite3_exec(_db, [SQL UTF8String], NULL, NULL, NULL); if (execRet != SQLITE_OK) { - [self raise:@"Error executing SQL: \"%@\" (%d)", SQL, execRet]; + if (execRet != SQLITE_AUTH && execRet != SQLITE_READONLY) { + secerror("sfsqlite: Error executing SQL: \"%@\" (%d)", SQL, execRet); + } + return NO; } + + return YES; } - (SFSQLiteStatement *)statementForSQL:(NSString *)SQL { if (!_db) { - [self raise:@"Database is closed"]; + secerror("sfsqlite: Database is closed"); + return nil; } SFSQLiteStatement *statement = _statementsBySQL[SQL]; @@ -550,7 +557,8 @@ - (SFSQLiteStatement *)statementForSQL:(NSString *)SQL { sqlite3_stmt *handle = NULL; NS_VALID_UNTIL_END_OF_SCOPE NSString *arcSafeSQL = SQL; if (sqlite3_prepare_v2(_db, [arcSafeSQL UTF8String], -1, &handle, NULL)) { - [self raise:@"Error preparing statement: %@", SQL]; + secerror("Error preparing statement: %@", SQL); + return nil; } statement = [[SFSQLiteStatement alloc] initWithSQLite:self SQL:SQL handle:handle]; @@ -585,7 +593,10 @@ - (void)dropAllTables { } - (NSString *)propertyForKey:(NSString *)key { - NSAssert(key, @"Null key"); + if (![key length]) { + secerror("SFSQLite: attempt to retrieve property without a key"); + return nil; + } NSString *value = nil; @@ -600,7 +611,10 @@ - (NSString *)propertyForKey:(NSString *)key { } - (void)setProperty:(NSString *)value forKey:(NSString *)key { - NSAssert(key, @"Null key"); + if (![key length]) { + secerror("SFSQLite: attempt to set property without a key"); + return; + } if (value) { SFSQLiteStatement *statement = [self statementForSQL:@"insert or replace into Properties (key, value) values (?,?)"]; @@ -616,16 +630,29 @@ - (void)setProperty:(NSString *)value forKey:(NSString *)key { - (NSDateFormatter *)dateFormatter { if (!_dateFormatter) { NSDateFormatter* dateFormatter = [NSDateFormatter new]; - dateFormatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ssZZZZZ"; + dateFormatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss.SSSZZZZ"; _dateFormatter = dateFormatter; } return _dateFormatter; } +- (NSDateFormatter *)oldDateFormatter { + if (!_oldDateFormatter) { + NSDateFormatter* dateFormatter = [NSDateFormatter new]; + dateFormatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ssZZZZZ"; + _oldDateFormatter = dateFormatter; + } + return _oldDateFormatter; +} + - (NSDate *)datePropertyForKey:(NSString *)key { NSString *dateStr = [self propertyForKey:key]; if (dateStr.length) { - return [self.dateFormatter dateFromString:dateStr]; + NSDate *date = [self.dateFormatter dateFromString:dateStr]; + if (date == NULL) { + date = [self.oldDateFormatter dateFromString:dateStr]; + } + return date; } return nil; } @@ -639,7 +666,9 @@ - (void)setDateProperty:(NSDate *)value forKey:(NSString *)key { } - (void)removePropertyForKey:(NSString *)key { - NSAssert(key, @"Null key"); + if (![key length]) { + return; + } SFSQLiteStatement *statement = [self statementForSQL:@"delete from Properties where key = ?"]; [statement bindText:key atIndex:0]; @@ -698,7 +727,7 @@ - (void)select:(NSArray *)columns from:(NSString *)tableName where:(NSString *)w NSString *orderByString = [orderBy componentsJoinedByString:@", "]; [SQL appendFormat:@" order by %@", orderByString]; } - if (limit) { + if (limit != nil) { [SQL appendFormat:@" limit %ld", (long)limit.integerValue]; } @@ -735,7 +764,7 @@ - (void)selectFrom:(NSString *)tableName where:(NSString *)whereSQL bindings:(NS NSString *orderByString = [orderBy componentsJoinedByString:@", "]; [SQL appendFormat:@" order by %@", orderByString]; } - if (limit) { + if (limit != nil) { [SQL appendFormat:@" limit %ld", (long)limit.integerValue]; } @@ -767,7 +796,7 @@ - (NSArray *)selectFrom:(NSString *)tableName where:(NSString *)whereSQL binding if (whereSQL.length) { [SQL appendFormat:@" where %@", whereSQL]; } - if (limit) { + if (limit != nil) { [SQL appendFormat:@" limit %ld", (long)limit.integerValue]; } @@ -784,16 +813,18 @@ - (NSArray *)selectFrom:(NSString *)tableName where:(NSString *)whereSQL binding } - (void)update:(NSString *)tableName set:(NSString *)setSQL where:(NSString *)whereSQL bindings:(NSArray *)whereBindings limit:(NSNumber *)limit { + if (![setSQL length]) { + return; + } + NSMutableString *SQL = [[NSMutableString alloc] init]; [SQL appendFormat:@"update %@", tableName]; - - NSAssert(setSQL.length > 0, @"null set expression"); [SQL appendFormat:@" set %@", setSQL]; if (whereSQL.length) { [SQL appendFormat:@" where %@", whereSQL]; } - if (limit) { + if (limit != nil) { [SQL appendFormat:@" limit %ld", (long)limit.integerValue]; } @@ -880,7 +911,8 @@ - (void)deleteFrom:(NSString *)tableName where:(NSString *)whereSQL bindings:(NS - (NSString *)_tableNameForClass:(Class)objectClass { NSString *className = [objectClass SFSQLiteClassName]; if (![className hasPrefix:_objectClassPrefix]) { - [NSException raise:NSInvalidArgumentException format:@"Object class \"%@\" does not have prefix \"%@\"", className, _objectClassPrefix]; + secerror("sfsqlite: %@", [NSString stringWithFormat:@"Object class \"%@\" does not have prefix \"%@\"", className, _objectClassPrefix]); + return nil; } return [className substringFromIndex:_objectClassPrefix.length]; } @@ -896,172 +928,17 @@ - (SInt32)dbUserVersion { return userVersion; } -@end - +- (SInt32)autoVacuumSetting { + SInt32 vacuumMode = 0; + SFSQLiteStatement *statement = [self statementForSQL:@"pragma auto_vacuum"]; + while ([statement step]) { + vacuumMode = [statement intAtIndex:0]; + } + [statement reset]; -#define SFSQLiteErrorRaiseMethod(SQLiteError) + (void)SQLiteError:(NSString *)reason { [NSException raise:NSGenericException format:@"%@", reason]; } -#define SFSQLiteErrorCase(SQLiteError) case SQLITE_ ## SQLiteError: [self SQLiteError:reason]; break - -@implementation SFSQLiteError - -// SQLite error codes -SFSQLiteErrorRaiseMethod(ERROR) -SFSQLiteErrorRaiseMethod(INTERNAL) -SFSQLiteErrorRaiseMethod(PERM) -SFSQLiteErrorRaiseMethod(ABORT) -SFSQLiteErrorRaiseMethod(BUSY) -SFSQLiteErrorRaiseMethod(LOCKED) -SFSQLiteErrorRaiseMethod(NOMEM) -SFSQLiteErrorRaiseMethod(READONLY) -SFSQLiteErrorRaiseMethod(INTERRUPT) -SFSQLiteErrorRaiseMethod(IOERR) -SFSQLiteErrorRaiseMethod(CORRUPT) -SFSQLiteErrorRaiseMethod(NOTFOUND) -SFSQLiteErrorRaiseMethod(FULL) -SFSQLiteErrorRaiseMethod(CANTOPEN) -SFSQLiteErrorRaiseMethod(PROTOCOL) -SFSQLiteErrorRaiseMethod(SCHEMA) -SFSQLiteErrorRaiseMethod(TOOBIG) -SFSQLiteErrorRaiseMethod(CONSTRAINT) -SFSQLiteErrorRaiseMethod(MISMATCH) -SFSQLiteErrorRaiseMethod(MISUSE) -SFSQLiteErrorRaiseMethod(RANGE) -SFSQLiteErrorRaiseMethod(NOTADB) - -// SQLite extended error codes -SFSQLiteErrorRaiseMethod(IOERR_READ) -SFSQLiteErrorRaiseMethod(IOERR_SHORT_READ) -SFSQLiteErrorRaiseMethod(IOERR_WRITE) -SFSQLiteErrorRaiseMethod(IOERR_FSYNC) -SFSQLiteErrorRaiseMethod(IOERR_DIR_FSYNC) -SFSQLiteErrorRaiseMethod(IOERR_TRUNCATE) -SFSQLiteErrorRaiseMethod(IOERR_FSTAT) -SFSQLiteErrorRaiseMethod(IOERR_UNLOCK) -SFSQLiteErrorRaiseMethod(IOERR_RDLOCK) -SFSQLiteErrorRaiseMethod(IOERR_DELETE) -SFSQLiteErrorRaiseMethod(IOERR_BLOCKED) -SFSQLiteErrorRaiseMethod(IOERR_NOMEM) -SFSQLiteErrorRaiseMethod(IOERR_ACCESS) -SFSQLiteErrorRaiseMethod(IOERR_CHECKRESERVEDLOCK) -SFSQLiteErrorRaiseMethod(IOERR_LOCK) -SFSQLiteErrorRaiseMethod(IOERR_CLOSE) -SFSQLiteErrorRaiseMethod(IOERR_DIR_CLOSE) -SFSQLiteErrorRaiseMethod(IOERR_SHMOPEN) -SFSQLiteErrorRaiseMethod(IOERR_SHMSIZE) -SFSQLiteErrorRaiseMethod(IOERR_SHMLOCK) -SFSQLiteErrorRaiseMethod(IOERR_SHMMAP) -SFSQLiteErrorRaiseMethod(IOERR_SEEK) -SFSQLiteErrorRaiseMethod(IOERR_DELETE_NOENT) -SFSQLiteErrorRaiseMethod(IOERR_MMAP) -SFSQLiteErrorRaiseMethod(IOERR_GETTEMPPATH) -SFSQLiteErrorRaiseMethod(IOERR_CONVPATH) -SFSQLiteErrorRaiseMethod(LOCKED_SHAREDCACHE) -SFSQLiteErrorRaiseMethod(BUSY_RECOVERY) -SFSQLiteErrorRaiseMethod(BUSY_SNAPSHOT) -SFSQLiteErrorRaiseMethod(CANTOPEN_NOTEMPDIR) -SFSQLiteErrorRaiseMethod(CANTOPEN_ISDIR) -SFSQLiteErrorRaiseMethod(CANTOPEN_FULLPATH) -SFSQLiteErrorRaiseMethod(CANTOPEN_CONVPATH) -SFSQLiteErrorRaiseMethod(CORRUPT_VTAB) -SFSQLiteErrorRaiseMethod(READONLY_RECOVERY) -SFSQLiteErrorRaiseMethod(READONLY_CANTLOCK) -SFSQLiteErrorRaiseMethod(READONLY_ROLLBACK) -SFSQLiteErrorRaiseMethod(READONLY_DBMOVED) -SFSQLiteErrorRaiseMethod(ABORT_ROLLBACK) -SFSQLiteErrorRaiseMethod(CONSTRAINT_CHECK) -SFSQLiteErrorRaiseMethod(CONSTRAINT_COMMITHOOK) -SFSQLiteErrorRaiseMethod(CONSTRAINT_FOREIGNKEY) -SFSQLiteErrorRaiseMethod(CONSTRAINT_FUNCTION) -SFSQLiteErrorRaiseMethod(CONSTRAINT_NOTNULL) -SFSQLiteErrorRaiseMethod(CONSTRAINT_PRIMARYKEY) -SFSQLiteErrorRaiseMethod(CONSTRAINT_TRIGGER) -SFSQLiteErrorRaiseMethod(CONSTRAINT_UNIQUE) -SFSQLiteErrorRaiseMethod(CONSTRAINT_VTAB) -SFSQLiteErrorRaiseMethod(CONSTRAINT_ROWID) -SFSQLiteErrorRaiseMethod(NOTICE_RECOVER_WAL) -SFSQLiteErrorRaiseMethod(NOTICE_RECOVER_ROLLBACK) - -+ (void)raise:(NSString *)reason code:(int)code extended:(int)extended { - switch(extended) { - SFSQLiteErrorCase(IOERR_READ); - SFSQLiteErrorCase(IOERR_SHORT_READ); - SFSQLiteErrorCase(IOERR_WRITE); - SFSQLiteErrorCase(IOERR_FSYNC); - SFSQLiteErrorCase(IOERR_DIR_FSYNC); - SFSQLiteErrorCase(IOERR_TRUNCATE); - SFSQLiteErrorCase(IOERR_FSTAT); - SFSQLiteErrorCase(IOERR_UNLOCK); - SFSQLiteErrorCase(IOERR_RDLOCK); - SFSQLiteErrorCase(IOERR_DELETE); - SFSQLiteErrorCase(IOERR_BLOCKED); - SFSQLiteErrorCase(IOERR_NOMEM); - SFSQLiteErrorCase(IOERR_ACCESS); - SFSQLiteErrorCase(IOERR_CHECKRESERVEDLOCK); - SFSQLiteErrorCase(IOERR_LOCK); - SFSQLiteErrorCase(IOERR_CLOSE); - SFSQLiteErrorCase(IOERR_DIR_CLOSE); - SFSQLiteErrorCase(IOERR_SHMOPEN); - SFSQLiteErrorCase(IOERR_SHMSIZE); - SFSQLiteErrorCase(IOERR_SHMLOCK); - SFSQLiteErrorCase(IOERR_SHMMAP); - SFSQLiteErrorCase(IOERR_SEEK); - SFSQLiteErrorCase(IOERR_DELETE_NOENT); - SFSQLiteErrorCase(IOERR_MMAP); - SFSQLiteErrorCase(IOERR_GETTEMPPATH); - SFSQLiteErrorCase(IOERR_CONVPATH); - SFSQLiteErrorCase(LOCKED_SHAREDCACHE); - SFSQLiteErrorCase(BUSY_RECOVERY); - SFSQLiteErrorCase(BUSY_SNAPSHOT); - SFSQLiteErrorCase(CANTOPEN_NOTEMPDIR); - SFSQLiteErrorCase(CANTOPEN_ISDIR); - SFSQLiteErrorCase(CANTOPEN_FULLPATH); - SFSQLiteErrorCase(CANTOPEN_CONVPATH); - SFSQLiteErrorCase(CORRUPT_VTAB); - SFSQLiteErrorCase(READONLY_RECOVERY); - SFSQLiteErrorCase(READONLY_CANTLOCK); - SFSQLiteErrorCase(READONLY_ROLLBACK); - SFSQLiteErrorCase(READONLY_DBMOVED); - SFSQLiteErrorCase(ABORT_ROLLBACK); - SFSQLiteErrorCase(CONSTRAINT_CHECK); - SFSQLiteErrorCase(CONSTRAINT_COMMITHOOK); - SFSQLiteErrorCase(CONSTRAINT_FOREIGNKEY); - SFSQLiteErrorCase(CONSTRAINT_FUNCTION); - SFSQLiteErrorCase(CONSTRAINT_NOTNULL); - SFSQLiteErrorCase(CONSTRAINT_PRIMARYKEY); - SFSQLiteErrorCase(CONSTRAINT_TRIGGER); - SFSQLiteErrorCase(CONSTRAINT_UNIQUE); - SFSQLiteErrorCase(CONSTRAINT_VTAB); - SFSQLiteErrorCase(CONSTRAINT_ROWID); - SFSQLiteErrorCase(NOTICE_RECOVER_WAL); - SFSQLiteErrorCase(NOTICE_RECOVER_ROLLBACK); - default: break; - } - switch(code) { - SFSQLiteErrorCase(ERROR); - SFSQLiteErrorCase(INTERNAL); - SFSQLiteErrorCase(PERM); - SFSQLiteErrorCase(ABORT); - SFSQLiteErrorCase(BUSY); - SFSQLiteErrorCase(LOCKED); - SFSQLiteErrorCase(NOMEM); - SFSQLiteErrorCase(READONLY); - SFSQLiteErrorCase(INTERRUPT); - SFSQLiteErrorCase(IOERR); - SFSQLiteErrorCase(CORRUPT); - SFSQLiteErrorCase(NOTFOUND); - SFSQLiteErrorCase(FULL); - SFSQLiteErrorCase(CANTOPEN); - SFSQLiteErrorCase(PROTOCOL); - SFSQLiteErrorCase(SCHEMA); - SFSQLiteErrorCase(TOOBIG); - SFSQLiteErrorCase(CONSTRAINT); - SFSQLiteErrorCase(MISMATCH); - SFSQLiteErrorCase(MISUSE); - SFSQLiteErrorCase(RANGE); - SFSQLiteErrorCase(NOTADB); - default: break; - } - [NSException raise:NSGenericException format:@"%@", reason]; + return vacuumMode; } @end + +#endif diff --git a/Analytics/SQLite/SFSQLiteStatement.h b/Analytics/SQLite/SFSQLiteStatement.h index 15ddb278c..01ae854f1 100644 --- a/Analytics/SQLite/SFSQLiteStatement.h +++ b/Analytics/SQLite/SFSQLiteStatement.h @@ -21,6 +21,11 @@ * @APPLE_LICENSE_HEADER_END@ */ +#ifndef SECURITY_SFSQLSTATEMENT_H +#define SECURITY_SFSQLSTATEMENT_H 1 + +#if __OBJC2__ + #import #import @@ -70,3 +75,6 @@ - (NSDictionary *)allObjectsByColumnName; @end + +#endif /* __OBJC2__ */ +#endif /* SECURITY_SFSQLSTATEMENT_H */ diff --git a/Analytics/SQLite/SFSQLiteStatement.m b/Analytics/SQLite/SFSQLiteStatement.m index c8de43a8b..ecc9269a1 100644 --- a/Analytics/SQLite/SFSQLiteStatement.m +++ b/Analytics/SQLite/SFSQLiteStatement.m @@ -21,9 +21,13 @@ * @APPLE_LICENSE_HEADER_END@ */ +#if __OBJC2__ + +#import #import "SFSQLite.h" #import "SFSQLiteStatement.h" #import "SFObjCType.h" +#import "utilities/debugging.h" @interface SFSQLiteStatement () @property (nonatomic, strong) NSMutableArray *temporaryBoundObjects; @@ -47,13 +51,13 @@ - (id)initWithSQLite:(SFSQLite *)SQLite SQL:(NSString *)SQL handle:(sqlite3_stmt } - (void)finalizeStatement { - SFSQLite *strongSQLite = _SQLite; - if (!_reset) { - [strongSQLite raise: @"Statement not reset after last use: \"%@\"", _SQL]; + secerror("sfsqlite: Statement not reset after last use: \"%@\"", _SQL); + return; } if (sqlite3_finalize(_handle)) { - [strongSQLite raise:@"Error finalizing prepared statement: \"%@\"", _SQL]; + secerror("sfsqlite: Error finalizing prepared statement: \"%@\"", _SQL); + return; } } @@ -79,21 +83,21 @@ - (BOOL)step { return NO; } else { [self resetAfterStepError]; - [_SQLite raise:@"Failed to step (%d): \"%@\"", rc, _SQL]; + secerror("sfsqlite: Failed to step (%d): \"%@\"", rc, _SQL); return NO; } } - (void)reset { - SFSQLite *strongSQLite = _SQLite; - if (!_reset) { if (sqlite3_reset(_handle)) { - [strongSQLite raise:@"Error resetting prepared statement: \"%@\"", _SQL]; + secerror("sfsqlite: Error resetting prepared statement: \"%@\"", _SQL); + return; } if (sqlite3_clear_bindings(_handle)) { - [strongSQLite raise:@"Error clearing prepared statement bindings: \"%@\"", _SQL]; + secerror("sfsqlite: Error clearing prepared statement bindings: \"%@\"", _SQL); + return; } [_temporaryBoundObjects removeAllObjects]; _reset = YES; @@ -101,36 +105,52 @@ - (void)reset { } - (void)bindInt:(SInt32)value atIndex:(NSUInteger)index { - NSAssert(_reset, @"Statement is not reset: \"%@\"", _SQL); + if (!_reset) { + secerror("sfsqlite: Statement is not reset: \"%@\"", _SQL); + return; + } if (sqlite3_bind_int(_handle, (int)index+1, value)) { - [_SQLite raise:@"Error binding int at %ld: \"%@\"", (unsigned long)index, _SQL]; + secerror("sfsqlite: Error binding int at %ld: \"%@\"", (unsigned long)index, _SQL); + return; } } - (void)bindInt64:(SInt64)value atIndex:(NSUInteger)index { - NSAssert(_reset, @"Statement is not reset: \"%@\"", _SQL); + if (!_reset) { + secerror("sfsqlite: Statement is not reset: \"%@\"", _SQL); + return; + } if (sqlite3_bind_int64(_handle, (int)index+1, value)) { - [_SQLite raise:@"Error binding int64 at %ld: \"%@\"", (unsigned long)index, _SQL]; + secerror("sfsqlite: Error binding int64 at %ld: \"%@\"", (unsigned long)index, _SQL); + return; } } - (void)bindDouble:(double)value atIndex:(NSUInteger)index { - NSAssert(_reset, @"Statement is not reset: \"%@\"", _SQL); + if (!_reset) { + secerror("sfsqlite: Statement is not reset: \"%@\"", _SQL); + return; + } if (sqlite3_bind_double(_handle, (int)index+1, value)) { - [_SQLite raise:@"Error binding double at %ld: \"%@\"", (unsigned long)index, _SQL]; + secerror("sfsqlite: Error binding double at %ld: \"%@\"", (unsigned long)index, _SQL); + return; } } - (void)bindBlob:(NSData *)value atIndex:(NSUInteger)index { - NSAssert(_reset, @"Statement is not reset: \"%@\"", _SQL); + if (!_reset) { + secerror("sfsqlite: Statement is not reset: \"%@\"", _SQL); + return; + } if (value) { NS_VALID_UNTIL_END_OF_SCOPE NSData *arcSafeValue = value; if (sqlite3_bind_blob(_handle, (int)index+1, [arcSafeValue bytes], (int)[arcSafeValue length], NULL)) { - [_SQLite raise:@"Error binding blob at %ld: \"%@\"", (unsigned long)index, _SQL]; + secerror("sfsqlite: Error binding blob at %ld: \"%@\"", (unsigned long)index, _SQL); + return; } } else { [self bindNullAtIndex:index]; @@ -138,12 +158,16 @@ - (void)bindBlob:(NSData *)value atIndex:(NSUInteger)index { } - (void)bindText:(NSString *)value atIndex:(NSUInteger)index { - NSAssert(_reset, @"Statement is not reset: \"%@\"", _SQL); - + if (!_reset) { + secerror("sfsqlite: Statement is not reset: \"%@\"", _SQL); + return; + } + if (value) { NS_VALID_UNTIL_END_OF_SCOPE NSString *arcSafeValue = value; if (sqlite3_bind_text(_handle, (int)index+1, [arcSafeValue UTF8String], -1, NULL)) { - [_SQLite raise:@"Error binding text at %ld: \"%@\"", (unsigned long)index, _SQL]; + secerror("sfsqlite: Error binding text at %ld: \"%@\"", (unsigned long)index, _SQL); + return; } } else { [self bindNullAtIndex:index]; @@ -153,7 +177,8 @@ - (void)bindText:(NSString *)value atIndex:(NSUInteger)index { - (void)bindNullAtIndex:(NSUInteger)index { int rc = sqlite3_bind_null(_handle, (int)index+1); if ((rc & 0x00FF) != SQLITE_OK) { - [_SQLite raise:@"sqlite3_bind_null error"]; + secerror("sfsqlite: sqlite3_bind_null error"); + return; } } @@ -177,12 +202,8 @@ - (void)bindValue:(id)value atIndex:(NSUInteger)index { } } else { NSAssert(type.isFloatingPointNumber, @"Expected number type to be either integer or floating point"); - if (type.code == SFObjCTypeFloat) { - [self bindInt:[value intValue] atIndex:index]; - } else { - NSAssert(type.code == SFObjCTypeDouble, @"Unexpected floating point number type: %@", type); - [self bindInt64:[value longLongValue] atIndex:index]; - } + NSAssert(type.code == SFObjCTypeDouble || type.code == SFObjCTypeFloat, @"Unexpected floating point number type: %@", type); + [self bindDouble:[value doubleValue] atIndex:index]; } } else if ([value isKindOfClass:[NSData class]]) { [self bindBlob:value atIndex:index]; @@ -197,11 +218,12 @@ - (void)bindValue:(id)value atIndex:(NSUInteger)index { } else if ([value isKindOfClass:[NSDate class]]) { [self bindDouble:[(NSDate *)value timeIntervalSinceReferenceDate] atIndex:index]; } else if ([value isKindOfClass:[NSError class]]) { - [self bindBlob:[self retainedTemporaryBoundObject:[NSKeyedArchiver archivedDataWithRootObject:value]] atIndex:index]; + [self bindBlob:[self retainedTemporaryBoundObject:[NSKeyedArchiver archivedDataWithRootObject:value requiringSecureCoding:YES error:nil]] atIndex:index]; } else if ([value isKindOfClass:[NSURL class]]) { [self bindText:[self retainedTemporaryBoundObject:[value absoluteString]] atIndex:index]; } else { - [NSException raise:NSInvalidArgumentException format:@"Can't bind object of type %@", [value class]]; + secerror("sfsqlite: Can't bind object of type %@", [value class]); + return; } } @@ -289,7 +311,7 @@ - (id)objectAtIndex:(NSUInteger)index { return nil; default: - [NSException raise:NSGenericException format:@"Unexpected column type: %d", type]; + secerror("sfsqlite: Unexpected column type: %d", type); return nil; } } @@ -317,3 +339,5 @@ - (NSDictionary *)allObjectsByColumnName { } @end + +#endif diff --git a/CMS/CMSDecoder.h b/CMS/CMSDecoder.h new file mode 100644 index 000000000..031ad4a4c --- /dev/null +++ b/CMS/CMSDecoder.h @@ -0,0 +1,375 @@ +/* + * Copyright (c) 2006-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@ + */ + +/* + * CMSDecoder.h - decode, decrypt, and/or verify signatures of messages in the + * Cryptographic Message Syntax (CMS), per RFC 3852. + * + * See CMSEncoder.h for general information about CMS messages. + */ + +#ifndef _CMS_DECODER_H_ +#define _CMS_DECODER_H_ + +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +CF_ASSUME_NONNULL_BEGIN + +/* + * Opaque reference to a CMS decoder object. + * This is a CF object, with standard CF semantics; dispose of it + * with CFRelease(). + */ +typedef struct CF_BRIDGED_TYPE(id) _CMSDecoder *CMSDecoderRef; + +CFTypeID CMSDecoderGetTypeID(void); + +/* + * Status of signature and signer information in a signed message. + */ +typedef CF_ENUM(uint32_t, CMSSignerStatus) { + kCMSSignerUnsigned = 0, /* message was not signed */ + kCMSSignerValid, /* message was signed and signature verify OK */ + kCMSSignerNeedsDetachedContent, /* message was signed but needs detached content + * to verify */ + kCMSSignerInvalidSignature, /* message was signed but had a signature error */ + kCMSSignerInvalidCert, /* message was signed but an error occurred in verifying + * the signer's certificate */ + kCMSSignerInvalidIndex /* specified signer index out of range */ +}; + +/* + * 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)); + +/* + * Feed raw bytes of the message to be decoded into the decoder. Can be called + * multiple times. + * Returns errSecUnknownFormat upon detection of improperly formatted CMS + * message. + */ +OSStatus CMSDecoderUpdateMessage( + CMSDecoderRef cmsDecoder, + const void *msgBytes, + size_t msgBytesLen) + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + +/* + * Indicate that no more CMSDecoderUpdateMessage() calls are forthcoming; + * finish decoding the message. + * Returns errSecUnknownFormat upon detection of improperly formatted CMS + * message. + */ +OSStatus CMSDecoderFinalizeMessage(CMSDecoderRef cmsDecoder) + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + +/* + * A signed CMS message optionally includes the data which was signed. If the + * message does not include the signed data, caller specifies the signed data + * (the "detached content") here. + * + * This can be called either before or after the actual decoding of the message + * (via CMSDecoderUpdateMessage() and CMSDecoderFinalizeMessage()); the only + * restriction is that, if detached content is required, this function must + * be called befoere successfully ascertaining the signature status via + * CMSDecoderCopySignerStatus(). + */ +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)); + +/* + * Obtain the detached content specified in CMSDecoderSetDetachedContent(). + * Returns a NULL detachedContent if no detached content has been specified. + * Caller must CFRelease() the result. + */ +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)); + +#if SEC_OS_OSX +/* + * This function no longer affects the behavior of the CMS Decoder. Please + * discontinue use. + */ +OSStatus CMSDecoderSetSearchKeychain( + CMSDecoderRef cmsDecoder, + CFTypeRef keychainOrArray) + API_DEPRECATED_WITH_REPLACEMENT("SecKeychainSetSearchList",macos(10.5, 10.13)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +#endif // SEC_OS_OSX + +/* + * Obtain the number of signers of a message. A result of zero indicates that + * the message was not signed. + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +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)); + +/* + * Obtain the status of a CMS message's signature. A CMS message can + * be signed my multiple signers; this function returns the status + * associated with signer 'n' as indicated by the signerIndex parameter. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + * + * Note that signature and certificate verification of a decoded message + * does *not* occur until this routine is called. + * + * All returned values are optional - pass NULL if you don't need a + * particular parameter. + * + * Note that errors like "bad signature" and "bad cert" do NOT cause this + * routine to return a nonzero error status itself; such errors are reported + * in the various out parameters, listed below. + * + * Inputs: + * ------- + * cmsDecoder : a CMSDecoder which has successfully performed a + * CMSDecoderFinalizeMessage(). + * signerIndex : indicates which of 'n' signers is being examined. + * Range is 0...(numSigners-1). + * policyOrArray : Either a SecPolicyRef or a CFArray of them. + * These policies are used to verify the signer's certificate. + * evaluateSecTrust : When TRUE, causes the SecTrust oebject created for the + * evaluation of the signer cert to actually be evaluated + * via SecTrustEvaluate(). When FALSE, the caller performs + * the SecTrustEvaluate() operation on the SecTrust object + * returned via the secTrust out parameter. + * NOTE: it is hazardous and not recommended to pass in FALSE + * for the evaluateSecTrust parameter as well as NULL for the + * secTrust out parameter, since no evaluation of the signer + * cert can occur in that situation. + * + * Outputs: + * -------- + * signerStatusOut -- An enum indicating the overall status. + * kCMSSignerUnsigned : message was not signed. + * kCMSSignerValid : both signature and signer certificate verified OK. + * kCMSSignerNeedsDetachedContent : a call to CMSDecoderSetDetachedContent() + * is required to ascertain the signature status. + * kCMSSignerInvalidSignature : bad signature. + * kCMSSignerInvalidCert : an error occurred verifying the signer's certificate. + * Further information available via the secTrust and + * certVerifyResultCode parameters. This will never be + * returned if evaluateSecTrust is FALSE. + * kCMSSignerInvalidIndex : specified signerIndex is larger than the number of + * signers (minus 1). + * + * secTrustOut -- The SecTrust object used to verify the signer's + * certificate. Caller must CFRelease this. + * certVerifyResultCodeOut -- The result of the certificate verification. If + * the evaluateSecTrust argument is set to FALSE on + * input, this out parameter is undefined on return. + * + * The certVerifyResultCode value can indicate a large number of errors; some of + * the most common and interesting errors are: + * + * CSSMERR_TP_INVALID_ANCHOR_CERT : The cert was verified back to a + * self-signed (root) cert which was present in the message, but + * that root cert is not a known, trusted root cert. + * CSSMERR_TP_NOT_TRUSTED: The cert could not be verified back to + * a root cert. + * CSSMERR_TP_VERIFICATION_FAILURE: A root cert was found which does + * not self-verify. + * CSSMERR_TP_VERIFY_ACTION_FAILED: Indicates a failure of the requested + * policy action. + * CSSMERR_TP_INVALID_CERTIFICATE: Indicates a bad leaf cert. + * CSSMERR_TP_CERT_EXPIRED: A cert in the chain was expired at the time of + * verification. + * CSSMERR_TP_CERT_NOT_VALID_YET: A cert in the chain was not yet valie at + * the time of verification. + */ +OSStatus CMSDecoderCopySignerStatus( + CMSDecoderRef cmsDecoder, + size_t signerIndex, + CFTypeRef policyOrArray, + Boolean evaluateSecTrust, + 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)); + +/* + * Obtain the email address of signer 'signerIndex' of a CMS message, if + * present. + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerEmailAddress( + CMSDecoderRef cmsDecoder, + size_t signerIndex, + CFStringRef * __nonnull CF_RETURNS_RETAINED signerEmailAddressOut) /* RETURNED */ + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + +/* + * Obtain the certificate of signer 'signerIndex' of a CMS message, if + * present. + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerCert( + CMSDecoderRef cmsDecoder, + size_t signerIndex, + SecCertificateRef * __nonnull CF_RETURNS_RETAINED signerCertOut) /* RETURNED */ + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + +/* + * Determine whether a CMS message was encrypted. Returns TRUE if so, FALSE if not. + * Note that if the message was encrypted, and the decoding succeeded, (i.e., + * CMSDecoderFinalizeMessage() returned errSecSuccess), then the message was successfully + * decrypted. + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +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)); + +/* + * Obtain the eContentType OID for a SignedData's EncapsulatedContentType, if + * present. If the message was not signed this will return NULL. + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + * The returned OID's data is in the same format as a CSSM_OID; i.e., it's + * the encoded content of the OID, not including the tag and length bytes. + */ +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)); + +/* + * Obtain an array of all of the certificates in a message. Elements of the + * returned array are SecCertificateRefs. The caller must CFRelease the returned + * array. If a message does not contain any certificates (which is the case for + * a message which is encrypted but not signed), the returned *certs value + * is NULL. The function will return errSecSuccess in this case. + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +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)); + +/* + * Obtain the actual message content (payload), if any. If the message was + * signed with detached content this will return NULL. + * Caller must CFRelease the result. + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +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)); + +/* + * Obtain the signing time of signer 'signerIndex' of a CMS message, if + * present. This is an unauthenticate time, although it is part of the + * signed attributes of the message. + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerSigningTime( + CMSDecoderRef cmsDecoder, + size_t signerIndex, + CFAbsoluteTime *signingTime) /* RETURNED */ + __API_AVAILABLE(macos(10.8)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + +/* + * Obtain the timestamp of signer 'signerIndex' of a CMS message, if + * present. This timestamp is an authenticated timestamp provided by + * a timestamping authority. + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerTimestamp( + CMSDecoderRef cmsDecoder, + size_t signerIndex, + CFAbsoluteTime *timestamp) /* RETURNED */ + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + +/* + * Obtain the timestamp of signer 'signerIndex' of a CMS message, if + * present. This timestamp is an authenticated timestamp provided by + * a timestamping authority. Use the policy provided as a parameter + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerTimestampWithPolicy( + CMSDecoderRef cmsDecoder, + CFTypeRef __nullable timeStampPolicy, + size_t signerIndex, /* usually 0 */ + CFAbsoluteTime *timestamp) /* RETURNED */ + API_AVAILABLE(macos(10.10)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + +/* + * Obtain an array of the certificates in a timestamp response. Elements of the + * returned array are SecCertificateRefs. The caller must CFRelease the returned + * array. This timestamp is an authenticated timestamp provided by + * a timestamping authority. + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. It returns + * errSecItemNotFound if no certificates were found. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerTimestampCertificates( + CMSDecoderRef cmsDecoder, + size_t signerIndex, /* usually 0 */ + CFArrayRef * __nonnull CF_RETURNS_RETAINED certificateRefs) /* RETURNED */ + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + +CF_ASSUME_NONNULL_END + +__END_DECLS + +#endif /* _CMS_DECODER_H_ */ + diff --git a/CMS/CMSEncoder.h b/CMS/CMSEncoder.h new file mode 100644 index 000000000..276b72ef2 --- /dev/null +++ b/CMS/CMSEncoder.h @@ -0,0 +1,433 @@ +/* + * Copyright (c) 2006-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@ + */ + +/* + * CMSEncoder.h - encode, sign, and/or encrypt messages in the Cryptographic + * Message Syntax (CMS), per RFC 3852. + * + * A CMS message can be signed, encrypted, or both. A message can be signed by + * an arbitrary number of signers; in this module, signers are expressed as + * SecIdentityRefs. A message can be encrypted for an arbitrary number of + * recipients; recipients are expressed here as SecCertificateRefs. + * + * In CMS terminology, this module performs encryption using the EnvelopedData + * ContentType and signing using the SignedData ContentType. + * + * If the message is both signed and encrypted, it uses "nested ContentInfos" + * in CMS terminology; in this implementation, signed & encrypted messages + * are implemented as an EnvelopedData containing a SignedData. + */ + +#ifndef _CMS_ENCODER_H_ +#define _CMS_ENCODER_H_ + +#include +#include +#include +#include + +#if SEC_OS_OSX +#include +#endif + +__BEGIN_DECLS + +CF_ASSUME_NONNULL_BEGIN + +/* + * Opaque reference to a CMS encoder object. + * This is a CF object, with standard CF semantics; dispose of it + * with CFRelease(). + */ +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)); + +/* + * 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)); + +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)); + +/* + * Specify signers of the CMS message; implies that the message will be signed. + * + * -- Caller can pass in one signer, as a SecIdentityRef, or an array of + * signers, as a CFArray of SecIdentityRefs. + * -- Can be called multiple times. + * -- If the message is not to be signed, don't call this. + * -- If this is called, it must be called before the first call to + * CMSEncoderUpdateContent(). + */ +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)); + +/* + * Obtain an array of signers as specified in CMSEncoderSetSigners(). + * Returns a NULL signers array if CMSEncoderSetSigners() has not been called. + * Caller must CFRelease the result. + */ +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)); + +/* + * Specify recipients of the message. Implies that the message will + * be encrypted. + * + * -- Caller can pass in one recipient, as a SecCertificateRef, or an + * array of recipients, as a CFArray of SecCertificateRefs. + * -- Can be called multiple times. + * -- If the message is not to be encrypted, don't call this. + * -- If this is called, it must be called before the first call to + * CMSEncoderUpdateContent(). + */ +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)); + +/* + * Obtain an array of recipients as specified in CMSEncoderSetRecipients(). + * Returns a NULL recipients array if CMSEncoderSetRecipients() has not been + * called. + * Caller must CFRelease the result. + */ +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)); + +/* + * A signed message optionally includes the data to be signed. If the message + * is *not* to include the data to be signed, call this function with a value + * of TRUE for detachedContent. The default, if this function is not called, + * is detachedContent=FALSE, i.e., the message contains the data to be signed. + * + * -- Encrypted messages can not use detached content. (This restriction + * also applies to messages that are both signed and encrypted.) + * -- If this is called, it must be called before the first call to + * CMSEncoderUpdateContent(). + */ +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)); + +/* + * Obtain a Boolean indicating whether the current message will have detached + * content. + * Returns the value specified in CMSEncoderHasDetachedContent() if that + * function has been called; else returns the default FALSE. + */ +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)); + +#if SEC_OS_OSX +/* + * Optionally specify an eContentType OID for the inner EncapsulatedData for + * a signed message. The default eContentType, used if this function is not + * called, is id-data (which is the normal eContentType for applications such + * as SMIME). + * + * If this is called, it must be called before the first call to + * CMSEncoderUpdateContent(). + * + * NOTE: This function is deprecated in Mac OS X 10.7 and later; + * please use CMSEncoderSetEncapsulatedContentTypeOID() instead. + */ +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); +#endif // SEC_OS_OSX + +/* + * Optionally specify an eContentType OID for the inner EncapsulatedData for + * a signed message. The default eContentTypeOID, used if this function is not + * called, is id-data (which is the normal eContentType for applications such + * as SMIME). + * + * The eContentTypeOID parameter may be specified as a CF string, e.g.: + * CFSTR("1.2.840.113549.1.7.1") + * + * If this is called, it must be called before the first call to + * CMSEncoderUpdateContent(). + */ +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)); + +/* + * Obtain the eContentType OID specified in CMSEncoderSetEncapsulatedContentType(). + * If CMSEncoderSetEncapsulatedContentType() has not been called this returns a + * NULL pointer. + * The returned OID's data is in the same format as the data provided to + * CMSEncoderSetEncapsulatedContentType;, i.e., it's the encoded content of + * the OID, not including the tag and length bytes. + */ +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)); + +/* + * Signed CMS messages can contain arbitrary sets of certificates beyond those + * indicating the identity of the signer(s). This function provides a means of + * adding these other certs. For normal signed messages it is not necessary to + * call this; the signer cert(s) and the intermediate certs needed to verify the + * signer(s) will be included in the message implicitly. + * + * -- Caller can pass in one cert, as a SecCertificateRef, or an array of certs, + * as a CFArray of SecCertificateRefs. + * -- If this is called, it must be called before the first call to + * CMSEncoderUpdateContent(). + * -- There is a "special case" use of CMS messages which involves neither + * signing nor encryption, but does include certificates. This is commonly + * used to transport "bags" of certificates. When constructing such a + * message, all an application needs to do is to create a CMSEncoderRef, + * call CMSEncoderAddSupportingCerts() one or more times, and then call + * CMSEncoderCopyEncodedContent() to get the resulting cert bag. No 'content' + * need be specified. (This is in fact the primary intended use for + * this function.) + */ +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)); + +/* + * Obtain the SecCertificates provided in CMSEncoderAddSupportingCerts(). + * If CMSEncoderAddSupportingCerts() has not been called this will return a + * NULL value for *certs. + * Caller must CFRelease the result. + */ +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)); + +/* + * Standard signed attributes, optionally specified in + * CMSEncoderAddSignedAttributes(). + */ +typedef CF_OPTIONS(uint32_t, CMSSignedAttributes) { + kCMSAttrNone = 0x0000, + /* + * S/MIME Capabilities - identifies supported signature, encryption, and + * digest algorithms. + */ + kCMSAttrSmimeCapabilities = 0x0001, + /* + * Indicates that a cert is the preferred cert for S/MIME encryption. + */ + kCMSAttrSmimeEncryptionKeyPrefs = 0x0002, + /* + * Same as kCMSSmimeEncryptionKeyPrefs, using an attribute OID preferred + * by Microsoft. + */ + kCMSAttrSmimeMSEncryptionKeyPrefs = 0x0004, + /* + * Include the signing time. + */ + kCMSAttrSigningTime = 0x0008, + /* + * Include the Apple Codesigning Hash Agility. + */ + kCMSAttrAppleCodesigningHashAgility = 0x0010, + kCMSAttrAppleCodesigningHashAgilityV2 = 0x0020, + /* + * Include the expiration time. + */ + kCMSAttrAppleExpirationTime = 0x0040, +}; + +/* + * Optionally specify signed attributes. Only meaningful when creating a + * signed message. If this is called, it must be called before + * CMSEncoderUpdateContent(). + */ +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)); + +/* + * Specification of what certificates to include in a signed message. + */ +typedef CF_ENUM(uint32_t, CMSCertificateChainMode) { + kCMSCertificateNone = 0, /* don't include any certificates */ + kCMSCertificateSignerOnly, /* only include signer certificate(s) */ + kCMSCertificateChain, /* signer certificate chain up to but not + * including root certiticate */ + kCMSCertificateChainWithRoot, /* signer certificate chain including root */ + kCMSCertificateChainWithRootOrFail, /* signer certificate chain including root + * and if chain not terminated by a self-signed cert, + * fail to create CMS */ +}; + +/* + * Optionally specify which certificates, if any, to include in a + * signed CMS message. The default, if this is not called, is + * kCMSCertificateChain, in which case the signer cert plus all CA + * certs needed to verify the signer cert, except for the root + * cert, are included. + * If this is called, it must be called before + * CMSEncoderUpdateContent(). + */ +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)); + +/* + * Obtain indication of which signer certs are to be included + * in a signed CMS message. + */ +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)); + +/* + * Feed content bytes into the encoder. + * Can be called multiple times. + * No 'setter' routines can be called after this function has been called. + */ +OSStatus CMSEncoderUpdateContent( + CMSEncoderRef cmsEncoder, + const void *content, + size_t contentLen) + __API_AVAILABLE(macos(10.5)) SPI_AVAILABLE(ios(11.0), tvos(11.0), watchos(4.0), iosmac(11.0)); + +/* + * Finish encoding the message and obtain the encoded result. + * Caller must CFRelease the 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)); + +#if TARGET_OS_OSX +/* + * High-level, one-shot encoder function. + * + * Inputs (all except for content optional, though at least one + * of {signers, recipients} must be non-NULL) + * ------------------------------------------------------------ + * signers : signer identities. Either a SecIdentityRef, or a + * CFArray of them. + * recipients : recipient certificates. Either a SecCertificateRef, + * or a CFArray of them. + * eContentType : contentType for inner EncapsulatedData. + * detachedContent : when true, do not include the signed data in the message. + * signedAttributes : Specifies which standard signed attributes are to be + * included in the message. + * content : raw content to be signed and/or encrypted. + * + * Output + * ------ + * encodedContent : the result of the encoding. + * + * NOTE: This function is deprecated in Mac OS X 10.7 and later; + * please use CMSEncodeContent() instead. + */ +OSStatus CMSEncode( + CFTypeRef __nullable signers, + CFTypeRef __nullable recipients, + const CSSM_OID * __nullable eContentType, + Boolean detachedContent, + CMSSignedAttributes signedAttributes, + 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); +#endif // TARGET_OS_OSX + +/* + * High-level, one-shot encoder function. + * + * Inputs (all except for content optional, though at least one + * of {signers, recipients} must be non-NULL) + * ------------------------------------------------------------ + * signers : signer identities. Either a SecIdentityRef, or a + * CFArray of them. + * recipients : recipient certificates. Either a SecCertificateRef, + * or a CFArray of them. + * eContentTypeOID : contentType OID for inner EncapsulatedData, e.g.: + * CFSTR("1.2.840.113549.1.7.1") + * detachedContent : when true, do not include the signed data in the message. + * signedAttributes : Specifies which standard signed attributes are to be + * included in the message. + * content : raw content to be signed and/or encrypted. + * + * Output + * ------ + * encodedContent : the result of the encoding. + */ +OSStatus CMSEncodeContent( + CFTypeRef __nullable signers, + CFTypeRef __nullable recipients, + CFTypeRef __nullable eContentTypeOID, + Boolean detachedContent, + CMSSignedAttributes signedAttributes, + 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)); + +OSStatus CMSEncoderCopySignerTimestamp( + CMSEncoderRef cmsEncoder, + size_t signerIndex, /* usually 0 */ + CFAbsoluteTime *timestamp) /* RETURNED */ + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + +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); + +CF_ASSUME_NONNULL_END + +__END_DECLS + +#endif /* _CMS_ENCODER_H_ */ + diff --git a/CMS/CMSPrivate.h b/CMS/CMSPrivate.h new file mode 100644 index 000000000..548a27926 --- /dev/null +++ b/CMS/CMSPrivate.h @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2006-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@ + */ + +/* + * CMSPrivate.h - access to low-level CMS objects used by CMSDecoder and CMSEncoder. + */ +#ifndef _CMS_PRIVATE_H_ +#define _CMS_PRIVATE_H_ + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*** + *** Private CMSEncoder routines + ***/ + +/* + * Obtain the SecCmsMessageRef associated with a CMSEncoderRef. Intended + * to be called after (optionally) setting the encoder's various attributes + * via CMSEncoderAddSigners(), CMSEncoderAddRecipients(), etc. and before + * the first call to CMSEncoderUpdateContent(). The returned SecCmsMessageRef + * will be initialized per the previously specified attributes; the caller + * can manipulate the SecCmsMessageRef prior to proceeding with + * CMSEncoderUpdateContent() calls. + */ +OSStatus CMSEncoderGetCmsMessage( + CMSEncoderRef cmsEncoder, + SecCmsMessageRef *cmsMessage); /* RETURNED */ + +/* + * Optionally specify a SecCmsEncoderRef to use with a CMSEncoderRef. + * If this is called, it must be called before the first call to + * CMSEncoderUpdateContent(). The CMSEncoderRef takes ownership of the + * incoming SecCmsEncoderRef. + */ +OSStatus CMSEncoderSetEncoder( + CMSEncoderRef cmsEncoder, + SecCmsEncoderRef encoder); + +/* + * Obtain the SecCmsEncoderRef associated with a CMSEncoderRef. + * Returns a NULL SecCmsEncoderRef if neither CMSEncoderSetEncoder nor + * CMSEncoderUpdateContent() has been called. + * The CMSEncoderRef retains ownership of the SecCmsEncoderRef. + */ +OSStatus CMSEncoderGetEncoder( + CMSEncoderRef cmsEncoder, + SecCmsEncoderRef *encoder); /* RETURNED */ + +/* + * Set the signing time for a CMSEncoder. + * This is only used if the kCMSAttrSigningTime attribute is included. + */ +OSStatus CMSEncoderSetSigningTime( + CMSEncoderRef cmsEncoder, + CFAbsoluteTime time); + +/* + * Set the hash agility attribute for a CMSEncoder. + * This is only used if the kCMSAttrAppleCodesigningHashAgility attribute + * is included. + */ +OSStatus CMSEncoderSetAppleCodesigningHashAgility( + CMSEncoderRef cmsEncoder, + CFDataRef hashAgilityAttrValue); + +/* + * Set the hash agility attribute for a CMSEncoder. + * This is only used if the kCMSAttrAppleCodesigningHashAgilityV2 attribute + * is included. V2 encodes the hash agility values using DER. + * The dictionary should have CFNumberRef keys, corresponding to SECOidTags + * (from SecCmsBase.h) for digest algorithms, and CFDataRef values, + * corresponding to the digest value for that digest algorithm. + */ +OSStatus CMSEncoderSetAppleCodesigningHashAgilityV2( + CMSEncoderRef cmsEncoder, + CFDictionaryRef hashAgilityV2AttrValues); + +/* + * Set the expiration time for a CMSEncoder. + * This is only used if the kCMSAttrAppleExpirationTime attribute is included. + */ +OSStatus CMSEncoderSetAppleExpirationTime( + CMSEncoderRef cmsEncoder, + CFAbsoluteTime time); + + +void +CmsMessageSetTSAContext(CMSEncoderRef cmsEncoder, CFTypeRef tsaContext) + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, tvos, watchos, bridgeos, iosmac); + +/*** + *** Private CMSDecoder routines + ***/ + +/* + * Obtain the SecCmsMessageRef associated with a CMSDecoderRef. Intended + * to be called after decoding the message (i.e., after + * CMSDecoderFinalizeMessage() to gain finer access to the contents of the + * SecCmsMessageRef than is otherwise available via the CMSDecoder interface. + * Returns a NULL SecCmsMessageRef if CMSDecoderFinalizeMessage() has not been + * called. + * + * The CMSDecoder retains ownership of the returned SecCmsMessageRef. + */ +OSStatus CMSDecoderGetCmsMessage( + CMSDecoderRef cmsDecoder, + SecCmsMessageRef *cmsMessage); /* RETURNED */ + + +/* + * Optionally specify a SecCmsDecoderRef to use with a CMSDecoderRef. + * If this is called, it must be called before the first call to + * CMSDecoderUpdateMessage(). The CMSDecoderRef takes ownership of the + * incoming SecCmsDecoderRef. + */ +OSStatus CMSDecoderSetDecoder( + CMSDecoderRef cmsDecoder, + SecCmsDecoderRef decoder); + +/* + * Obtain the SecCmsDecoderRef associated with a CMSDecoderRef. + * Returns a NULL SecCmsDecoderRef if neither CMSDecoderSetDecoder() nor + * CMSDecoderUpdateMessage() has been called. + * The CMSDecoderRef retains ownership of the SecCmsDecoderRef. + */ +OSStatus CMSDecoderGetDecoder( + CMSDecoderRef cmsDecoder, + SecCmsDecoderRef *decoder); /* RETURNED */ + +/* + * Obtain the Hash Agility attribute value of signer 'signerIndex' + * of a CMS message, if present. + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerAppleCodesigningHashAgility( + CMSDecoderRef cmsDecoder, + size_t signerIndex, /* usually 0 */ + CFDataRef CF_RETURNS_RETAINED *hashAgilityAttrValue) /* RETURNED */ + API_AVAILABLE(macos(10.12.4), ios(11.0)); + +/* + * Obtain the Hash Agility v2 attribute value of signer 'signerIndex' + * of a CMS message, if present. V2 encodes the hash agility values using DER. + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerAppleCodesigningHashAgilityV2( + CMSDecoderRef cmsDecoder, + size_t signerIndex, /* usually 0 */ + CFDictionaryRef CF_RETURNS_RETAINED * hashAgilityAttrValues) /* RETURNED */ + API_AVAILABLE(macos(10.13.4), ios(11.3)); + +/* + * Obtain the expiration time of signer 'signerIndex' of a CMS message, if + * present. This is part of the signed attributes of the message. + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerAppleExpirationTime( + CMSDecoderRef cmsDecoder, + size_t signerIndex, + CFAbsoluteTime *expirationTime) /* RETURNED */ + API_AVAILABLE(macos(10.14), ios(12.0)); + +#ifdef __cplusplus +} +#endif + +#endif /* _CMS_PRIVATE_H_ */ + diff --git a/CMS/SecCMS.h b/CMS/SecCMS.h new file mode 100644 index 000000000..8670d04e1 --- /dev/null +++ b/CMS/SecCMS.h @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2008-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@ + */ + +/*! + @header SecCMS +*/ + +#include +#include +#include +#include + +#ifndef _SECURITY_SECCMS_H_ +#define _SECURITY_SECCMS_H_ + +__BEGIN_DECLS + +extern const void * kSecCMSSignDigest; +extern const void * kSecCMSSignDetached; +extern const void * kSecCMSSignHashAlgorithm; +extern const void * kSecCMSCertChainMode; +extern const void * kSecCMSAdditionalCerts; +extern const void * kSecCMSSignedAttributes; +extern const void * kSecCMSSignDate; +extern const void * kSecCMSAllCerts; +extern const void * kSecCMSHashAgility; +extern const void * kSecCMSHashAgilityV2; +extern const void * kSecCMSExpirationDate; + +extern const void * kSecCMSBulkEncryptionAlgorithm; +extern const void * kSecCMSEncryptionAlgorithmDESCBC; +extern const void * kSecCMSEncryptionAlgorithmAESCBC; + +extern const void * kSecCMSCertChainModeNone; + +extern const void * kSecCMSHashingAlgorithmMD5 + __API_DEPRECATED("Disuse this constant in order to upgrade to SHA-1", ios(3.1, 10.0), macos(10.15, 10.15)); +extern const void * kSecCMSHashingAlgorithmSHA1; +extern const void * kSecCMSHashingAlgorithmSHA256; +extern const void * kSecCMSHashingAlgorithmSHA384; +extern const void * kSecCMSHashingAlgorithmSHA512; + +/*! + @function SecCMSVerifyCopyDataAndAttributes + @abstract verify a signed data cms blob. + @param message the cms message to be parsed + @param detached_contents to pass detached contents (optional) + @param policy specifies policy or array thereof should be used (optional). + if none is passed the blob will **not** be verified and only + the attached contents will be returned. + @param trustref (output/optional) if specified, the trust chain built during + verification will not be evaluated but returned to the caller to do so. + @param attached_contents (output/optional) return a copy of the attached + contents. + @param signed_attributes (output/optional) return a copy of the signed + attributes as a CFDictionary from oids (CFData) to values + (CFArray of CFData). + @result A result code. See "Security Error Codes" (SecBase.h). + errSecDecode not a CMS message we can parse, + errSecAuthFailed bad signature, or untrusted signer if caller doesn't + ask for trustref, + errSecParam garbage in, garbage out. +*/ +OSStatus SecCMSVerifyCopyDataAndAttributes(CFDataRef message, CFDataRef detached_contents, + CFTypeRef policy, SecTrustRef *trustref, + CFDataRef *attached_contents, CFDictionaryRef *signed_attributes); + +/*! + @function SecCMSVerify + @abstract same as SecCMSVerifyCopyDataAndAttributes, for binary compatibility. +*/ +OSStatus SecCMSVerify(CFDataRef message, CFDataRef detached_contents, + CFTypeRef policy, SecTrustRef *trustref, CFDataRef *attached_contents); + +OSStatus SecCMSVerifySignedData(CFDataRef message, CFDataRef detached_contents, + CFTypeRef policy, SecTrustRef *trustref, CFArrayRef additional_certificates, + CFDataRef *attached_contents, CFDictionaryRef *message_attributes); + + +/* Return an array of certificates contained in message, if message is of the + type SignedData and has no signers, return NULL otherwise. Not that if + the message is properly formed but has no certificates an empty array will + be returned. */ +CFArrayRef SecCMSCertificatesOnlyMessageCopyCertificates(CFDataRef message); + +/* Create a degenerate PKCS#7 containing a cert or a CFArray of certs. */ +CFDataRef SecCMSCreateCertificatesOnlyMessage(CFTypeRef cert_or_array_thereof); +CFDataRef SecCMSCreateCertificatesOnlyMessageIAP(SecCertificateRef cert); + +/*! + @function SecCMSSignDataAndAttributes + @abstract create a signed data cms blob. + @param identity signer + @param data message to be signed + @param detached sign detached or not + @param signed_data (output) return signed message. + @param signed_attributes (input/optional) signed attributes to insert + as a CFDictionary from oids (CFData) to value (CFData). + @result A result code. See "Security Error Codes" (SecBase.h). + errSecParam garbage in, garbage out. +*/ +OSStatus SecCMSSignDataAndAttributes(SecIdentityRef identity, CFDataRef data, + bool detached, CFMutableDataRef signed_data, CFDictionaryRef signed_attributes); + +/*! + @function SecCMSSignDigestAndAttributes + @abstract create a detached signed data cms blob for a SHA-1 hash. + @param identity signer + @param digest SHA-1 digest of message to be signed + @param signed_data (output) return signed message. + @param signed_attributes (input/optional) signed attributes to insert + as a CFDictionary from oids (CFData) to value (CFData). + @result A result code. See "Security Error Codes" (SecBase.h). + errSecParam garbage in, garbage out. +*/ +OSStatus SecCMSSignDigestAndAttributes(SecIdentityRef identity, CFDataRef digest, + CFMutableDataRef signed_data, CFDictionaryRef signed_attributes); + +/*! + @function SecCMSCreateSignedData + @abstract create a signed data cms blob. + @param identity signer + @param data SHA-1 digest or message to be signed + @param parameters (input/optional) specify algorithm, detached, digest + @param signed_attributes (input/optional) signed attributes to insert + as a CFDictionary from oids (CFData) to value (CFData). + @param signed_data (output) return signed message. + @result A result code. See "Security Error Codes" (SecBase.h). + errSecParam garbage in, garbage out. +*/ +OSStatus SecCMSCreateSignedData(SecIdentityRef identity, CFDataRef data, + CFDictionaryRef parameters, CFDictionaryRef signed_attributes, + CFMutableDataRef signed_data); + +/*! + @function SecCMSCreateEnvelopedData + @abstract create a enveloped cms blob for recipients + @param recipient_or_cfarray_thereof SecCertificateRef for each recipient + @param params CFDictionaryRef with encryption parameters + @param data Data to be encrypted + @param enveloped_data (output) return enveloped message. + @result A result code. See "Security Error Codes" (SecBase.h). + errSecParam garbage in, garbage out. +*/ +OSStatus SecCMSCreateEnvelopedData(CFTypeRef recipient_or_cfarray_thereof, + CFDictionaryRef params, CFDataRef data, CFMutableDataRef enveloped_data); + +/*! + @function SecCMSDecryptEnvelopedData + @abstract open an enveloped cms blob. expects recipients identity in keychain. + @param message Eveloped message + @param data (output) return decrypted message. + @param recipient (output/optional) return addressed recipient + @result A result code. See "Security Error Codes" (SecBase.h). + errSecParam garbage in, garbage out. +*/ +OSStatus SecCMSDecryptEnvelopedData(CFDataRef message, + CFMutableDataRef data, SecCertificateRef *recipient); + +__END_DECLS + +#endif /* !_SECURITY_SECCMS_H_ */ diff --git a/CMS/SecCmsBase.h b/CMS/SecCmsBase.h new file mode 100644 index 000000000..44f7eadea --- /dev/null +++ b/CMS/SecCmsBase.h @@ -0,0 +1,543 @@ +/* + * Copyright (c) 2004-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@ + */ + +/*! + @header SecCmsBase.h + + @availability 10.4 and later + @abstract Interfaces of the CMS implementation. + @discussion The functions here implement functions for encoding + and decoding Cryptographic Message Syntax (CMS) objects + as described in rfc3369. + */ + +#ifndef _SECURITY_SECCMSBASE_H_ +#define _SECURITY_SECCMSBASE_H_ 1 + +#include +#include +#include +#include + +#if TARGET_OS_OSX +#include +#endif + +__BEGIN_DECLS + +/*! + @typedef + @discussion XXX We need to remove these from the API and move them back to secoidt.h. + */ +typedef struct SECOidDataStr SECOidData; + +/*! + @typedef + @discussion XXX We might want to get rid of this alltogether. + */ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#if TARGET_OS_OSX +typedef CSSM_X509_ALGORITHM_IDENTIFIER SECAlgorithmID; +#else // !TARGET_OS_OSX +typedef SecAsn1AlgId SECAlgorithmID; +#endif // !TARGET_OS_OSX +#pragma clang diagnostic pop + +/*! + @typedef + @discussion XXX This should probably move to SecKey.h + */ +#if TARGET_OS_OSX +typedef SecKeyRef SecSymmetricKeyRef API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); +#else +typedef void * SecSymmetricKeyRef API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); +#endif + +/*! + @typedef + @discussion XXX This should probably move to SecKey.h + */ +typedef SecKeyRef SecPublicKeyRef; + +/*! + @typedef + @discussion XXX This should probably move to SecKey.h + */ +typedef SecKeyRef SecPrivateKeyRef; + +/*! + @typedef + */ +typedef void(*PK11PasswordFunc)(void); + +#if TARGET_OS_OSX +/*! + @typedef + */ +typedef struct SecArenaPoolStr *SecArenaPoolRef; +#endif + +/*! + @typedef + */ +typedef struct SecCmsMessageStr *SecCmsMessageRef; + +/*! + @typedef + */ +typedef struct SecCmsContentInfoStr *SecCmsContentInfoRef; + +/*! + @typedef + */ +typedef struct SecCmsSignedDataStr *SecCmsSignedDataRef; + +/*! + @typedef + */ +typedef struct SecCmsSignerInfoStr *SecCmsSignerInfoRef; + +/*! + @typedef + */ +typedef struct SecCmsEnvelopedDataStr *SecCmsEnvelopedDataRef; + +/*! + @typedef + */ +typedef struct SecCmsRecipientInfoStr *SecCmsRecipientInfoRef; + +/*! + @typedef + */ +typedef struct SecCmsDigestedDataStr *SecCmsDigestedDataRef; + +/*! + @typedef + */ +typedef struct SecCmsEncryptedDataStr *SecCmsEncryptedDataRef; + +/*! + @typedef + */ +typedef struct SecCmsDecoderStr *SecCmsDecoderRef; + +/*! + @typedef + */ +typedef struct SecCmsEncoderStr *SecCmsEncoderRef; + +/*! + @typedef + */ +typedef struct SecCmsDigestContextStr *SecCmsDigestContextRef; + + +/*! + @typedef + @discussion Type of function passed to SecCmsDecode or SecCmsDecoderStart. + If specified, this is where the content bytes (only) will be "sent" as they are recovered during the decoding. + And: + Type of function passed to SecCmsEncode or SecCmsEncoderStart. + This is where the DER-encoded bytes will be "sent". + + XXX Should just combine this with SecCmsEncoderContentCallback type and use a simpler, common name. + */ +typedef void (*SecCmsContentCallback)(void *arg, const char *buf, size_t len); + +/*! + @typedef + @discussion Type of function passed to SecCmsDecode or SecCmsDecoderStart to retrieve the decryption key. This function is intended to be used for EncryptedData content info's which do not have a key available in a certificate, etc. + */ +#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); +#pragma clang diagnostic pop + +/*! + @enum SecCmsVerificationStatus + */ +typedef enum { + SecCmsVSUnverified = 0, + SecCmsVSGoodSignature = 1, + SecCmsVSBadSignature = 2, + SecCmsVSDigestMismatch = 3, + SecCmsVSSigningCertNotFound = 4, + SecCmsVSSigningCertNotTrusted = 5, + SecCmsVSSignatureAlgorithmUnknown = 6, + SecCmsVSSignatureAlgorithmUnsupported = 7, + SecCmsVSMalformedSignature = 8, + SecCmsVSProcessingError = 9, + SecCmsVSTimestampMissing = 10, /* A timestamp was expected but was not found. */ + SecCmsVSTimestampInvalid = 11, /* The timestamp was not valid. */ + SecCmsVSTimestampNotTrusted = 12, /* The timestamp signing chain was not trusted. */ +} SecCmsVerificationStatus; + +/*! + @enum SecCmsCertChainMode + */ +typedef enum { + SecCmsCMNone = 0, + SecCmsCMCertOnly = 1, + SecCmsCMCertChain = 2, + SecCmsCMCertChainWithRoot = 3, + SecCmsCMCertChainWithRootOrFail = 4, +} SecCmsCertChainMode; + +/*! + @enum + @discussion XXX This should be replaced with SecPolicyRefs + */ +typedef enum SECCertUsageEnum { + certUsageSSLClient = 0, + certUsageSSLServer = 1, + certUsageSSLServerWithStepUp = 2, + certUsageSSLCA = 3, + certUsageEmailSigner = 4, + certUsageEmailRecipient = 5, + certUsageObjectSigner = 6, + certUsageUserCertImport = 7, + certUsageVerifyCA = 8, + certUsageProtectedObjectSigner = 9, + certUsageStatusResponder = 10, + certUsageAnyCA = 11 +} SECCertUsage; + + +/*! + @enum SECOidTag + @abstract Misc object IDs - these numbers are for convenient handling. + @discussion They are mapped into real object IDs + NOTE: the order of these entries must mach the array "oids" of SECOidData in util/secoid.c. + */ +typedef enum { + SEC_OID_UNKNOWN = 0, + SEC_OID_MD2 = 1, + SEC_OID_MD4 = 2, + SEC_OID_MD5 = 3, + SEC_OID_SHA1 = 4, + SEC_OID_RC2_CBC = 5, + SEC_OID_RC4 = 6, + SEC_OID_DES_EDE3_CBC = 7, + SEC_OID_RC5_CBC_PAD = 8, + SEC_OID_DES_ECB = 9, + SEC_OID_DES_CBC = 10, + SEC_OID_DES_OFB = 11, + SEC_OID_DES_CFB = 12, + SEC_OID_DES_MAC = 13, + SEC_OID_DES_EDE = 14, + SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE = 15, + SEC_OID_PKCS1_RSA_ENCRYPTION = 16, + SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION = 17, + SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION = 18, + SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION = 19, + SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION = 20, + SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC = 21, + SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC = 22, + SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC = 23, + SEC_OID_PKCS7 = 24, + SEC_OID_PKCS7_DATA = 25, + SEC_OID_PKCS7_SIGNED_DATA = 26, + SEC_OID_PKCS7_ENVELOPED_DATA = 27, + SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA = 28, + SEC_OID_PKCS7_DIGESTED_DATA = 29, + SEC_OID_PKCS7_ENCRYPTED_DATA = 30, + SEC_OID_PKCS9_EMAIL_ADDRESS = 31, + SEC_OID_PKCS9_UNSTRUCTURED_NAME = 32, + SEC_OID_PKCS9_CONTENT_TYPE = 33, + SEC_OID_PKCS9_MESSAGE_DIGEST = 34, + SEC_OID_PKCS9_SIGNING_TIME = 35, + SEC_OID_PKCS9_COUNTER_SIGNATURE = 36, + SEC_OID_PKCS9_CHALLENGE_PASSWORD = 37, + SEC_OID_PKCS9_UNSTRUCTURED_ADDRESS = 38, + SEC_OID_PKCS9_EXTENDED_CERTIFICATE_ATTRIBUTES = 39, + SEC_OID_PKCS9_SMIME_CAPABILITIES = 40, + SEC_OID_AVA_COMMON_NAME = 41, + SEC_OID_AVA_COUNTRY_NAME = 42, + SEC_OID_AVA_LOCALITY = 43, + SEC_OID_AVA_STATE_OR_PROVINCE = 44, + SEC_OID_AVA_ORGANIZATION_NAME = 45, + SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME = 46, + SEC_OID_AVA_DN_QUALIFIER = 47, + SEC_OID_AVA_DC = 48, + + SEC_OID_NS_TYPE_GIF = 49, + SEC_OID_NS_TYPE_JPEG = 50, + SEC_OID_NS_TYPE_URL = 51, + SEC_OID_NS_TYPE_HTML = 52, + SEC_OID_NS_TYPE_CERT_SEQUENCE = 53, + SEC_OID_MISSI_KEA_DSS_OLD = 54, + SEC_OID_MISSI_DSS_OLD = 55, + SEC_OID_MISSI_KEA_DSS = 56, + SEC_OID_MISSI_DSS = 57, + SEC_OID_MISSI_KEA = 58, + SEC_OID_MISSI_ALT_KEA = 59, + + /* Netscape private certificate extensions */ + SEC_OID_NS_CERT_EXT_NETSCAPE_OK = 60, + SEC_OID_NS_CERT_EXT_ISSUER_LOGO = 61, + SEC_OID_NS_CERT_EXT_SUBJECT_LOGO = 62, + SEC_OID_NS_CERT_EXT_CERT_TYPE = 63, + SEC_OID_NS_CERT_EXT_BASE_URL = 64, + SEC_OID_NS_CERT_EXT_REVOCATION_URL = 65, + SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL = 66, + SEC_OID_NS_CERT_EXT_CA_CRL_URL = 67, + SEC_OID_NS_CERT_EXT_CA_CERT_URL = 68, + SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL = 69, + SEC_OID_NS_CERT_EXT_CA_POLICY_URL = 70, + SEC_OID_NS_CERT_EXT_HOMEPAGE_URL = 71, + SEC_OID_NS_CERT_EXT_ENTITY_LOGO = 72, + SEC_OID_NS_CERT_EXT_USER_PICTURE = 73, + SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME = 74, + SEC_OID_NS_CERT_EXT_COMMENT = 75, + SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL = 76, + SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME = 77, + SEC_OID_NS_KEY_USAGE_GOVT_APPROVED = 78, + + /* x.509 v3 Extensions */ + SEC_OID_X509_SUBJECT_DIRECTORY_ATTR = 79, + SEC_OID_X509_SUBJECT_KEY_ID = 80, + SEC_OID_X509_KEY_USAGE = 81, + SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD = 82, + SEC_OID_X509_SUBJECT_ALT_NAME = 83, + SEC_OID_X509_ISSUER_ALT_NAME = 84, + SEC_OID_X509_BASIC_CONSTRAINTS = 85, + SEC_OID_X509_NAME_CONSTRAINTS = 86, + SEC_OID_X509_CRL_DIST_POINTS = 87, + SEC_OID_X509_CERTIFICATE_POLICIES = 88, + SEC_OID_X509_POLICY_MAPPINGS = 89, + SEC_OID_X509_POLICY_CONSTRAINTS = 90, + SEC_OID_X509_AUTH_KEY_ID = 91, + SEC_OID_X509_EXT_KEY_USAGE = 92, + SEC_OID_X509_AUTH_INFO_ACCESS = 93, + + SEC_OID_X509_CRL_NUMBER = 94, + SEC_OID_X509_REASON_CODE = 95, + SEC_OID_X509_INVALID_DATE = 96, + /* End of x.509 v3 Extensions */ + + SEC_OID_X500_RSA_ENCRYPTION = 97, + + /* alg 1485 additions */ + SEC_OID_RFC1274_UID = 98, + SEC_OID_RFC1274_MAIL = 99, + + /* PKCS 12 additions */ + SEC_OID_PKCS12 = 100, + SEC_OID_PKCS12_MODE_IDS = 101, + SEC_OID_PKCS12_ESPVK_IDS = 102, + SEC_OID_PKCS12_BAG_IDS = 103, + SEC_OID_PKCS12_CERT_BAG_IDS = 104, + SEC_OID_PKCS12_OIDS = 105, + SEC_OID_PKCS12_PBE_IDS = 106, + SEC_OID_PKCS12_SIGNATURE_IDS = 107, + SEC_OID_PKCS12_ENVELOPING_IDS = 108, + /* SEC_OID_PKCS12_OFFLINE_TRANSPORT_MODE, + SEC_OID_PKCS12_ONLINE_TRANSPORT_MODE, */ + SEC_OID_PKCS12_PKCS8_KEY_SHROUDING = 109, + SEC_OID_PKCS12_KEY_BAG_ID = 110, + SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID = 111, + SEC_OID_PKCS12_SECRET_BAG_ID = 112, + SEC_OID_PKCS12_X509_CERT_CRL_BAG = 113, + SEC_OID_PKCS12_SDSI_CERT_BAG = 114, + SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4 = 115, + SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4 = 116, + SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC = 117, + SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC = 118, + SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC = 119, + SEC_OID_PKCS12_RSA_ENCRYPTION_WITH_128_BIT_RC4 = 120, + SEC_OID_PKCS12_RSA_ENCRYPTION_WITH_40_BIT_RC4 = 121, + SEC_OID_PKCS12_RSA_ENCRYPTION_WITH_TRIPLE_DES = 122, + SEC_OID_PKCS12_RSA_SIGNATURE_WITH_SHA1_DIGEST = 123, + /* end of PKCS 12 additions */ + + /* DSA signatures */ + SEC_OID_ANSIX9_DSA_SIGNATURE = 124, + SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST = 125, + SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST = 126, + + /* Verisign OIDs */ + SEC_OID_VERISIGN_USER_NOTICES = 127, + + /* PKIX OIDs */ + SEC_OID_PKIX_CPS_POINTER_QUALIFIER = 128, + SEC_OID_PKIX_USER_NOTICE_QUALIFIER = 129, + SEC_OID_PKIX_OCSP = 130, + SEC_OID_PKIX_OCSP_BASIC_RESPONSE = 131, + SEC_OID_PKIX_OCSP_NONCE = 132, + SEC_OID_PKIX_OCSP_CRL = 133, + SEC_OID_PKIX_OCSP_RESPONSE = 134, + SEC_OID_PKIX_OCSP_NO_CHECK = 135, + SEC_OID_PKIX_OCSP_ARCHIVE_CUTOFF = 136, + SEC_OID_PKIX_OCSP_SERVICE_LOCATOR = 137, + SEC_OID_PKIX_REGCTRL_REGTOKEN = 138, + SEC_OID_PKIX_REGCTRL_AUTHENTICATOR = 139, + SEC_OID_PKIX_REGCTRL_PKIPUBINFO = 140, + SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS = 141, + SEC_OID_PKIX_REGCTRL_OLD_CERT_ID = 142, + SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY = 143, + SEC_OID_PKIX_REGINFO_UTF8_PAIRS = 144, + SEC_OID_PKIX_REGINFO_CERT_REQUEST = 145, + SEC_OID_EXT_KEY_USAGE_SERVER_AUTH = 146, + SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH = 147, + SEC_OID_EXT_KEY_USAGE_CODE_SIGN = 148, + SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT = 149, + SEC_OID_EXT_KEY_USAGE_TIME_STAMP = 150, + SEC_OID_OCSP_RESPONDER = 151, + + /* Netscape Algorithm OIDs */ + SEC_OID_NETSCAPE_SMIME_KEA = 152, + + /* Skipjack OID -- ### mwelch temporary */ + SEC_OID_FORTEZZA_SKIPJACK = 153, + + /* PKCS 12 V2 oids */ + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4 = 154, + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4 = 155, + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC = 156, + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC = 157, + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC = 158, + SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC = 159, + SEC_OID_PKCS12_SAFE_CONTENTS_ID = 160, + SEC_OID_PKCS12_PKCS8_SHROUDED_KEY_BAG_ID = 161, + + SEC_OID_PKCS12_V1_KEY_BAG_ID = 162, + SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID = 163, + SEC_OID_PKCS12_V1_CERT_BAG_ID = 164, + SEC_OID_PKCS12_V1_CRL_BAG_ID = 165, + SEC_OID_PKCS12_V1_SECRET_BAG_ID = 166, + SEC_OID_PKCS12_V1_SAFE_CONTENTS_BAG_ID = 167, + SEC_OID_PKCS9_X509_CERT = 168, + SEC_OID_PKCS9_SDSI_CERT = 169, + SEC_OID_PKCS9_X509_CRL = 170, + SEC_OID_PKCS9_FRIENDLY_NAME = 171, + SEC_OID_PKCS9_LOCAL_KEY_ID = 172, + SEC_OID_PKCS12_KEY_USAGE = 173, + + /*Diffe Helman OIDS */ + SEC_OID_X942_DIFFIE_HELMAN_KEY = 174, + + /* Netscape other name types */ + SEC_OID_NETSCAPE_NICKNAME = 175, + + /* Cert Server OIDS */ + SEC_OID_NETSCAPE_RECOVERY_REQUEST = 176, + + /* New PSM certificate management OIDs */ + SEC_OID_CERT_RENEWAL_LOCATOR = 177, + SEC_OID_NS_CERT_EXT_SCOPE_OF_USE = 178, + + /* CMS (RFC2630) OIDs */ + SEC_OID_CMS_EPHEMERAL_STATIC_DIFFIE_HELLMAN = 179, + SEC_OID_CMS_3DES_KEY_WRAP = 180, + SEC_OID_CMS_RC2_KEY_WRAP = 181, + + /* SMIME attributes */ + SEC_OID_SMIME_ENCRYPTION_KEY_PREFERENCE = 182, + + /* AES OIDs */ + SEC_OID_AES_128_ECB = 183, + SEC_OID_AES_128_CBC = 184, + SEC_OID_AES_192_ECB = 185, + SEC_OID_AES_192_CBC = 186, + SEC_OID_AES_256_ECB = 187, + SEC_OID_AES_256_CBC = 188, + + SEC_OID_SDN702_DSA_SIGNATURE = 189, + + SEC_OID_MS_SMIME_ENCRYPTION_KEY_PREFERENCE = 190, + + SEC_OID_SHA224 = 191, + SEC_OID_SHA256 = 192, + SEC_OID_SHA384 = 193, + SEC_OID_SHA512 = 194, + + SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION = 195, + SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION = 196, + SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION = 197, + + SEC_OID_AES_128_KEY_WRAP = 198, + SEC_OID_AES_192_KEY_WRAP = 199, + SEC_OID_AES_256_KEY_WRAP = 200, + + /* eContentType set by client and not understood by this library; treated + * like SEC_OID_PKCS7_DATA, except the caller's OID is encoded. */ + SEC_OID_OTHER = 201, + + /* ECDSA */ + SEC_OID_EC_PUBLIC_KEY = 202, + SEC_OID_ECDSA_WithSHA1 = 203, + SEC_OID_DH_SINGLE_STD_SHA1KDF = 204, + SEC_OID_SECP_256_R1 = 205, + SEC_OID_SECP_384_R1 = 206, + SEC_OID_SECP_521_R1 = 207, + + /* RFC 3161 Timestamping OIDs */ + SEC_OID_PKCS9_ID_CT_TSTInfo = 208, + SEC_OID_PKCS9_TIMESTAMP_TOKEN = 209, + SEC_OID_PKCS9_SIGNING_CERTIFICATE = 210, + + /* ECDSA with SHA2 */ + SEC_OID_ECDSA_WITH_SHA256 = 211, + SEC_OID_ECDSA_WITH_SHA384 = 212, + SEC_OID_ECDSA_WITH_SHA512 = 213, + + /* Apple CMS Attributes */ + SEC_OID_APPLE_HASH_AGILITY = 214, + SEC_OID_APPLE_HASH_AGILITY_V2 = 215, + + /* Apple Expiration Time Attribute */ + SEC_OID_APPLE_EXPIRATION_TIME = 216, + + SEC_OID_TOTAL +} SECOidTag; + +#if TARGET_OS_OSX +/*! + @function + @abstract Create a new SecArenaPool object. + @param chunksize Size of the chunks the pool will use to allocate its underlying storage. + @param outArena pointer to a SecArenaPoolRef to be created. + @result On success return 0 and outArena will contain a newly created SecArenaPoolRef. + @availability 10.4 and later + @updated 2004-04-23 + */ +OSStatus SecArenaPoolCreate(size_t chunksize, SecArenaPoolRef *outArena); + +/*! + @function + @abstract Free a SecArenaPool object and everything in it. + @param arena The SecArenaPool object to free. + @param zero If this is true the arena's memory will be zero filled before it is freed. + @discussion arena will no longer be valid and the memory used by it is returned to the malloc heap. + @availability 10.4 and later + @updated 2004-04-23 + */ +void SecArenaPoolFree(SecArenaPoolRef arena, Boolean zero); +#endif // TARGET_OS_OSX + +__END_DECLS + +#endif /* _SECURITY_SECCMSBASE_H_ */ diff --git a/CMS/SecCmsContentInfo.h b/CMS/SecCmsContentInfo.h new file mode 100644 index 000000000..c799eb43b --- /dev/null +++ b/CMS/SecCmsContentInfo.h @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2004-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@ + */ + +/*! + @header SecCmsContentInfo.h + + @availability 10.4 and later + @abstract Interfaces of the CMS implementation. + @discussion The functions here implement functions for creating and + accessing ContentInfo objects that are part of Cryptographic + Message Syntax (CMS) objects as described in rfc3369. + */ + +#ifndef _SECURITY_SECCMSCONTENTINFO_H_ +#define _SECURITY_SECCMSCONTENTINFO_H_ 1 + +#include +#include + + +__BEGIN_DECLS + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +/*! @functiongroup ContentInfo accessors */ +/*! + @function + @abstract Get content's contentInfo (if it exists). + @param cinfo A ContentInfo object of which we want to get the child contentInfo. + @result The child ContentInfo object, or NULL if there is none. + @discussion This function requires a ContentInfo object which is usually created by decoding and SecCmsMessage using a SecCmsDecoder. + @availability 10.4 and later + */ +extern SecCmsContentInfoRef +SecCmsContentInfoGetChildContentInfo(SecCmsContentInfoRef cinfo); + +/*! + @function + @abstract Get pointer to inner content + @discussion needs to be casted... + */ +extern void * +SecCmsContentInfoGetContent(SecCmsContentInfoRef cinfo); + +#if TARGET_OS_OSX +/*! + @function + @abstract Get pointer to innermost content + @discussion This is typically only called by SecCmsMessageGetContent(). + */ +extern CSSM_DATA_PTR +SecCmsContentInfoGetInnerContent(SecCmsContentInfoRef cinfo) + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); +#else // !TARGET_OS_OSX +/*! + @function + @abstract Get pointer to innermost content + @discussion This is typically only called by SecCmsMessageGetContent(). + */ +extern const SecAsn1Item * +SecCmsContentInfoGetInnerContent(SecCmsContentInfoRef cinfo) + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); +#endif // !TARGET_OS_OSX + +/*! + @function + @abstract Find out and return the inner content type. + */ +extern SECOidTag +SecCmsContentInfoGetContentTypeTag(SecCmsContentInfoRef cinfo); + + +#if TARGET_OS_OSX +/*! + @function + @abstract Find out and return the inner content type. + @discussion Caches pointer to lookup result for future reference. + */ +extern CSSM_OID * +SecCmsContentInfoGetContentTypeOID(SecCmsContentInfoRef cinfo) + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); +#else // !TARGET_OS_OSX +/*! + @function + @abstract Find out and return the inner content type. + @discussion Caches pointer to lookup result for future reference. + */ +extern SecAsn1Oid * +SecCmsContentInfoGetContentTypeOID(SecCmsContentInfoRef cinfo) + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); +#endif // !TARGET_OS_OSX + +/*! + @function + @abstract Find out and return the content encryption algorithm tag. + */ +extern SECOidTag +SecCmsContentInfoGetContentEncAlgTag(SecCmsContentInfoRef cinfo); + +/*! + @function + @abstract Find out and return the content encryption algorithm. + @discussion Caches pointer to lookup result for future reference. + */ +extern SECAlgorithmID * +SecCmsContentInfoGetContentEncAlg(SecCmsContentInfoRef cinfo) + API_AVAILABLE(macos(10.4), ios(2.0)); + +/*! @functiongroup Message construction */ + +#if TARGET_OS_OSX +/*! + @function + @abstract Set a ContentInfos content to a Data + @param cmsg A Message object to which the cinfo object belongs. + @param cinfo A ContentInfo object of which we want set the content. + @param data A pointer to a CSSM_DATA object or NULL if data will be provided during SecCmsEncoderUpdate calls. + @param detached True if the content is to be deattched from the CMS message rather than included within it. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion This function requires a ContentInfo object which can be made by creating a SecCmsMessage object. If the call succeeds the passed in data will be owned by the reciever. The data->Data must have been allocated using the cmsg's SecArenaPool if it is present. + @availability 10.4 through 10.7 + */ +extern OSStatus +SecCmsContentInfoSetContentData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, CSSM_DATA_PTR data, Boolean detached) + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); +#else // !TARGET_OS_OSX +/*! + @function + @abstract Set a ContentInfos content to a Data + @param cinfo A ContentInfo object of which we want set the content. + @param data A CFDataRef or NULL if data will be provided during SecCmsEncoderUpdate calls. + @param detached True if the content is to be deattched from the CMS message rather than included within it. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion This function requires a ContentInfo object which can be made by creating a SecCmsMessage object. + @availability 10.4 and later + */ +extern OSStatus +SecCmsContentInfoSetContentData(SecCmsContentInfoRef cinfo, CFDataRef data, Boolean detached) + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); +#endif // !TARGET_OS_OSX + +#if TARGET_OS_OSX +/*! + @function + @abstract Set a ContentInfos content to a SignedData. + @param cmsg A Message object to which the cinfo object belongs. + @param cinfo A ContentInfo object of which we want set the content. + @param sigd A SignedData object to set as the content of the cinfo object. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion This function requires a ContentInfo object which can be made by creating a SecCmsMessage object and a SignedData which can be made by calling SecCmsSignedDataCreate(). If the call succeeds the passed in SignedData object will be owned by the reciever. The Message object of the SignedData object must be the same as cmsg. + @availability 10.4 and later + */ +extern OSStatus +SecCmsContentInfoSetContentSignedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsSignedDataRef sigd) + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); +#else // !TARGET_OS_OSX +/*! + @function + @abstract Set a ContentInfos content to a SignedData. + @param cinfo A ContentInfo object of which we want set the content. + @param sigd A SignedData object to set as the content of the cinfo object. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion This function requires a ContentInfo object which can be made by creating a SecCmsMessage object and a SignedData which can be made by calling SecCmsSignedDataCreate(). If the call succeeds the passed in SignedData object will be owned by the reciever. The Message object of the SignedData object must be the same as cmsg. + @availability 10.4 and later + */ +extern OSStatus +SecCmsContentInfoSetContentSignedData(SecCmsContentInfoRef cinfo, SecCmsSignedDataRef sigd) + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); +#endif // TARGET_OS_OSX + +#if TARGET_OS_OSX +/*! + @function + @abstract Set a ContentInfos content to a EnvelopedData. + @param cmsg A Message object to which the cinfo object belongs. + @param cinfo A ContentInfo object of which we want set the content. + @param envd A EnvelopedData object to set as the content of the cinfo object. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion This function requires a ContentInfo object which can be made by creating a SecCmsMessage object and a EnvelopedData which can be made by calling SecCmsEnvelopedDataCreate(). If the call succeeds the passed in EnvelopedData object will be owned by the reciever. The Message object of the EnvelopedData object must be the same as cmsg. + @availability 10.4 and later + */ +extern OSStatus +SecCmsContentInfoSetContentEnvelopedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsEnvelopedDataRef envd) + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); +#else // !TARGET_OS_OSX +/*! + @function + @abstract Set a ContentInfos content to a EnvelopedData. + @param cinfo A ContentInfo object of which we want set the content. + @param envd A EnvelopedData object to set as the content of the cinfo object. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion This function requires a ContentInfo object which can be made by creating a SecCmsMessage object and a EnvelopedData which can be made by calling SecCmsEnvelopedDataCreate(). If the call succeeds the passed in EnvelopedData object will be owned by the reciever. The Message object of the EnvelopedData object must be the same as cmsg. + @availability 10.4 and later + */ +extern OSStatus +SecCmsContentInfoSetContentEnvelopedData(SecCmsContentInfoRef cinfo, SecCmsEnvelopedDataRef envd) + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); +#endif // !TARGET_OS_OSX + +#if TARGET_OS_OSX +/*! + @function + @abstract Set a ContentInfos content to a DigestedData. + @param cmsg A Message object to which the cinfo object belongs. + @param cinfo A ContentInfo object of which we want set the content. + @param digd A DigestedData object to set as the content of the cinfo object. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion This function requires a ContentInfo object which can be made by creating a SecCmsMessage object and a DigestedData which can be made by calling SecCmsDigestedDataCreate(). If the call succeeds the passed in DigestedData object will be owned by the reciever. The Message object of the DigestedData object must be the same as cmsg. + @availability 10.4 and later + */ +extern OSStatus +SecCmsContentInfoSetContentDigestedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsDigestedDataRef digd) + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); +#else // !TARGET_OS_OSX +/*! + @function + @abstract Set a ContentInfos content to a DigestedData. + @param cinfo A ContentInfo object of which we want set the content. + @param digd A DigestedData object to set as the content of the cinfo object. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion This function requires a ContentInfo object which can be made by creating a SecCmsMessage object and a DigestedData which can be made by calling SecCmsDigestedDataCreate(). If the call succeeds the passed in DigestedData object will be owned by the reciever. The Message object of the DigestedData object must be the same as cmsg. + @availability 10.4 and later + */ +extern OSStatus +SecCmsContentInfoSetContentDigestedData(SecCmsContentInfoRef cinfo, SecCmsDigestedDataRef digd) + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); +#endif // !TARGET_OS_OSX + +#if TARGET_OS_OSX +/*! + @function + @abstract Set a ContentInfos content to a EncryptedData. + @param cmsg A Message object to which the cinfo object belongs. + @param cinfo A ContentInfo object of which we want set the content. + @param encd A EncryptedData object to set as the content of the cinfo object. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion This function requires a ContentInfo object which can be made by creating a SecCmsMessage object and a EncryptedData which can be made by calling SecCmsEncryptedDataCreate(). If the call succeeds the passed in EncryptedData object will be owned by the reciever. The Message object of the EncryptedData object must be the same as cmsg. + @availability 10.4 and later + */ +extern OSStatus +SecCmsContentInfoSetContentEncryptedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsEncryptedDataRef encd) + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); +#else // !TARGET_OS_OSX +/*! + @function + @abstract Set a ContentInfos content to a EncryptedData. + @param cinfo A ContentInfo object of which we want set the content. + @param encd A EncryptedData object to set as the content of the cinfo object. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion This function requires a ContentInfo object which can be made by creating a SecCmsMessage object and a EncryptedData which can be made by calling SecCmsEncryptedDataCreate(). If the call succeeds the passed in EncryptedData object will be owned by the reciever. The Message object of the EncryptedData object must be the same as cmsg. + @availability 10.4 and later + */ +extern OSStatus +SecCmsContentInfoSetContentEncryptedData(SecCmsContentInfoRef cinfo, SecCmsEncryptedDataRef encd) + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); +#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); +#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); +#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); +#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); +#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); +#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); +#endif // !!TARGET_OS_OSX + +/*! + @function + */ +extern void +SecCmsContentInfoSetBulkKey(SecCmsContentInfoRef cinfo, SecSymmetricKeyRef bulkkey) + API_AVAILABLE(macos(10.4),ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + +/*! + @function + */ +extern SecSymmetricKeyRef +SecCmsContentInfoGetBulkKey(SecCmsContentInfoRef cinfo) + API_AVAILABLE(macos(10.4),ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + +/*! + @function + */ +extern int +SecCmsContentInfoGetBulkKeySize(SecCmsContentInfoRef cinfo); + +#pragma clang diagnostic pop + +__END_DECLS + +#endif /* _SECURITY_SECCMSCONTENTINFO_H_ */ diff --git a/CMS/SecCmsDecoder.h b/CMS/SecCmsDecoder.h new file mode 100644 index 000000000..b1eb50eca --- /dev/null +++ b/CMS/SecCmsDecoder.h @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2004-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@ + */ + +/*! + @header SecCmsDecoder.h + + @availability 10.4 and later + @abstract Interfaces of the CMS implementation. + @discussion The functions here implement functions for encoding + and decoding Cryptographic Message Syntax (CMS) objects + as described in rfc3369. + */ + +#ifndef _SECURITY_SECCMSDECODER_H_ +#define _SECURITY_SECCMSDECODER_H_ 1 + +#include + +__BEGIN_DECLS + +/*! @functiongroup Streaming interface */ + +#if TARGET_OS_OSX +/*! + @function + @abstract Set up decoding of a BER-encoded CMS message. + @param arena An ArenaPool object to use for the resulting message, or NULL if new ArenaPool + should be created. + @param cb callback function for delivery of inner content inner + content will be stored in the message if cb is NULL. + @param cb_arg first argument passed to cb when it is called. + @param pwfn callback function for getting token password for + enveloped data content with a password recipient. + @param pwfn_arg first argument passed to pwfn when it is called. + @param decrypt_key_cb callback function for getting bulk key + for encryptedData content. + @param decrypt_key_cb_arg first argument passed to decrypt_key_cb + when it is called. + @param outDecoder On success will contain a pointer to a newly created SecCmsDecoder. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion Create a SecCmsDecoder(). If this function returns noErr, the caller must dispose of the returned outDecoder by calling SecCmsDecoderDestroy() or SecCmsDecoderFinish(). + @availability 10.4 through 10.7 + */ +extern OSStatus +SecCmsDecoderCreate(SecArenaPoolRef arena, + SecCmsContentCallback cb, void *cb_arg, + PK11PasswordFunc pwfn, void *pwfn_arg, + SecCmsGetDecryptKeyCallback decrypt_key_cb, void + *decrypt_key_cb_arg, + SecCmsDecoderRef *outDecoder) + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); +#else // !TARGET_OS_OSX +/*! + @function + @abstract Set up decoding of a BER-encoded CMS message. + @param cb callback function for delivery of inner content inner + content will be stored in the message if cb is NULL. + @param cb_arg first argument passed to cb when it is called. + @param pwfn callback function for getting token password for + enveloped data content with a password recipient. + @param pwfn_arg first argument passed to pwfn when it is called. + @param decrypt_key_cb callback function for getting bulk key + for encryptedData content. + @param decrypt_key_cb_arg first argument passed to decrypt_key_cb + when it is called. + @param outDecoder On success will contain a pointer to a newly created SecCmsDecoder. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion Create a SecCmsDecoder(). If this function returns errSecSuccess, the caller must dispose of the returned outDecoder by calling SecCmsDecoderDestroy() or SecCmsDecoderFinish(). + @availability 10.4 and later + */ +extern OSStatus +SecCmsDecoderCreate(SecCmsContentCallback cb, void *cb_arg, + PK11PasswordFunc pwfn, void *pwfn_arg, + SecCmsGetDecryptKeyCallback decrypt_key_cb, void + *decrypt_key_cb_arg, + SecCmsDecoderRef *outDecoder) + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); +#endif // !TARGET_OS_OSX + +/*! + @function + @abstract Feed BER-encoded data to decoder. + @param decoder Pointer to a SecCmsDecoderContext created with SecCmsDecoderCreate(). + @param buf Pointer to bytes to be decoded. + @param len number of bytes to decode. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion If a call to this function fails the caller should call SecCmsDecoderDestroy(). + @availability 10.4 and later + */ +extern OSStatus +SecCmsDecoderUpdate(SecCmsDecoderRef decoder, const void *buf, CFIndex len); + +/*! + @function + @abstract Abort a (presumably failed) decoding process. + @param decoder Pointer to a SecCmsDecoderContext created with SecCmsDecoderCreate(). + @availability 10.4 and later + */ +extern void +SecCmsDecoderDestroy(SecCmsDecoderRef decoder); + +/*! + @function + @abstract Mark the end of inner content and finish decoding. + @param decoder Pointer to a SecCmsDecoderContext created with SecCmsDecoderCreate(). + @param outMessage On success a pointer to a SecCmsMessage containing the decoded message. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion decoder is no longer valid after this function is called. + @availability 10.4 and later + */ +extern OSStatus +SecCmsDecoderFinish(SecCmsDecoderRef decoder, SecCmsMessageRef *outMessage); + +/*! @functiongroup One shot interface */ +#if TARGET_OS_OSX +/*! + @function + @abstract Decode a CMS message from BER encoded data. + @discussion This function basically does the same as calling + SecCmsDecoderStart(), SecCmsDecoderUpdate() and SecCmsDecoderFinish(). + @param encodedMessage Pointer to a CSSM_DATA containing the BER encoded cms + message to decode. + @param cb callback function for delivery of inner content inner + content will be stored in the message if cb is NULL. + @param cb_arg first argument passed to cb when it is called. + @param pwfn callback function for getting token password for enveloped + data content with a password recipient. + @param pwfn_arg first argument passed to pwfn when it is called. + @param decrypt_key_cb callback function for getting bulk key for encryptedData content. + @param decrypt_key_cb_arg first argument passed to decrypt_key_cb when it is called. + @param outMessage On success a pointer to a SecCmsMessage containing the decoded message. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion decoder is no longer valid after this function is called. + @availability 10.4 through 10.7 + */ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +extern OSStatus +SecCmsMessageDecode(const CSSM_DATA *encodedMessage, + SecCmsContentCallback cb, void *cb_arg, + PK11PasswordFunc pwfn, void *pwfn_arg, + SecCmsGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg, + SecCmsMessageRef *outMessage) + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); +#pragma clang diagnostic pop +#else // !TARGET_OS_OSX +/*! + @function + @abstract Decode a CMS message from BER encoded data. + @discussion This function basically does the same as calling + SecCmsDecoderStart(), SecCmsDecoderUpdate() and SecCmsDecoderFinish(). + @param encodedMessage Pointer to a SecAsn1Item containing the BER encoded cms + message to decode. + @param cb callback function for delivery of inner content inner + content will be stored in the message if cb is NULL. + @param cb_arg first argument passed to cb when it is called. + @param pwfn callback function for getting token password for enveloped + data content with a password recipient. + @param pwfn_arg first argument passed to pwfn when it is called. + @param decrypt_key_cb callback function for getting bulk key for encryptedData content. + @param decrypt_key_cb_arg first argument passed to decrypt_key_cb when it is called. + @param outMessage On success a pointer to a SecCmsMessage containing the decoded message. + @result A result code. See "SecCmsBase.h" for possible results. + @discussion decoder is no longer valid after this function is called. + @availability 10.4 and later + */ +extern OSStatus +SecCmsMessageDecode(const SecAsn1Item *encodedMessage, + SecCmsContentCallback cb, void *cb_arg, + 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); +#endif // !TARGET_OS_OSX + + +__END_DECLS + +#endif /* _SECURITY_SECCMSDECODER_H_ */ diff --git a/CMS/SecCmsDigestContext.h b/CMS/SecCmsDigestContext.h new file mode 100644 index 000000000..159a28271 --- /dev/null +++ b/CMS/SecCmsDigestContext.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2004-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@ + */ + +/*! + @header SecCmsDigestContext.h + + @availability 10.4 and later + @abstract Interfaces of the CMS implementation. + @discussion The functions here implement functions calculating digests. + */ + +#ifndef _SECURITY_SECCMSDIGESTCONTEXT_H_ +#define _SECURITY_SECCMSDIGESTCONTEXT_H_ 1 + +#include + +__BEGIN_DECLS + +/*! + @function + @abstract Start digest calculation using all the digest algorithms in "digestalgs" in parallel. + */ +#pragma clang diagnostic push +#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); +#pragma clang diagnostic pop + +/*! + @function + @abstract Feed more data into the digest machine. + */ +extern void +SecCmsDigestContextUpdate(SecCmsDigestContextRef cmsdigcx, const unsigned char *data, size_t len); + +/*! + @function + @abstract Cancel digesting operation in progress and destroy it. + @discussion Cancel a DigestContext created with @link SecCmsDigestContextStartMultiple SecCmsDigestContextStartMultiple function@/link. + */ +extern void +SecCmsDigestContextCancel(SecCmsDigestContextRef cmsdigcx); + +#if TARGET_OS_IPHONE +/*! + @function + @abstract Destroy a SecCmsDigestContextRef. + @discussion Cancel a DigestContext created with @link SecCmsDigestContextStartMultiple SecCmsDigestContextStartMultiple function@/link after it has been used in a @link SecCmsSignedDataSetDigestContext SecCmsSignedDataSetDigestContext function@/link. + */ +extern void +SecCmsDigestContextDestroy(SecCmsDigestContextRef cmsdigcx) + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); +#endif // TARGET_OS_IPHONE + +#if TARGET_OS_OSX +/*! + @function + @abstract Finish the digests and put them into an array of CSSM_DATAs (allocated on arena) + */ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +extern OSStatus +SecCmsDigestContextFinishMultiple(SecCmsDigestContextRef cmsdigcx, SecArenaPoolRef arena, + CSSM_DATA_PTR **digestsp) + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); +#pragma clang diagnostic pop +#endif // TARGET_OS_OSX + +__END_DECLS + +#endif /* _SECURITY_SECCMSDIGESTCONTEXT_H_ */ diff --git a/CMS/SecCmsDigestedData.h b/CMS/SecCmsDigestedData.h new file mode 100644 index 000000000..6fc48c998 --- /dev/null +++ b/CMS/SecCmsDigestedData.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2004-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@ + */ + +/*! + @header SecCmsDigestedData.h + + @availability 10.4 and later + @abstract Interfaces of the CMS implementation. + @discussion The functions here implement functions for creating + and accessing the DigestData content type of a + Cryptographic Message Syntax (CMS) object + as described in rfc3369. + */ + +#ifndef _SECURITY_SECCMSDIGESTEDDATA_H_ +#define _SECURITY_SECCMSDIGESTEDDATA_H_ 1 + +#include + +__BEGIN_DECLS + +/*! + @function + @abstract Create a digestedData object (presumably for encoding). + @discussion Version will be set by SecCmsDigestedDataEncodeBeforeStart + digestAlg is passed as parameter + contentInfo must be filled by the user + digest will be calculated while encoding + */ +#pragma clang diagnostic push +#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); +#pragma clang diagnostic pop + +/*! + @function + @abstract Destroy a digestedData object. + */ +extern void +SecCmsDigestedDataDestroy(SecCmsDigestedDataRef digd); + +/*! + @function + @abstract Return pointer to digestedData object's contentInfo. + */ +extern SecCmsContentInfoRef +SecCmsDigestedDataGetContentInfo(SecCmsDigestedDataRef digd); + +__END_DECLS + +#endif /* _SECURITY_SECCMSDIGESTEDDATA_H_ */ diff --git a/CMS/SecCmsEncoder.h b/CMS/SecCmsEncoder.h new file mode 100644 index 000000000..102c39af8 --- /dev/null +++ b/CMS/SecCmsEncoder.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2004-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@ + */ + +/*! + @header SecCmsEncoder.h + + @availability 10.4 and later + @abstract CMS message encoding + @discussion The functions here implement functions for encoding + Cryptographic Message Syntax (CMS) objects as described + in rfc3369. + A SecCmsEncoder object is used to encode CMS messages into BER. + */ + +#ifndef _SECURITY_SECCMSENCODER_H_ +#define _SECURITY_SECCMSENCODER_H_ 1 + +#include +#include + + +__BEGIN_DECLS + +/*! @functiongroup Streaming interface */ + +#if TARGET_OS_OSX +/*! + @function + @abstract Set up encoding of a CMS message. + @param outputfn callback function for delivery of BER-encoded output will + not be called if NULL. + @param outputarg first argument passed to outputfn when it is called. + @param dest If non-NULL, pointer to a CSSM_DATA that will hold the + BER-encoded output. + @param destpoolp Pool to allocate BER-encoded output in. + @param pwfn callback function for getting token password for enveloped + data content with a password recipient. + @param pwfn_arg first argument passed to pwfn when it is called. + @param encrypt_key_cb callback function for getting bulk key for encryptedData content. + @param encrypt_key_cb_arg first argument passed to encrypt_key_cb when it is + called. + @param detached_digestalgs digest algorithms in detached_digests + @param detached_digests digests from detached content (one for every element + in detached_digestalgs). + @result On success a pointer to a SecCmsMessage containing the decoded message + is returned. On failure returns NULL. Call PR_GetError() to find out what + went wrong in this case. + @availability 10.4 through 10.7 + */ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +extern OSStatus +SecCmsEncoderCreate(SecCmsMessageRef cmsg, + SecCmsContentCallback outputfn, void *outputarg, + CSSM_DATA_PTR dest, SecArenaPoolRef destpoolp, + PK11PasswordFunc pwfn, void *pwfn_arg, + 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); +#pragma clang diagnostic pop +#else // !TARGET_OS_OSX +/*! + @function + @abstract Set up encoding of a CMS message. + @param cmsg The SecCmsMessageRef to be encoded. + @param outputfn callback function for delivery of BER-encoded output will + not be called if NULL. + @param outputarg first argument passed to outputfn when it is called. + @param outBer If non-NULL, a CFMutableDataRef to which the + BER-encoded output will be appended. + @param pwfn callback function for getting token password for enveloped + data content with a password recipient. + @param pwfn_arg first argument passed to pwfn when it is called. + @param encrypt_key_cb callback function for getting bulk key for encryptedData content. + @param encrypt_key_cb_arg first argument passed to encrypt_key_cb when it is + called. + @result On success a pointer to a SecCmsMessage containing the decoded message + is returned. On failure returns NULL. Call PR_GetError() to find out what + went wrong in this case. + @availability 10.4 and later + */ +extern OSStatus +SecCmsEncoderCreate(SecCmsMessageRef cmsg, + SecCmsContentCallback outputfn, void *outputarg, + CFMutableDataRef outBer, + 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); +#endif // !TARGET_OS_OSX + +/*! + @function + @abstract Take content data delivery from the user + @param encoder encoder context + @param data content data + @param len length of content data + @result On success 0 is returned. On failure returns non zero. Call + PR_GetError() to find out what went wrong in this case. + @availability 10.4 and later + */ +extern OSStatus +SecCmsEncoderUpdate(SecCmsEncoderRef encoder, const void *data, CFIndex len); + +/*! + @function + @abstract Abort a (presumably failed) encoding process. + @param encoder Pointer to a SecCmsEncoderContext created with SecCmsEncoderCreate(). + @availability 10.4 and later + */ +extern void +SecCmsEncoderDestroy(SecCmsEncoderRef encoder); + +/*! + @function + @abstract Signal the end of data. + @discussion Walks down the chain of encoders and the finishes them from the + innermost out. + @param encoder Pointer to a SecCmsEncoder created with SecCmsEncoderCreate(). + @result On success 0 is returned. On failure returns non zero. Call + PR_GetError() to find out what went wrong in this case. + @availability 10.4 and later + */ +extern OSStatus +SecCmsEncoderFinish(SecCmsEncoderRef encoder); + +/*! @functiongroup One shot interface */ +#if TARGET_OS_OSX +/*! + @function + @abstract BER Encode a CMS message. + @discussion BER Encode a CMS message, with input being the plaintext message and outBer being the output, stored in arena's pool. + */ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +extern OSStatus +SecCmsMessageEncode(SecCmsMessageRef cmsg, const CSSM_DATA *input, SecArenaPoolRef arena, + CSSM_DATA_PTR outBer) + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); +#pragma clang diagnostic pop +#else // !TARGET_OS_OSX +/*! + @function + @abstract BER Encode a CMS message. + @param cmsg The SecCmsMessageRef to be encoded. + @param input The inner content of the message. + @param outBer A CFMutableDataRef to which the + BER-encoded output will be appended. + @discussion BER Encode a CMS message, with input being the plaintext message and outBer being the output, stored in arena's pool. + */ +extern OSStatus +SecCmsMessageEncode(SecCmsMessageRef cmsg, const SecAsn1Item *input, + CFMutableDataRef outBer) + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); +#endif // !TARGET_OS_OSX + +__END_DECLS + +#endif /* _SECURITY_SECCMSENCODER_H_ */ diff --git a/CMS/SecCmsEncryptedData.h b/CMS/SecCmsEncryptedData.h new file mode 100644 index 000000000..b45c3eaa8 --- /dev/null +++ b/CMS/SecCmsEncryptedData.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2004-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@ + */ + +/*! + @header SecCmsEnvelopedData.h + + @availability 10.4 and later + @abstract Interfaces of the CMS implementation. + @discussion The functions here implement functions for encoding + and decoding Cryptographic Message Syntax (CMS) objects + as described in rfc3369. + */ + +#ifndef _SECURITY_SECCMSENCRYPTEDDATA_H_ +#define _SECURITY_SECCMSENCRYPTEDDATA_H_ 1 + +#include + +__BEGIN_DECLS + +/*! + @function + @abstract Create an empty EncryptedData object. + @param algorithm Specifies the bulk encryption algorithm to use. + @param keysize is the key size. + @discussion An error results in a return value of NULL and an error set. + (Retrieve specific errors via PORT_GetError()/XP_GetError().) + */ +extern SecCmsEncryptedDataRef +SecCmsEncryptedDataCreate(SecCmsMessageRef cmsg, SECOidTag algorithm, int keysize); + +/*! + @function + @abstract Destroy an encryptedData object. + */ +extern void +SecCmsEncryptedDataDestroy(SecCmsEncryptedDataRef encd); + +/*! + @function + @abstract Return pointer to an EncryptedData object's contentInfo. + */ +extern SecCmsContentInfoRef +SecCmsEncryptedDataGetContentInfo(SecCmsEncryptedDataRef encd); + +__END_DECLS + +#endif /* _SECURITY_SECCMSENCRYPTEDDATA_H_ */ diff --git a/CMS/SecCmsEnvelopedData.h b/CMS/SecCmsEnvelopedData.h new file mode 100644 index 000000000..642dc9569 --- /dev/null +++ b/CMS/SecCmsEnvelopedData.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2004-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@ + */ + +/*! + @header SecCmsEnvelopedData.h + + @availability 10.4 and later + @abstract Interfaces of the CMS implementation. + @discussion The functions here implement functions for encoding + and decoding Cryptographic Message Syntax (CMS) objects + as described in rfc3369. + */ + +#ifndef _SECURITY_SECCMSENVELOPEDDATA_H_ +#define _SECURITY_SECCMSENVELOPEDDATA_H_ 1 + +#include + +__BEGIN_DECLS + +/*! + @function + @abstract Create an enveloped data message. + */ +extern SecCmsEnvelopedDataRef +SecCmsEnvelopedDataCreate(SecCmsMessageRef cmsg, SECOidTag algorithm, int keysize); + +/*! + @function + @abstract Destroy an enveloped data message. + */ +extern void +SecCmsEnvelopedDataDestroy(SecCmsEnvelopedDataRef edp); + +/*! + @function + @abstract Return pointer to this envelopedData's contentinfo. + */ +extern SecCmsContentInfoRef +SecCmsEnvelopedDataGetContentInfo(SecCmsEnvelopedDataRef envd); + +#if TARGET_OS_OSX +/*! + @function + @abstract Add a recipientinfo to the enveloped data msg. + @discussion Rip must be created on the same pool as edp - this is not enforced, though. + */ +extern OSStatus +SecCmsEnvelopedDataAddRecipient(SecCmsEnvelopedDataRef edp, SecCmsRecipientInfoRef rip); +#endif + +__END_DECLS + +#endif /* _SECURITY_SECCMSENVELOPEDDATA_H_ */ diff --git a/CMS/SecCmsMessage.h b/CMS/SecCmsMessage.h new file mode 100644 index 000000000..497c4677b --- /dev/null +++ b/CMS/SecCmsMessage.h @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2004-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@ + */ + +/*! + @header SecCmsMessage.h + + @availability 10.4 and later + @abstract CMS message object interfaces + @abstract Interfaces of the CMS implementation. + @discussion A SecCmsMessage represent a Cryptographic Message + Syntax (CMS) object as described in rfc3369. + It can be encoded using a SecCmsEncoder into BER + data or obtained from a SecCmsDecoder and examined + using the functions below. + */ + +#ifndef _SECURITY_SECCMSMESSAGE_H_ +#define _SECURITY_SECCMSMESSAGE_H_ 1 + +#include + +__BEGIN_DECLS + +#if TARGET_OS_OSX + +/*! + @function + @abstract Create a CMS message object. + @param poolp Arena to allocate memory from, or NULL if new arena should + be created. + @result A pointer to a newly created SecCmsMessage. When finished using + this the caller should call SecCmsMessageDestroy(). On failure + returns NULL. In this case call PR_GetError() to find out what went + wrong. + */ +extern SecCmsMessageRef +SecCmsMessageCreate(SecArenaPoolRef poolp) + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + +#else // !TARGET_OS_OSX + +/*! + @function + @abstract Create a CMS message object. + @result A pointer to a newly created SecCmsMessage. When finished using + this the caller should call SecCmsMessageDestroy(). On failure + returns NULL. In this case call PR_GetError() to find out what went + wrong. + */ +extern SecCmsMessageRef +SecCmsMessageCreate(void) + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); + +#endif // !TARGET_OS_OSX + +/*! + @function + @abstract Destroy a CMS message and all of its sub-pieces. + @param cmsg Pointer to a SecCmsMessage object. + */ +extern void +SecCmsMessageDestroy(SecCmsMessageRef cmsg); + +/*! + @function + @abstract Return a copy of the given message. + @discussion The copy may be virtual or may be real -- either way, the + result needs to be passed to SecCmsMessageDestroy later (as does the + original). + @param cmsg Pointer to a SecCmsMessage object. + */ +extern SecCmsMessageRef +SecCmsMessageCopy(SecCmsMessageRef cmsg); + +#if SEC_OS_OSX +/*! + @function + @abstract Return a pointer to the message's arena pool. + */ +extern SecArenaPoolRef +SecCmsMessageGetArena(SecCmsMessageRef cmsg); +#endif + +/*! + @function + @abstract Return a pointer to the top level contentInfo. + */ +extern SecCmsContentInfoRef +SecCmsMessageGetContentInfo(SecCmsMessageRef cmsg); + +#if TARGET_OS_OSX +/*! + @function + @abstract Return a pointer to the actual content. + @discussion In the case of those types which are encrypted, this returns the *plain* content. + In case of nested contentInfos, this descends and retrieves the innermost content. + */ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +extern CSSM_DATA_PTR +SecCmsMessageGetContent(SecCmsMessageRef cmsg) + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); +#pragma clang diagnostic pop +#else // !TARGET_OS_OSX +/*! + @function + @abstract Return a pointer to the actual content. + @discussion In the case of those types which are encrypted, this returns the *plain* content. + In case of nested contentInfos, this descends and retrieves the innermost content. + */ +extern const SecAsn1Item * +SecCmsMessageGetContent(SecCmsMessageRef cmsg) + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); +#endif // !TARGET_OS_OSX + +/*! + @function + @abstract Count number of levels of CMS content objects in this message. + @discussion CMS data content objects do not count. + */ +extern int +SecCmsMessageContentLevelCount(SecCmsMessageRef cmsg); + +/*! + @function + @abstract Find content level #n. + @discussion CMS data content objects do not count. + */ +extern SecCmsContentInfoRef +SecCmsMessageContentLevel(SecCmsMessageRef cmsg, int n); + +/*! + @function + @abstract See if message contains certs along the way. + */ +extern Boolean +SecCmsMessageContainsCertsOrCrls(SecCmsMessageRef cmsg); + +/*! + @function + @abstract See if message contains a encrypted submessage. + */ +extern Boolean +SecCmsMessageIsEncrypted(SecCmsMessageRef cmsg); + +/*! + @function + @abstract See if message contains a signed submessage + @discussion If the CMS message has a SignedData with a signature (not just a SignedData) + return true; false otherwise. This can/should be called before calling + VerifySignature, which will always indicate failure if no signature is + present, but that does not mean there even was a signature! + Note that the content itself can be empty (detached content was sent + another way); it is the presence of the signature that matters. + */ +extern Boolean +SecCmsMessageIsSigned(SecCmsMessageRef cmsg); + +/*! + @function + @abstract See if content is empty. + @result Returns PR_TRUE is innermost content length is < minLen + @discussion XXX need the encrypted content length (why?) + */ +extern Boolean +SecCmsMessageIsContentEmpty(SecCmsMessageRef cmsg, unsigned int minLen); + +#if TARGET_OS_OSX +extern Boolean +SecCmsMessageContainsTSTInfo(SecCmsMessageRef cmsg); +#endif + +__END_DECLS + +#endif /* _SECURITY_SECCMSMESSAGE_H_ */ diff --git a/CMS/SecCmsRecipientInfo.h b/CMS/SecCmsRecipientInfo.h new file mode 100644 index 000000000..f57481fd7 --- /dev/null +++ b/CMS/SecCmsRecipientInfo.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2004-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@ + */ + +/*! + @header SecCmsRecipientInfo.h + + @availability 10.4 and later + @abstract Interfaces of the CMS implementation. + @discussion The functions here implement functions for encoding + and decoding Cryptographic Message Syntax (CMS) objects + as described in rfc3369. + */ + +#ifndef _SECURITY_SECCMSRECIPIENTINFO_H_ +#define _SECURITY_SECCMSRECIPIENTINFO_H_ 1 + +#include + +__BEGIN_DECLS + +#if TARGET_OS_OSX +/*! + @function + @abstract Create a recipientinfo + @discussion We currently do not create KeyAgreement recipientinfos with multiple recipientEncryptedKeys + the certificate is supposed to have been verified by the caller + */ +extern SecCmsRecipientInfoRef +SecCmsRecipientInfoCreate(SecCmsMessageRef cmsg, SecCertificateRef cert) + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + +#else // !TARGET_OS_OSX + +/*! + @function + @abstract Create a recipientinfo + @discussion We currently do not create KeyAgreement recipientinfos with multiple recipientEncryptedKeys + the certificate is supposed to have been verified by the caller + */ +extern SecCmsRecipientInfoRef +SecCmsRecipientInfoCreate(SecCmsEnvelopedDataRef envd, SecCertificateRef cert) + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); +#endif // !TARGET_OS_OSX + + +#if TARGET_OS_OSX +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +extern SecCmsRecipientInfoRef +SecCmsRecipientInfoCreateWithSubjKeyID(SecCmsMessageRef cmsg, + CSSM_DATA_PTR subjKeyID, + SecPublicKeyRef pubKey) + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); +#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); +#endif // !TARGET_OS_OSX + + +#if TARGET_OS_OSX +extern SecCmsRecipientInfoRef +SecCmsRecipientInfoCreateWithSubjKeyIDFromCert(SecCmsMessageRef cmsg, + SecCertificateRef cert) + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); +#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); +#endif // !TARGET_OS_OSX + + +#if TARGET_OS_OSX +extern void +SecCmsRecipientInfoDestroy(SecCmsRecipientInfoRef ri); +#endif + +__END_DECLS + +#endif /* _SECURITY_SECCMSRECIPIENTINFO_H_ */ diff --git a/CMS/SecCmsSignedData.h b/CMS/SecCmsSignedData.h new file mode 100644 index 000000000..f74f89b23 --- /dev/null +++ b/CMS/SecCmsSignedData.h @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2004-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@ + */ + +/*! + @header SecCmsSignedData.h + + @availability 10.4 and later + @abstract Interfaces of the CMS implementation. + @discussion The functions here implement functions for encoding + and decoding Cryptographic Message Syntax (CMS) objects + as described in rfc3369. + */ + +#ifndef _SECURITY_SECCMSSIGNEDDATA_H_ +#define _SECURITY_SECCMSSIGNEDDATA_H_ 1 + +#include +#include + +__BEGIN_DECLS + +/*! + @function + @abstract Create a new SecCmsSignedData object. + @param cmsg Pointer to a SecCmsMessage in which this SecCmsSignedData + should be created. + */ +extern SecCmsSignedDataRef +SecCmsSignedDataCreate(SecCmsMessageRef cmsg); + +/*! + @function + */ +extern void +SecCmsSignedDataDestroy(SecCmsSignedDataRef sigd); + +/*! + @function + @abstract Retrieve the SignedData's signer list. + */ +extern SecCmsSignerInfoRef * +SecCmsSignedDataGetSignerInfos(SecCmsSignedDataRef sigd); + +/*! + @function + */ +extern int +SecCmsSignedDataSignerInfoCount(SecCmsSignedDataRef sigd); + +/*! + @function + */ +extern SecCmsSignerInfoRef +SecCmsSignedDataGetSignerInfo(SecCmsSignedDataRef sigd, int i); + +/*! + @function + @abstract Retrieve the SignedData's digest algorithm list. + */ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +extern SECAlgorithmID ** +SecCmsSignedDataGetDigestAlgs(SecCmsSignedDataRef sigd); +#pragma clang diagnostic pop + +/*! + @function + @abstract Return pointer to this signedData's contentinfo. + */ +extern SecCmsContentInfoRef +SecCmsSignedDataGetContentInfo(SecCmsSignedDataRef sigd); + +/*! + @function + @discussion XXX Should be obsoleted. + */ +extern OSStatus +SecCmsSignedDataImportCerts(SecCmsSignedDataRef sigd, SecKeychainRef keychain, + SECCertUsage certusage, Boolean keepcerts); + +/*! + @function + @abstract See if we have digests in place. + */ +extern Boolean +SecCmsSignedDataHasDigests(SecCmsSignedDataRef sigd); + +/*! + @function + @abstract Check the signatures. + @discussion The digests were either calculated during decoding (and are stored in the + signedData itself) or set after decoding using SecCmsSignedDataSetDigests. + + The verification checks if the signing cert is valid and has a trusted chain + for the purpose specified by "policies". + + If trustRef is NULL the cert chain is verified and the VerificationStatus is set accordingly. + Otherwise a SecTrust object is returned for the caller to evaluate using SecTrustEvaluate(). + */ +extern OSStatus +SecCmsSignedDataVerifySignerInfo(SecCmsSignedDataRef sigd, int i, SecKeychainRef keychainOrArray, + CFTypeRef policies, SecTrustRef *trustRef); + +/*! + @function + @abstract Verify the certs in a certs-only message. +*/ +extern OSStatus +SecCmsSignedDataVerifyCertsOnly(SecCmsSignedDataRef sigd, + SecKeychainRef keychainOrArray, + CFTypeRef policies); + +/*! + @function + */ +extern OSStatus +SecCmsSignedDataAddCertList(SecCmsSignedDataRef sigd, CFArrayRef certlist); + +/*! + @function + @abstract Add cert and its entire chain to the set of certs. + */ +extern OSStatus +SecCmsSignedDataAddCertChain(SecCmsSignedDataRef sigd, SecCertificateRef cert); + +/*! + @function + */ +extern OSStatus +SecCmsSignedDataAddCertificate(SecCmsSignedDataRef sigd, SecCertificateRef cert); + +/*! + @function + */ +extern Boolean +SecCmsSignedDataContainsCertsOrCrls(SecCmsSignedDataRef sigd); + + +#if TARGET_OS_OSX +/*! + @function + @abstract Retrieve the SignedData's certificate list. + */ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +extern CSSM_DATA_PTR * +SecCmsSignedDataGetCertificateList(SecCmsSignedDataRef sigd) + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); +#pragma clang diagnostic pop +#else // !TARGET_OS_OSX +/*! + @function + @abstract Retrieve the SignedData's certificate list. + */ +extern SecAsn1Item * * +SecCmsSignedDataGetCertificateList(SecCmsSignedDataRef sigd) + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(iosmac); +#endif // !TARGET_OS_OSX + +/*! + @function + @abstract Create a certs-only SignedData. + @param cert Base certificate that will be included + @param include_chain If true, include the complete cert chain for cert. + @discussion More certs and chains can be added via AddCertificate and AddCertChain. + @result An error results in a return value of NULL and an error set. + */ +extern SecCmsSignedDataRef +SecCmsSignedDataCreateCertsOnly(SecCmsMessageRef cmsg, SecCertificateRef cert, Boolean include_chain); + +#if TARGET_OS_IPHONE +/*! + @function + @abstract Finalize the digests in digestContext and apply them to sigd. + @param sigd A SecCmsSignedDataRef for which the digests have been calculated + @param digestContext A digestContext created with SecCmsDigestContextStartMultiple. + @result The digest will have been applied to sigd. After this call completes sigd is ready to accept + SecCmsSignedDataVerifySignerInfo() calls. The caller should still destroy digestContext with a SecCmsDigestContextDestroy() call. + + */ +extern OSStatus SecCmsSignedDataSetDigestContext(SecCmsSignedDataRef sigd, + SecCmsDigestContextRef digestContext) + API_AVAILABLE(ios(2.0), tvos(2.0), watchos(1.0)) API_UNAVAILABLE(macos, iosmac); +#endif + +#if TARGET_OS_OSX +extern OSStatus +SecCmsSignedDataAddSignerInfo(SecCmsSignedDataRef sigd, + SecCmsSignerInfoRef signerinfo); + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +extern OSStatus +SecCmsSignedDataSetDigests(SecCmsSignedDataRef sigd, + SECAlgorithmID **digestalgs, + CSSM_DATA_PTR *digests) + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); +#pragma clang diagnostic pop +#endif + +__END_DECLS + +#endif /* _SECURITY_SECCMSSIGNEDDATA_H_ */ diff --git a/CMS/SecCmsSignerInfo.h b/CMS/SecCmsSignerInfo.h new file mode 100644 index 000000000..f3f80d6ed --- /dev/null +++ b/CMS/SecCmsSignerInfo.h @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2004-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@ + */ + +/*! + @header SecCmsSignerInfo.h + + @availability 10.4 and later + @abstract Interfaces of the CMS implementation. + @discussion The functions here implement functions for encoding + and decoding Cryptographic Message Syntax (CMS) objects + as described in rfc3369. + */ + +#ifndef _SECURITY_SECCMSSIGNERINFO_H_ +#define _SECURITY_SECCMSSIGNERINFO_H_ 1 + +#include + +#include +#include + +__BEGIN_DECLS + +#if TARGET_OS_OSX +extern SecCmsSignerInfoRef +SecCmsSignerInfoCreate(SecCmsMessageRef cmsg, SecIdentityRef identity, SECOidTag digestalgtag) + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(iosmac); + +#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); +#endif // !TARGET_OS_OSX + +#if TARGET_OS_OSX +#pragma clang diagnostic push +#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); +#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); +#endif // !TARGET_OS_OSX + +#if TARGET_OS_OSX +/*! + @function + @abstract Destroy a SignerInfo data structure. + */ +extern void +SecCmsSignerInfoDestroy(SecCmsSignerInfoRef si) + API_AVAILABLE(macos(10.4)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); +#endif + +/*! + @function + */ +extern SecCmsVerificationStatus +SecCmsSignerInfoGetVerificationStatus(SecCmsSignerInfoRef signerinfo); + +/*! + @function + */ +extern SECOidData * +SecCmsSignerInfoGetDigestAlg(SecCmsSignerInfoRef signerinfo); + +/*! + @function + */ +extern SECOidTag +SecCmsSignerInfoGetDigestAlgTag(SecCmsSignerInfoRef signerinfo); + +/*! + @function + */ +extern CFArrayRef +SecCmsSignerInfoGetCertList(SecCmsSignerInfoRef signerinfo); + +/*! + @function + @abstract Return the signing time, in UTCTime format, of a CMS signerInfo. + @param sinfo SignerInfo data for this signer. + @discussion Returns a pointer to XXXX (what?) + @result A return value of NULL is an error. + */ +extern OSStatus +SecCmsSignerInfoGetSigningTime(SecCmsSignerInfoRef sinfo, CFAbsoluteTime *stime); + +/*! + @function + @abstract Return the data in the signed Codesigning Hash Agility attribute. + @param sinfo SignerInfo data for this signer, pointer to a CFDataRef for attribute value + @discussion Returns a CFDataRef containing the value of the attribute + @result A return value of SECFailure is an error. + */ +extern OSStatus +SecCmsSignerInfoGetAppleCodesigningHashAgility(SecCmsSignerInfoRef sinfo, CFDataRef *sdata); + +/*! + @function + @abstract Return the data in the signed Codesigning Hash Agility V2 attribute. + @param sinfo SignerInfo data for this signer, pointer to a CFDictionaryRef for attribute values + @discussion Returns a CFDictionaryRef containing the values of the attribute. V2 encodes the + hash agility values using DER. + @result A return value of SECFailure is an error. + */ +extern OSStatus +SecCmsSignerInfoGetAppleCodesigningHashAgilityV2(SecCmsSignerInfoRef sinfo, CFDictionaryRef *sdict); + +/*! + @function SecCmsSignerInfoGetAppleExpirationTime + @abstract Return the expriation time, in CFAbsoluteTime, of a CMS signerInfo. + @param sinfo SignerInfo data for this signer. + @discussion Returns a CFAbsoluteTime + @result A return value of SECFailure is an error. + */ +extern OSStatus +SecCmsSignerInfoGetAppleExpirationTime(SecCmsSignerInfoRef sinfo, CFAbsoluteTime *etime); + +/*! + @function + @abstract Return the signing cert of a CMS signerInfo. + @discussion The certs in the enclosing SignedData must have been imported already. + */ +extern SecCertificateRef +SecCmsSignerInfoGetSigningCertificate(SecCmsSignerInfoRef signerinfo, SecKeychainRef keychainOrArray); + +/*! + @function + @abstract Return the common name of the signer. + @param sinfo SignerInfo data for this signer. + @discussion Returns a CFStringRef containing the common name of the signer. + @result A return value of NULL is an error. + */ +extern CF_RETURNS_RETAINED CFStringRef +SecCmsSignerInfoGetSignerCommonName(SecCmsSignerInfoRef sinfo); + +/*! + @function + @abstract Return the email address of the signer + @param sinfo SignerInfo data for this signer. + @discussion Returns a CFStringRef containing the name of the signer. + @result A return value of NULL is an error. + */ +extern CF_RETURNS_RETAINED CFStringRef +SecCmsSignerInfoGetSignerEmailAddress(SecCmsSignerInfoRef sinfo); + +/*! + @function + @abstract Add the signing time to the authenticated (i.e. signed) attributes of "signerinfo". + @discussion This is expected to be included in outgoing signed + messages for email (S/MIME) but is likely useful in other situations. + + This should only be added once; a second call will do nothing. + + XXX This will probably just shove the current time into "signerinfo" + but it will not actually get signed until the entire item is + processed for encoding. Is this (expected to be small) delay okay? + */ +extern OSStatus +SecCmsSignerInfoAddSigningTime(SecCmsSignerInfoRef signerinfo, CFAbsoluteTime t); + +/*! + @function + @abstract Add a SMIMECapabilities attribute to the authenticated (i.e. signed) attributes of "signerinfo". + @discussion This is expected to be included in outgoing signed messages for email (S/MIME). + */ +extern OSStatus +SecCmsSignerInfoAddSMIMECaps(SecCmsSignerInfoRef signerinfo); + +/*! + @function + @abstract Add a SMIMEEncryptionKeyPreferences attribute to the authenticated (i.e. signed) attributes of "signerinfo". + @discussion This is expected to be included in outgoing signed messages for email (S/MIME). + */ +OSStatus +SecCmsSignerInfoAddSMIMEEncKeyPrefs(SecCmsSignerInfoRef signerinfo, SecCertificateRef cert, SecKeychainRef keychainOrArray); + +/*! + @function + @abstract Add a SMIMEEncryptionKeyPreferences attribute to the authenticated (i.e. signed) attributes of "signerinfo", using the OID prefered by Microsoft. + @discussion This is expected to be included in outgoing signed messages for email (S/MIME), if compatibility with Microsoft mail clients is wanted. + */ +OSStatus +SecCmsSignerInfoAddMSSMIMEEncKeyPrefs(SecCmsSignerInfoRef signerinfo, SecCertificateRef cert, SecKeychainRef keychainOrArray); + +/*! + @function + @abstract Countersign a signerinfo. + */ +extern OSStatus +SecCmsSignerInfoAddCounterSignature(SecCmsSignerInfoRef signerinfo, + SECOidTag digestalg, SecIdentityRef identity); + +/*! + @function + @abstract Add the Apple Codesigning Hash Agility attribute to the authenticated (i.e. signed) attributes of "signerinfo". + @discussion This is expected to be included in outgoing Apple code signatures. +*/ +OSStatus +SecCmsSignerInfoAddAppleCodesigningHashAgility(SecCmsSignerInfoRef signerinfo, CFDataRef attrValue); + +/*! + @function + @abstract Add the Apple Codesigning Hash Agility V2 attribute to the authenticated (i.e. signed) attributes of "signerinfo". + @discussion This is expected to be included in outgoing Apple code signatures. V2 encodes the hash agility values using DER. + The dictionary should have CFNumberRef keys, corresponding to SECOidTags for digest algorithms, and CFDataRef values, + corresponding to the digest value for that digest algorithm. + */ +OSStatus +SecCmsSignerInfoAddAppleCodesigningHashAgilityV2(SecCmsSignerInfoRef signerinfo, CFDictionaryRef attrValues); + +/*! + @function SecCmsSignerInfoAddAppleExpirationTime + @abstract Add the expiration time to the authenticated (i.e. signed) attributes of "signerinfo". + @discussion This is expected to be included in outgoing signed messages for Asset Receipts but is likely + useful in other situations. This should only be added once; a second call will do nothing. + @result A result of SECFailure indicates an error adding the attribute. + */ +extern OSStatus +SecCmsSignerInfoAddAppleExpirationTime(SecCmsSignerInfoRef signerinfo, CFAbsoluteTime t); + +/*! + @function + @abstract The following needs to be done in the S/MIME layer code after signature of a signerinfo has been verified. + @param signerinfo The SecCmsSignerInfo object for which we verified the signature. + @result The preferred encryption certificate of the user who signed this message will be added to the users default Keychain and it will be marked as the preferred certificate to use when sending that person messages from now on. + */ +extern OSStatus +SecCmsSignerInfoSaveSMIMEProfile(SecCmsSignerInfoRef signerinfo); + +/*! + @function + @abstract Set cert chain inclusion mode for this signer. + */ +extern OSStatus +SecCmsSignerInfoIncludeCerts(SecCmsSignerInfoRef signerinfo, SecCmsCertChainMode cm, SECCertUsage usage); + +/*! @functiongroup CMS misc utility functions */ +/*! + @function + Convert a SecCmsVerificationStatus to a human readable string. + */ +extern const char * +SecCmsUtilVerificationStatusToString(SecCmsVerificationStatus vs); + +/* + * Preference domain and key for the Microsoft ECDSA compatibility flag. + * Default if not present is TRUE, meaning we generate ECDSA-signed messages + * which are compatible with Microsoft Entourage. FALSE means we adhere to + * the spec (RFC 3278 section 2.1.1). + */ +#define kMSCompatibilityDomain "com.apple.security.smime" +#define kMSCompatibilityMode CFSTR("MSCompatibilityMode") + +/*! + @function SecCmsSignerInfoCopyCertFromEncryptionKeyPreference + @abstract Copy the certificate specified in the encryption key preference. + @param signerinfo The SecCmsSignerInfo object for which we verified the signature. + @result The preferred encryption certificate of the user who signed this message, if found. + @discussion This function should be called after the signer info has been verified. + */ +SecCertificateRef SecCmsSignerInfoCopyCertFromEncryptionKeyPreference(SecCmsSignerInfoRef signerinfo); + +#if TARGET_OS_OSX +/* MARK: Timestamping support */ + +extern OSStatus +SecCmsSignerInfoVerifyUnAuthAttrs(SecCmsSignerInfoRef signerinfo) + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + +extern OSStatus +SecCmsSignerInfoVerifyUnAuthAttrsWithPolicy(SecCmsSignerInfoRef signerinfo,CFTypeRef timeStampPolicy) + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + +#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); +#pragma clang diagnostic pop + +extern CFArrayRef +SecCmsSignerInfoGetTimestampCertList(SecCmsSignerInfoRef signerinfo) + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + +extern SecCertificateRef +SecCmsSignerInfoGetTimestampSigningCert(SecCmsSignerInfoRef signerinfo) + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + +/*! + @function + @abstract Return the timestamp time, in UTCTime format, of a CMS signerInfo. + @param sinfo SignerInfo data for this signer. + @discussion Returns a pointer to XXXX (what?) + @result A return value of NULL is an error. + */ +OSStatus +SecCmsSignerInfoGetTimestampTime(SecCmsSignerInfoRef sinfo, CFAbsoluteTime *stime) + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + +/*! + @function + @abstract Return the timestamp time, in UTCTime format, of a CMS signerInfo. + @param sinfo SignerInfo data for this signer, timeStampPolicy the policy to verify the timestamp signer + @discussion Returns a pointer to XXXX (what?) + @result A return value of NULL is an error. + */ +OSStatus +SecCmsSignerInfoGetTimestampTimeWithPolicy(SecCmsSignerInfoRef sinfo, CFTypeRef timeStampPolicy, CFAbsoluteTime *stime) + API_AVAILABLE(macos(10.8)) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + +/*! + @function + @abstract Create a timestamp unsigned attribute with a TimeStampToken. + */ +#pragma clang diagnostic push +#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); +#pragma clang diagnostic pop +#endif // TARGET_OS_OSX + +__END_DECLS + +#endif /* _SECURITY_SECCMSSIGNERINFO_H_ */ diff --git a/CMS/SecSMIME.h b/CMS/SecSMIME.h new file mode 100644 index 000000000..947f145e7 --- /dev/null +++ b/CMS/SecSMIME.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2004-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@ + */ + +/*! + @header SecSMIME.h + + @availability 10.4 and later + @abstract S/MIME Specific routines. + @discussion Header file for routines specific to S/MIME. Keep + things that are pure pkcs7 out of here; this is for + S/MIME policy, S/MIME interoperability, etc. +*/ + +#ifndef _SECURITY_SECSMIME_H_ +#define _SECURITY_SECSMIME_H_ 1 + +#include + +__BEGIN_DECLS + +/*! + @function + @abstract Find bulk algorithm suitable for all recipients. + */ +extern OSStatus +SecSMIMEFindBulkAlgForRecipients(SecCertificateRef *rcerts, SECOidTag *bulkalgtag, int *keysize); + +__END_DECLS + +#endif /* _SECURITY_SECSMIME_H_ */ diff --git a/CSSMOID.exp-in b/CSSMOID.exp-in index 9704e53c5..531b3558e 100644 --- a/CSSMOID.exp-in +++ b/CSSMOID.exp-in @@ -8,6 +8,125 @@ _CSSMOID_ECDSA_WithSHA1 _CSSMOID_ECDSA_WithSHA256 _CSSMOID_ECDSA_WithSHA384 _CSSMOID_PKCS5_HMAC_SHA1 + +_CSSMOID_ANSI_DH_EPHEM +_CSSMOID_ANSI_DH_EPHEM_SHA1 +_CSSMOID_ANSI_DH_HYBRID1 +_CSSMOID_ANSI_DH_HYBRID1_SHA1 +_CSSMOID_ANSI_DH_HYBRID2 +_CSSMOID_ANSI_DH_HYBRID2_SHA1 +_CSSMOID_ANSI_DH_HYBRID_ONEFLOW +_CSSMOID_ANSI_DH_ONE_FLOW +_CSSMOID_ANSI_DH_ONE_FLOW_SHA1 +_CSSMOID_ANSI_DH_PUB_NUMBER +_CSSMOID_ANSI_DH_STATIC +_CSSMOID_ANSI_DH_STATIC_SHA1 +_CSSMOID_ANSI_MQV1 +_CSSMOID_ANSI_MQV1_SHA1 +_CSSMOID_ANSI_MQV2 +_CSSMOID_ANSI_MQV2_SHA1 +_CSSMOID_APPLE_ASC +_CSSMOID_APPLE_ECDSA +_CSSMOID_APPLE_FEE +_CSSMOID_APPLE_FEED +_CSSMOID_APPLE_FEEDEXP +_CSSMOID_APPLE_FEE_MD5 +_CSSMOID_APPLE_FEE_SHA1 +_CSSMOID_APPLE_ISIGN +_CSSMOID_APPLE_TP_APPLEID_SHARING +_CSSMOID_APPLE_TP_CODE_SIGN +_CSSMOID_APPLE_TP_CODE_SIGNING +_CSSMOID_APPLE_TP_CSR_GEN +_CSSMOID_APPLE_TP_EAP +_CSSMOID_APPLE_TP_ESCROW_SERVICE +_CSSMOID_APPLE_TP_ICHAT +_CSSMOID_APPLE_TP_IP_SEC +_CSSMOID_APPLE_TP_LOCAL_CERT_GEN +_CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT +_CSSMOID_APPLE_TP_MOBILE_STORE +_CSSMOID_APPLE_TP_PACKAGE_SIGNING +_CSSMOID_APPLE_TP_PASSBOOK_SIGNING +_CSSMOID_APPLE_TP_PCS_ESCROW_SERVICE +_CSSMOID_APPLE_TP_PKINIT_CLIENT +_CSSMOID_APPLE_TP_PKINIT_SERVER +_CSSMOID_APPLE_TP_PROFILE_SIGNING +_CSSMOID_APPLE_TP_PROVISIONING_PROFILE_SIGNING +_CSSMOID_APPLE_TP_QA_PROFILE_SIGNING +_CSSMOID_APPLE_TP_RESOURCE_SIGN +_CSSMOID_APPLE_TP_REVOCATION +_CSSMOID_APPLE_TP_REVOCATION_CRL +_CSSMOID_APPLE_TP_REVOCATION_OCSP +_CSSMOID_APPLE_TP_SMIME +_CSSMOID_APPLE_TP_SSL +_CSSMOID_APPLE_TP_SW_UPDATE_SIGNING +_CSSMOID_APPLE_TP_TEST_MOBILE_STORE +_CSSMOID_APPLE_TP_TIMESTAMPING +_CSSMOID_APPLE_X509_BASIC +_CSSMOID_DES_CBC +_CSSMOID_DH +_CSSMOID_DOTMAC_CERT +_CSSMOID_DOTMAC_CERT_REQ +_CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_FETCH +_CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_LIST +_CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_REMOVE +_CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_STORE +_CSSMOID_DOTMAC_CERT_REQ_EMAIL_ENCRYPT +_CSSMOID_DOTMAC_CERT_REQ_EMAIL_SIGN +_CSSMOID_DOTMAC_CERT_REQ_IDENTITY +_CSSMOID_DOTMAC_CERT_REQ_SHARED_SERVICES +_CSSMOID_DOTMAC_CERT_REQ_VALUE_ASYNC +_CSSMOID_DOTMAC_CERT_REQ_VALUE_HOSTNAME +_CSSMOID_DOTMAC_CERT_REQ_VALUE_IS_PENDING +_CSSMOID_DOTMAC_CERT_REQ_VALUE_PASSWORD +_CSSMOID_DOTMAC_CERT_REQ_VALUE_RENEW +_CSSMOID_DOTMAC_CERT_REQ_VALUE_USERNAME +_CSSMOID_DSA +_CSSMOID_DSA_CMS +_CSSMOID_DSA_JDK +_CSSMOID_ECDSA_WithSHA224 +_CSSMOID_ECDSA_WithSHA512 +_CSSMOID_ECDSA_WithSpecified +_CSSMOID_MD2 +_CSSMOID_MD2WithRSA +_CSSMOID_MD4 +_CSSMOID_MD4WithRSA +_CSSMOID_MD5 +_CSSMOID_OAEP_ID_PSPECIFIED +_CSSMOID_OAEP_MGF1 +_CSSMOID_PKCS12_pbeWithSHAAnd128BitRC2CBC +_CSSMOID_PKCS12_pbeWithSHAAnd128BitRC4 +_CSSMOID_PKCS12_pbeWithSHAAnd2Key3DESCBC +_CSSMOID_PKCS12_pbeWithSHAAnd3Key3DESCBC +_CSSMOID_PKCS12_pbeWithSHAAnd40BitRC4 +_CSSMOID_PKCS12_pbewithSHAAnd40BitRC2CBC +_CSSMOID_PKCS3 +_CSSMOID_PKCS5_DES_EDE3_CBC +_CSSMOID_PKCS5_DIGEST_ALG +_CSSMOID_PKCS5_ENCRYPT_ALG +_CSSMOID_PKCS5_PBES2 +_CSSMOID_PKCS5_PBKDF2 +_CSSMOID_PKCS5_PBMAC1 +_CSSMOID_PKCS5_RC2_CBC +_CSSMOID_PKCS5_RC5_CBC +_CSSMOID_PKCS5_pbeWithMD2AndDES +_CSSMOID_PKCS5_pbeWithMD2AndRC2 +_CSSMOID_PKCS5_pbeWithMD5AndDES +_CSSMOID_PKCS5_pbeWithMD5AndRC2 +_CSSMOID_PKCS5_pbeWithSHA1AndDES +_CSSMOID_PKCS5_pbeWithSHA1AndRC2 +_CSSMOID_RSA +_CSSMOID_RSAWithOAEP +_CSSMOID_SHA1WithDSA +_CSSMOID_SHA1WithDSA_CMS +_CSSMOID_SHA1WithDSA_JDK +_CSSMOID_SHA1WithRSA_OIW +_CSSMOID_SHA224 +_CSSMOID_SHA224WithRSA +_CSSMOID_SHA256 +_CSSMOID_SHA384 +_CSSMOID_SHA512 +_CSSMOID_SHA512WithRSA +_CSSMOID_ecPublicKey #endif #if TARGET_OS_OSX @@ -109,6 +228,7 @@ _CSSMOID_EmailProtection _CSSMOID_EnhancedSearchGuide _CSSMOID_ExtendedCertificateAttributes _CSSMOID_ExtendedKeyUsage +_CSSMOID_InhibitAnyPolicy _CSSMOID_AuthorityInfoAccess _CSSMOID_BiometricInfo _CSSMOID_QC_Statements @@ -243,6 +363,7 @@ _CSSMOID_SHA256WithRSA _CSSMOID_SHA384WithRSA _CSSMOID_SHA512WithRSA _CSSMOID_SHA1WithRSA_OIW +_CSSMOID_DES_CBC _CSSMOID_RSAWithOAEP _CSSMOID_OAEP_MGF1 _CSSMOID_OAEP_ID_PSPECIFIED @@ -273,6 +394,7 @@ _CSSMOID_UnstructuredName _CSSMOID_UseExemptions _CSSMOID_UserCertificate _CSSMOID_UserID +_CSSMOID_DomainComponent _CSSMOID_UserPassword _CSSMOID_X509V1CRLIssuerNameCStruct _CSSMOID_X509V1CRLIssuerNameLDAP @@ -398,7 +520,12 @@ _CSSMOID_APPLE_EXTENSION_AAI_INTERMEDIATE _CSSMOID_APPLE_EXTENSION_APPLEID_INTERMEDIATE _CSSMOID_APPLE_EXTENSION_APPLEID_SHARING _CSSMOID_APPLE_EXTENSION_SYSINT2_INTERMEDIATE +_CSSMOID_APPLE_EXTENSION_DEVELOPER_AUTHENTICATION +_CSSMOID_APPLE_EXTENSION_PROVISIONING_PROFILE_SIGNING +_CSSMOID_APPLE_EXTENSION_SERVER_AUTHENTICATION _CSSMOID_APPLE_EXTENSION_ESCROW_SERVICE +_CSSMOID_APPLE_TP_PCS_ESCROW_SERVICE +_CSSMOID_APPLE_TP_PROVISIONING_PROFILE_SIGNING _CSSMOID_PKIX_OCSP _CSSMOID_PKIX_OCSP_ARCHIVE_CUTOFF _CSSMOID_PKIX_OCSP_BASIC diff --git a/CircleJoinRequested/Applicant.h b/CircleJoinRequested/Applicant.h index f7c76bffd..bbb48daa6 100644 --- a/CircleJoinRequested/Applicant.h +++ b/CircleJoinRequested/Applicant.h @@ -7,7 +7,7 @@ // #import -#include "SecureObjectSync/SOSPeerInfo.h" +#include "keychain/SecureObjectSync/SOSPeerInfo.h" typedef enum { ApplicantWaiting, diff --git a/CircleJoinRequested/Applicant.m b/CircleJoinRequested/Applicant.m index 84ada23b2..5cce51774 100644 --- a/CircleJoinRequested/Applicant.m +++ b/CircleJoinRequested/Applicant.m @@ -36,8 +36,8 @@ -(NSString *)name -(void)dealloc { - if (self.rawPeerInfo) { - CFRelease(self.rawPeerInfo); + if (self->_rawPeerInfo) { + CFRelease(self->_rawPeerInfo); } } diff --git a/CircleJoinRequested/CircleJoinRequested.m b/CircleJoinRequested/CircleJoinRequested.m index d6942e570..2009f377d 100644 --- a/CircleJoinRequested/CircleJoinRequested.m +++ b/CircleJoinRequested/CircleJoinRequested.m @@ -36,14 +36,15 @@ #import #import #import +#import #import #import #import #include -#include "SecureObjectSync/SOSCloudCircle.h" -#include "SecureObjectSync/SOSCloudCircleInternal.h" -#include "SecureObjectSync/SOSPeerInfo.h" -#include "SecureObjectSync/SOSInternal.h" +#include "keychain/SecureObjectSync/SOSCloudCircle.h" +#include "keychain/SecureObjectSync/SOSCloudCircleInternal.h" +#include "keychain/SecureObjectSync/SOSPeerInfo.h" +#include "keychain/SecureObjectSync/SOSInternal.h" #include #include #import "Applicant.h" @@ -60,13 +61,14 @@ #include "utilities/debugging.h" #include "utilities/SecAKSWrappers.h" #include "utilities/SecCFWrappers.h" +#include #import "CoreCDP/CDPFollowUpController.h" #import "CoreCDP/CDPFollowUpContext.h" #import // As long as we are logging the failure use exit code of zero to make launchd happy -#define EXIT_LOGGED_FAILURE(code) xpc_transaction_end(); exit(0) +#define EXIT_LOGGED_FAILURE(code) exit(0) const char *kLaunchLaterXPCName = "com.apple.security.CircleJoinRequestedTick"; CFRunLoopSourceRef currentAlertSource = NULL; @@ -81,13 +83,23 @@ bool _unlockedSinceBoot = false; bool _hasPostedFollowupAndStillInError = false; bool _isAccountICDP = false; - +bool _executeProcessEventsOnce = false; NSString *castleKeychainUrl = @"prefs:root=APPLE_ACCOUNT&path=ICLOUD_SERVICE/com.apple.Dataclass.KeychainSync/ADVANCED"; NSString *rejoinICDPUrl = @"prefs:root=APPLE_ACCOUNT&aaaction=CDP&command=rejoin"; BOOL processRequests(CFErrorRef *error); +static BOOL isErrorFromXPC(CFErrorRef error) +{ + // Error due to XPC failure does not provide information about the circle. + if (error && (CFEqual(sSecXPCErrorDomain, CFErrorGetDomain(error)))) { + secnotice("cjr", "XPC error while checking circle status: \"%@\", not processing events", error); + return YES; + } + return NO; +} + static void PSKeychainSyncIsUsingICDP(void) { ACAccountStore *accountStore = [[ACAccountStore alloc] init]; @@ -115,14 +127,19 @@ static void keybagDidUnlock() secnotice("cjr", "keybagDidUnlock"); CFErrorRef error = NULL; - + if(processApplicantsAfterUnlock){ processRequests(&error); processApplicantsAfterUnlock = false; } SOSCCStatus circleStatus = SOSCCThisDeviceIsInCircle(&error); - if(_isAccountICDP && (circleStatus == kSOSCCError || circleStatus == kSOSCCCircleAbsent || circleStatus == kSOSCCNotInCircle) && _hasPostedFollowupAndStillInError == false){ + BOOL xpcError = isErrorFromXPC(error); + if(xpcError && circleStatus == kSOSCCError) { + secnotice("cjr", "returning early due to error returned from securityd: %@", error); + return; + } + else if (_isAccountICDP && (circleStatus == kSOSCCError || circleStatus == kSOSCCCircleAbsent || circleStatus == kSOSCCNotInCircle) && _hasPostedFollowupAndStillInError == false) { NSError *localError = nil; CDPFollowUpContext *context = [CDPFollowUpContext contextForStateRepair]; CDPFollowUpController *cdpd = [[CDPFollowUpController alloc] init]; @@ -741,20 +758,30 @@ static void postKickedOutAlert(enum DepartureReason reason) debugState = @"pKOA Z"; } - static bool processEvents() { debugState = @"processEvents A"; - CFErrorRef error = NULL; - CFErrorRef departError = NULL; - SOSCCStatus circleStatus = SOSCCThisDeviceIsInCircle(&error); - NSDate *nowish = [NSDate date]; - PersistentState *state = [PersistentState loadFromStorage]; - enum DepartureReason departureReason = SOSCCGetLastDepartureReason(&departError); - secnotice("cjr", "CircleStatus %d -> %d{%d} (s=%p)", state.lastCircleStatus, circleStatus, departureReason, state); + CFErrorRef error = NULL; + CFErrorRef departError = NULL; + SOSCCStatus circleStatus = SOSCCThisDeviceIsInCircleNonCached(&error); + enum DepartureReason departureReason = SOSCCGetLastDepartureReason(&departError); - // Pending application reminder + BOOL abortFromError = isErrorFromXPC(error); + if(abortFromError && circleStatus == kSOSCCError) { + secnotice("cjr", "returning from processEvents due to error returned from securityd: %@", error); + return true; + } + if (departureReason == kSOSDepartureReasonError && departError && (CFEqual(sSecXPCErrorDomain, CFErrorGetDomain(departError)))) { + secnotice("cjr", "XPC error while checking last departure reason: \"%@\", not processing events", departError); + return true; + } + + NSDate *nowish = [NSDate date]; + PersistentState *state = [PersistentState loadFromStorage]; + secnotice("cjr", "CircleStatus %d -> %d{%d} (s=%p)", state.lastCircleStatus, circleStatus, departureReason, state); + + // Pending application reminder NSTimeInterval timeUntilApplicationAlert = [state.pendingApplicationReminder timeIntervalSinceDate:nowish]; secnotice("cjr", "Time until pendingApplicationReminder (%@) %f", [state.pendingApplicationReminder debugDescription], timeUntilApplicationAlert); if (circleStatus == kSOSCCRequestPending) { @@ -767,13 +794,33 @@ static bool processEvents() } PSKeychainSyncIsUsingICDP(); - + + // Refresh because sometimes we're fixed elsewhere before we get here. + CFReleaseNull(error); + circleStatus = SOSCCThisDeviceIsInCircleNonCached(&error); + abortFromError = isErrorFromXPC(error); + if(abortFromError && circleStatus == kSOSCCError) { + secnotice("cjr", "returning from processEvents due to error returned from securityd: %@", error); + return true; + } + if(_isAccountICDP){ if((circleStatus == kSOSCCError || circleStatus == kSOSCCCircleAbsent || circleStatus == kSOSCCNotInCircle) && _hasPostedFollowupAndStillInError == false) { - secnotice("cjr", "error from SOSCCThisDeviceIsInCircle: %@", error); - secnotice("cjr", "iCDP: We need to get back into the circle"); - doOnceInMain(^{ - if(_isAccountICDP){ + if(circleStatus == kSOSCCError) { + secnotice("cjr", "error from SOSCCThisDeviceIsInCircle: %@", error); + } + + /* + You would think we could count on not being iCDP if the account was signed out. Evidently that's wrong. + So we'll go based on the artifact that when the account object is reset (like by signing out) the + departureReason will be set to kSOSDepartureReasonError. So we won't push to get back into a circle if that's + the current reason. I've checked code for other ways we could be out. If we boot and can't load the account + we'll end up with kSOSDepartureReasonError. Then too if we end up in kSOSDepartureReasonError and reboot we end up + in the same place. Leave it to cdpd to decide whether the user needs to sign in to an account. + */ + if(departureReason != kSOSDepartureReasonError) { + secnotice("cjr", "iCDP: We need to get back into the circle"); + doOnceInMain(^{ NSError *localError = nil; CDPFollowUpController *cdpd = [[CDPFollowUpController alloc] init]; CDPFollowUpContext *context = [CDPFollowUpContext contextForStateRepair]; @@ -785,27 +832,25 @@ static bool processEvents() secnotice("cjr", "CoreCDP handling follow up"); _hasPostedFollowupAndStillInError = true; } - } - else{ - postKickedOutAlert(kSOSPasswordChanged); - state.lastCircleStatus = kSOSCCError; - [state writeToStorage]; - } - }); + }); + } else { + secnotice("cjr", "iCDP: We appear to not be associated with an iCloud account"); + } state.lastCircleStatus = circleStatus; + _executeProcessEventsOnce = true; return false; } else if(circleStatus == kSOSCCInCircle){ secnotice("cjr", "follow up should be resolved"); + _executeProcessEventsOnce = true; _hasPostedFollowupAndStillInError = false; } else{ secnotice("cjr", "followup not resolved"); + _executeProcessEventsOnce = true; return false; } - } - else if(circleStatus == kSOSCCError && state.lastCircleStatus != kSOSCCError && (departureReason == kSOSNeverLeftCircle) - && !_isAccountICDP) { + } else if(circleStatus == kSOSCCError && state.lastCircleStatus != kSOSCCError && (departureReason == kSOSNeverLeftCircle)) { secnotice("cjr", "SA: error from SOSCCThisDeviceIsInCircle: %@", error); CFIndex errorCode = CFErrorGetCode(error); if(errorCode == kSOSErrorPublicKeyAbsent){ @@ -891,16 +936,22 @@ static bool processEvents() notify_register_dispatch(kSOSCCCircleChangedNotification, ¬ifyToken, dispatch_get_main_queue(), ^(int token) { if (postedAlert != currentAlert) { secnotice("cjr", "-- CC after original alert gone (currentAlertIsForApplicants %d, pA %p, cA %p -- %@)", - currentAlertIsForApplicants, postedAlert, currentAlert, currentAlert); - notify_cancel(token); - } else { + currentAlertIsForApplicants, postedAlert, currentAlert, currentAlert); + notify_cancel(token); + } else { CFErrorRef localError = NULL; - SOSCCStatus newCircleStatus = SOSCCThisDeviceIsInCircle(&localError); - if (newCircleStatus != kSOSCCRequestPending) { - if (newCircleStatus == kSOSCCError) - secnotice("cjr", "No longer pending (nCS=%d, alert=%@) error: %@", newCircleStatus, currentAlert, localError); - else - secnotice("cjr", "No longer pending (nCS=%d, alert=%@)", newCircleStatus, currentAlert); + SOSCCStatus newCircleStatus = SOSCCThisDeviceIsInCircle(&localError); + BOOL xpcError = isErrorFromXPC(localError); + if(xpcError && newCircleStatus == kSOSCCError) { + secnotice("cjr", "returning from processEvents due to error returned from securityd: %@", localError); + return; + } + + if (newCircleStatus != kSOSCCRequestPending) { + if (newCircleStatus == kSOSCCError) + secnotice("cjr", "No longer pending (nCS=%d, alert=%@) error: %@", newCircleStatus, currentAlert, localError); + else + secnotice("cjr", "No longer pending (nCS=%d, alert=%@)", newCircleStatus, currentAlert); cancelCurrentAlert(true); } else { secnotice("cjr", "Still pending..."); @@ -981,10 +1032,16 @@ static bool processEvents() if (newIds.count == 0) { secnotice("cjr", "All applicants were handled elsewhere"); cancelCurrentAlert(true); - } - SOSCCStatus currentCircleStatus = SOSCCThisDeviceIsInCircle(&circleStatusError); - if (kSOSCCInCircle != currentCircleStatus) { - secnotice("cjr", "Left circle (%d), not handling remaining %lu applicants", currentCircleStatus, (unsigned long)newIds.count); + } + CFErrorRef circleError = NULL; + SOSCCStatus currentCircleStatus = SOSCCThisDeviceIsInCircle(&circleError); + BOOL xpcError = isErrorFromXPC(circleError); + if(xpcError && currentCircleStatus == kSOSCCError) { + secnotice("cjr", "returning early due to error returned from securityd: %@", circleError); + return; + } + if (kSOSCCInCircle != currentCircleStatus) { + secnotice("cjr", "Left circle (%d), not handling remaining %lu applicants", currentCircleStatus, (unsigned long)newIds.count); cancelCurrentAlert(true); } if (needsUpdate) { @@ -1019,9 +1076,8 @@ static bool processEvents() int main (int argc, const char * argv[]) { - - xpc_transaction_begin(); - + os_transaction_t txion = os_transaction_create("com.apple.security.circle-join-requested"); + @autoreleasepool { // NOTE: DISPATCH_QUEUE_PRIORITY_LOW will not actually manage to drain events in a lot of cases (like circleStatus != kSOSCCInCircle) @@ -1044,7 +1100,7 @@ int main (int argc, const char * argv[]) { }); int falseInARow = 0; - while (falseInARow < 2) { + while (falseInARow < 2 && !_executeProcessEventsOnce) { if (processEvents()) { secnotice("cjr", "Processed events!!!"); falseInARow = 0; @@ -1060,6 +1116,7 @@ int main (int argc, const char * argv[]) { } secnotice("cjr", "Done"); - xpc_transaction_end(); + (void) txion; // But we really do want this around, compiler... + txion = nil; return(0); } diff --git a/CircleJoinRequested/PersistentState.h b/CircleJoinRequested/PersistentState.h index 29e0ef75f..3e4734761 100644 --- a/CircleJoinRequested/PersistentState.h +++ b/CircleJoinRequested/PersistentState.h @@ -7,8 +7,8 @@ // #import -#include "SecureObjectSync/SOSCloudCircle.h" -#include "SecureObjectSync/SOSPeerInfo.h" +#include "keychain/SecureObjectSync/SOSCloudCircle.h" +#include "keychain/SecureObjectSync/SOSPeerInfo.h" @interface PersistentState : NSObject +(instancetype)loadFromStorage; diff --git a/IDSKeychainSyncingProxy/com.apple.private.alloy.keychainsync.plist b/IDSKeychainSyncingProxy/com.apple.private.alloy.keychainsync.plist deleted file mode 100644 index f08f2617b..000000000 Binary files a/IDSKeychainSyncingProxy/com.apple.private.alloy.keychainsync.plist and /dev/null differ diff --git a/KVSKeychainSyncingProxy/CKDKVSProxy.h b/KVSKeychainSyncingProxy/CKDKVSProxy.h index 23dc1994c..aa1d50a22 100644 --- a/KVSKeychainSyncingProxy/CKDKVSProxy.h +++ b/KVSKeychainSyncingProxy/CKDKVSProxy.h @@ -76,6 +76,9 @@ typedef void (^FreshnessResponseBlock)(bool success, NSError *err); @property (retain, nonatomic) NSMutableSet* shadowPendingSyncBackupPeerIDs; @property (atomic) bool ensurePeerRegistration; +@property (atomic) bool ensurePeerRegistrationEnqueuedButNotStarted; + +// Another version of ensurePeerRegistration due to legacy code structure @property (atomic) bool shadowEnsurePeerRegistration; @property (atomic) bool inCallout; @@ -86,10 +89,6 @@ typedef void (^FreshnessResponseBlock)(bool success, NSError *err); @property (atomic) dispatch_queue_t calloutQueue; @property (atomic) dispatch_queue_t ckdkvsproxy_queue; -@property (atomic) dispatch_source_t penaltyTimer; -@property (atomic) bool penaltyTimerScheduled; -@property (retain, atomic) NSMutableDictionary *monitor; -@property (retain, atomic) NSDictionary *queuedMessages; @property (copy, atomic) dispatch_block_t shadowFlushBlock; diff --git a/KVSKeychainSyncingProxy/CKDKVSProxy.m b/KVSKeychainSyncingProxy/CKDKVSProxy.m index 9b74ef606..d586951c8 100644 --- a/KVSKeychainSyncingProxy/CKDKVSProxy.m +++ b/KVSKeychainSyncingProxy/CKDKVSProxy.m @@ -37,7 +37,8 @@ #import "CKDSecuritydAccount.h" #import "NSURL+SOSPlistStore.h" -#include +#include "keychain/SecureObjectSync/SOSARCDefines.h" +#include "keychain/SecureObjectSync/SOSKVSKeys.h" #include #include @@ -49,9 +50,6 @@ #import "XPCNotificationDispatcher.h" -CFStringRef const CKDAggdIncreaseThrottlingKey = CFSTR("com.apple.cloudkeychainproxy.backoff.increase"); -CFStringRef const CKDAggdDecreaseThrottlingKey = CFSTR("com.apple.cloudkeychainproxy.backoff.decrease"); - @interface NSSet (CKDLogging) - (NSString*) logKeys; - (NSString*) logIDs; @@ -94,16 +92,13 @@ - (NSString*) logIDs { static NSString *kKeyEnsurePeerRegistration = @"EnsurePeerRegistration"; static NSString *kKeyDSID = @"DSID"; -static NSString *kMonitorState = @"MonitorState"; -static NSString *kKeyAccountUUID = @"MonitorState"; +static NSString *kKeyAccountUUID = @"KeyAccountUUID"; static NSString *kMonitorPenaltyBoxKey = @"Penalty"; static NSString *kMonitorMessageKey = @"Message"; static NSString *kMonitorConsecutiveWrites = @"ConsecutiveWrites"; static NSString *kMonitorLastWriteTimestamp = @"LastWriteTimestamp"; static NSString *kMonitorMessageQueue = @"MessageQueue"; -static NSString *kMonitorPenaltyTimer = @"PenaltyTimer"; -static NSString *kMonitorDidWriteDuringPenalty = @"DidWriteDuringPenalty"; static NSString *kMonitorTimeTable = @"TimeTable"; static NSString *kMonitorFirstMinute = @"AFirstMinute"; @@ -112,11 +107,6 @@ - (NSString*) logIDs { static NSString *kMonitorFourthMinute = @"DFourthMinute"; static NSString *kMonitorFifthMinute = @"EFifthMinute"; static NSString *kMonitorWroteInTimeSlice = @"TimeSlice"; -const CFStringRef kSOSKVSKeyParametersKey = CFSTR(">KeyParameters"); -const CFStringRef kSOSKVSInitialSyncKey = CFSTR("^InitialSync"); -const CFStringRef kSOSKVSAccountChangedKey = CFSTR("^AccountChanged"); -const CFStringRef kSOSKVSRequiredKey = CFSTR("^Required"); -const CFStringRef kSOSKVSOfficialDSIDKey = CFSTR("^OfficialDSID"); #define kSecServerKeychainChangedNotification "com.apple.security.keychainchanged" @@ -148,7 +138,7 @@ - (instancetype)initWithAccount:(NSObject*) account { secnotice("event", "%@ start", self); -#if !(TARGET_OS_EMBEDDED) +#if !TARGET_OS_IPHONE || TARGET_OS_SIMULATOR // rdar://problem/26247270 if (geteuid() == 0) { secerror("Cannot run CloudKeychainProxy as root"); @@ -174,18 +164,8 @@ - (instancetype)initWithAccount:(NSObject*) account _freshnessCompletions = [NSMutableArray array]; - _monitor = [NSMutableDictionary dictionary]; - [[XPCNotificationDispatcher dispatcher] addListener: self]; - int notificationToken; - notify_register_dispatch(kSecServerKeychainChangedNotification, ¬ificationToken, _ckdkvsproxy_queue, - ^ (int token __unused) - { - secinfo("backoff", "keychain changed, wiping backoff monitor state"); - self->_monitor = [NSMutableDictionary dictionary]; - }); - [self setPersistentData: [self.persistenceURL readPlist]]; _dsid = @""; @@ -268,7 +248,6 @@ - (NSDictionary*) persistentData kKeyPendingKeys:[_pendingKeys allObjects], kKeyPendingSyncPeerIDs:[_pendingSyncPeerIDs allObjects], kKeyPendingSyncBackupPeerIDs:[_pendingSyncBackupPeerIDs allObjects], - kMonitorState:_monitor, kKeyEnsurePeerRegistration:[NSNumber numberWithBool:_ensurePeerRegistration], kKeyDSID:_dsid, kKeyAccountUUID:_accountUUID @@ -278,6 +257,7 @@ - (NSDictionary*) persistentData - (void) setPersistentData: (NSDictionary*) interests { _alwaysKeys = [NSMutableSet setWithArray: interests[kKeyAlwaysKeys]]; + [_alwaysKeys addObject:(__bridge NSString*) kSOSKVSKeyParametersKey]; // Make sure KeyParms are always of interest _firstUnlockKeys = [NSMutableSet setWithArray: interests[kKeyFirstUnlockKeys]]; _unlockedKeys = [NSMutableSet setWithArray: interests[kKeyUnlockedKeys]]; @@ -286,20 +266,11 @@ - (void) setPersistentData: (NSDictionary*) interests _pendingSyncPeerIDs = [NSMutableSet setWithArray: interests[kKeyPendingSyncPeerIDs]]; _pendingSyncBackupPeerIDs = [NSMutableSet setWithArray: interests[kKeyPendingSyncBackupPeerIDs]]; - _monitor = interests[kMonitorState]; - if(_monitor == nil) - _monitor = [NSMutableDictionary dictionary]; - _ensurePeerRegistration = [interests[kKeyEnsurePeerRegistration] boolValue]; _dsid = interests[kKeyDSID]; _accountUUID = interests[kKeyAccountUUID]; - - // If we had a sync pending, we kick it off and migrate to sync with these peers - if ([interests[kKeySyncWithPeersPending] boolValue]) { - [self doSyncWithAllPeers]; } -} - (void)persistState { @@ -617,9 +588,8 @@ - (void) calloutWith: (void(^)(NSSet *pending, NSSet* pendingSyncIDs, NSSet* pen self->_ensurePeerRegistration = ((self->_ensurePeerRegistration && !handledEnsurePeerRegistration) || self->_shadowEnsurePeerRegistration); self->_shadowEnsurePeerRegistration = NO; - - if(self->_ensurePeerRegistration && ![self.lockMonitor locked]) - [self doEnsurePeerRegistration]; + + [self handlePendingEnsurePeerRegistrationRequests:true]; bool hadShadowPeerIDs = ![self->_shadowPendingSyncPeerIDs isEmpty] || ![self->_shadowPendingSyncBackupPeerIDs isEmpty]; @@ -666,8 +636,12 @@ - (void) calloutWith: (void(^)(NSSet *pending, NSSet* pendingSyncIDs, NSSet* pen // Handle shadow pended stuff // We only kick off another sync if we got new stuff during handling - if (hadShadowPeerIDs && ![self.lockMonitor locked]) - [self newPeersToSyncWith]; + if (hadShadowPeerIDs && ![self.lockMonitor locked]) { + secnotice("event", "%@ syncWithPeersPending: %d inCallout: %d isLocked: %d", self, [self hasPendingSyncIDs], self->_inCallout, [self.lockMonitor locked]); + if ([self hasPendingSyncIDs] && !self->_inCallout && ![self.lockMonitor locked]){ + [self doSyncWithPendingPeers]; + } + } /* We don't want to call processKeyChangedEvent if we failed to handle pending keys and the device didn't unlock nor receive @@ -713,11 +687,28 @@ - (void) sendKeysCallout: (NSSet *(^)(NSSet* pending, NSError** error)) handleKe }]; } +- (void)handlePendingEnsurePeerRegistrationRequests:(bool)onlyIfUnlocked +{ + // doEnsurePeerRegistration's callback will be run on _calloutQueue, so we should check the 'are we running yet' flags on that queue + dispatch_async(_calloutQueue, ^{ + if(self.ensurePeerRegistration && (!onlyIfUnlocked || ![self.lockMonitor locked])) { + if(self.ensurePeerRegistrationEnqueuedButNotStarted) { + secnotice("EnsurePeerRegistration", "%@ ensurePeerRegistration block already enqueued, not starting a new one", self); + return; + } + + [self doEnsurePeerRegistration]; + } + }); +} + - (void) doEnsurePeerRegistration { NSObject* accountDelegate = [self account]; + self.ensurePeerRegistrationEnqueuedButNotStarted = true; [self calloutWith:^(NSSet *pending, NSSet* pendingSyncIDs, NSSet* pendingBackupSyncIDs, bool ensurePeerRegistration, dispatch_queue_t queue, void(^done)(NSSet *handledKeys, NSSet *handledSyncs, bool handledEnsurePeerRegistration, NSError* error)) { NSError* error = nil; + self.ensurePeerRegistrationEnqueuedButNotStarted = false; bool handledEnsurePeerRegistration = [accountDelegate ensurePeerRegistration:&error]; secnotice("EnsurePeerRegistration", "%@ ensurePeerRegistration called, %@ (%@)", self, handledEnsurePeerRegistration ? @"success" : @"failure", error); if (!handledEnsurePeerRegistration) { @@ -766,17 +757,6 @@ - (void) doSyncWithAllPeers }]; } -- (void)newPeersToSyncWith -{ - secnotice("event", "%@ syncWithPeersPending: %d inCallout: %d isLocked: %d", self, [self hasPendingSyncIDs], _inCallout, [self.lockMonitor locked]); - if(_ensurePeerRegistration){ - [self doEnsurePeerRegistration]; - } - if ([self hasPendingSyncIDs] && !_inCallout && ![self.lockMonitor locked]){ - [self doSyncWithPendingPeers]; - } -} - - (bool)hasPendingNonShadowSyncIDs { return ![_pendingSyncPeerIDs isEmpty] || ![_pendingSyncBackupPeerIDs isEmpty]; } @@ -815,9 +795,8 @@ - (void)requestSyncWithPeerIDs: (NSArray*) peerIDs backupPeerIDs: (NS [self persistState]; - if(_ensurePeerRegistration){ - [self doEnsurePeerRegistration]; - } + [self handlePendingEnsurePeerRegistrationRequests:true]; + if ([self hasPendingSyncIDs] && !_inCallout && ![self.lockMonitor locked]){ [self doSyncWithPendingPeers]; } @@ -843,9 +822,7 @@ - (void)requestEnsurePeerRegistration _shadowEnsurePeerRegistration = YES; } else { _ensurePeerRegistration = YES; - if (![self.lockMonitor locked]){ - [self doEnsurePeerRegistration]; - } + [self handlePendingEnsurePeerRegistrationRequests:true]; [self persistState]; } @@ -864,9 +841,7 @@ - (void)_queue_unlocked dispatch_assert_queue(_ckdkvsproxy_queue); secnotice("event", "%@ Unlocked", self); - if (_ensurePeerRegistration) { - [self doEnsurePeerRegistration]; - } + [self handlePendingEnsurePeerRegistrationRequests:false]; // First send changed keys to securityd so it can proccess updates [self processPendingKeysForCurrentLockState]; diff --git a/KVSKeychainSyncingProxy/CKDKVSStore.m b/KVSKeychainSyncingProxy/CKDKVSStore.m index 89bdd3296..03386203a 100644 --- a/KVSKeychainSyncingProxy/CKDKVSStore.m +++ b/KVSKeychainSyncingProxy/CKDKVSStore.m @@ -17,6 +17,8 @@ #import "SyncedDefaults/SYDConstants.h" #include +#import "Analytics/Clients/SOSAnalytics.h" + struct CKDKVSCounters { uint64_t synchronize; uint64_t synchronizeWithCompletionHandler; @@ -32,7 +34,7 @@ @interface CKDKVSStore () @property (readwrite, weak) UbiqitousKVSProxy* proxy; @property (readwrite) NSUbiquitousKeyValueStore* cloudStore; -@property (assign,readwrite) struct CKDKVSCounters *perfCounters; +@property (assign,readwrite) struct CKDKVSCounters* perfCounters; @property dispatch_queue_t perfQueue; @end @@ -55,6 +57,7 @@ - (instancetype)init { self.perfQueue = dispatch_queue_create("CKDKVSStorePerfQueue", NULL); self.perfCounters = calloc(1, sizeof(struct CKDKVSCounters)); + [self setupSamplers]; return self; } @@ -232,17 +235,41 @@ - (void)perfCounters:(void(^)(NSDictionary *counters))callback { dispatch_async(self.perfQueue, ^{ callback(@{ - @"CKDKVS-synchronize" : @(self.perfCounters->synchronize), - @"CKDKVS-synchronizeWithCompletionHandler" : @(self.perfCounters->synchronizeWithCompletionHandler), - @"CKDKVS-incomingMessages" : @(self.perfCounters->incomingMessages), - @"CKDKVS-outgoingMessages" : @(self.perfCounters->outgoingMessages), - @"CKDKVS-totalWaittimeSynchronize" : @(self.perfCounters->totalWaittimeSynchronize), - @"CKDKVS-longestWaittimeSynchronize" : @(self.perfCounters->longestWaittimeSynchronize), - @"CKDKVS-synchronizeFailures" : @(self.perfCounters->synchronizeFailures), + CKDKVSPerfCounterSynchronize : @(self.perfCounters->synchronize), + CKDKVSPerfCounterSynchronizeWithCompletionHandler : @(self.perfCounters->synchronizeWithCompletionHandler), + CKDKVSPerfCounterIncomingMessages : @(self.perfCounters->incomingMessages), + CKDKVSPerfCounterOutgoingMessages : @(self.perfCounters->outgoingMessages), + CKDKVSPerfCounterTotalWaitTimeSynchronize : @(self.perfCounters->totalWaittimeSynchronize), + CKDKVSPerfCounterLongestWaitTimeSynchronize : @(self.perfCounters->longestWaittimeSynchronize), + CKDKVSPerfCounterSynchronizeFailures : @(self.perfCounters->synchronizeFailures), }); }); } +#if __OBJC2__ +- (void)setupSamplers +{ + [[SOSAnalytics logger] AddMultiSamplerForName:CKDKVSPerformanceCountersSampler + withTimeInterval:SFAnalyticsSamplerIntervalOncePerReport + block:^NSDictionary *{ + __block NSDictionary* data; + [self perfCounters:^(NSDictionary *counters) { + data = counters; + }]; + + dispatch_sync(self.perfQueue, ^{ + memset(self.perfCounters, 0, sizeof(struct CKDKVSCounters)); + }); + return data; + }]; +} +#else +- (void)setupSamplers +{ + // SFA is only for 64 bit cool kids +} +#endif + - (void)addOneToOutGoing { dispatch_async(self.perfQueue, ^{ diff --git a/KVSKeychainSyncingProxy/CKDLockMonitor.h b/KVSKeychainSyncingProxy/CKDLockMonitor.h index 83ab5c29f..36cf8e90f 100644 --- a/KVSKeychainSyncingProxy/CKDLockMonitor.h +++ b/KVSKeychainSyncingProxy/CKDLockMonitor.h @@ -5,14 +5,14 @@ #import "CKDLockMonitor.h" -@protocol CKDLockListener +@protocol CKDLockListener - (void) unlocked; - (void) locked; @end -@protocol CKDLockMonitor +@protocol CKDLockMonitor @property (readonly) BOOL unlockedSinceBoot; @property (readonly) BOOL locked; diff --git a/KVSKeychainSyncingProxy/CKDStore.h b/KVSKeychainSyncingProxy/CKDStore.h index 46b8a031f..ec68f709c 100644 --- a/KVSKeychainSyncingProxy/CKDStore.h +++ b/KVSKeychainSyncingProxy/CKDStore.h @@ -8,7 +8,7 @@ @class UbiqitousKVSProxy; -@protocol CKDStore +@protocol CKDStore - (void)connectToProxy: (UbiqitousKVSProxy*) proxy; diff --git a/KVSKeychainSyncingProxy/XPCNotificationDispatcher.h b/KVSKeychainSyncingProxy/XPCNotificationDispatcher.h index 3fc9c4c43..6b1b6243e 100644 --- a/KVSKeychainSyncingProxy/XPCNotificationDispatcher.h +++ b/KVSKeychainSyncingProxy/XPCNotificationDispatcher.h @@ -6,7 +6,7 @@ #import -@protocol XPCNotificationListener +@protocol XPCNotificationListener - (void) handleNotification: (const char *) name; @end diff --git a/KVSKeychainSyncingProxy/cloudkeychainproxy.m b/KVSKeychainSyncingProxy/cloudkeychainproxy.m index 29ea30241..b0f39a4cb 100644 --- a/KVSKeychainSyncingProxy/cloudkeychainproxy.m +++ b/KVSKeychainSyncingProxy/cloudkeychainproxy.m @@ -330,7 +330,6 @@ void finalize_connection(void *not_used) static bool operation_put_dictionary(xpc_object_t event) { // PUT a set of objects into the KVS store. Return false if error - describeXPCObject("operation_put_dictionary event: ", event); xpc_object_t xvalue = xpc_dictionary_get_value(event, kMessageKeyValue); if (!xvalue) { return false; @@ -349,9 +348,7 @@ static bool operation_put_dictionary(xpc_object_t event) static bool operation_get_v2(xpc_connection_t peer, xpc_object_t event) { - // GET a set of objects from the KVS store. Return false if error - describeXPCObject("operation_get_v2 event: ", 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) { @@ -393,7 +390,6 @@ static bool operation_get_v2(xpc_connection_t peer, xpc_object_t event) secdebug(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); - describeXPCObject("operation_get_v2: value from kvs: ", xobject); }]; } else // get all values from kvs @@ -422,11 +418,16 @@ static void cloudkeychainproxy_event_handler(xpc_connection_t peer) 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) { - describeXPCObject("peer: ", peer); // Only describes under debug - // 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) { @@ -468,7 +469,7 @@ int ckdproxymain(int argc, const char *argv[]) UbiqitousKVSProxy* proxyID = SharedProxy(); if (proxyID) { // nothing bad happened when initializing - xpc_connection_t listener = xpc_connection_create_mach_service(xpcServiceName, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER); + 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. diff --git a/KVSKeychainSyncingProxy/com.apple.security.cloudkeychainproxy3.osx.plist b/KVSKeychainSyncingProxy/com.apple.security.cloudkeychainproxy3.osx.plist index 14f56bbf9..37caef67d 100644 --- a/KVSKeychainSyncingProxy/com.apple.security.cloudkeychainproxy3.osx.plist +++ b/KVSKeychainSyncingProxy/com.apple.security.cloudkeychainproxy3.osx.plist @@ -4,8 +4,6 @@ ProcessType Adaptive - LimitLoadToSessionType - Background EnablePressuredExit ProgramArguments diff --git a/KeychainCircle/KCAESGCMDuplexSession.h b/KeychainCircle/KCAESGCMDuplexSession.h index 0304f1d18..7d6c8f2e2 100644 --- a/KeychainCircle/KCAESGCMDuplexSession.h +++ b/KeychainCircle/KCAESGCMDuplexSession.h @@ -10,6 +10,12 @@ NS_ASSUME_NONNULL_BEGIN @interface KCAESGCMDuplexSession : NSObject +// Due to design constraints, this session object is the only thing serialized during piggybacking sessions. +// Therefore, we must add some extra data here, which is not strictly part of a AES GCM session. +@property (retain, nullable) NSString* pairingUUID; +@property uint64_t piggybackingVersion; +@property uint64_t epoch; + - (nullable NSData*) encrypt: (NSData*) data error: (NSError**) error; - (nullable NSData*) decryptAndVerify: (NSData*) data error: (NSError**) error; @@ -24,7 +30,15 @@ NS_ASSUME_NONNULL_BEGIN context: (uint64_t) context; - (nullable instancetype) initWithSecret: (NSData*) sharedSecret context: (uint64_t) context - as: (bool) inverted NS_DESIGNATED_INITIALIZER; + as: (bool) inverted; + +- (nullable instancetype)initWithSecret:(NSData*)sharedSecret + context:(uint64_t)context + as:(bool) sender + pairingUUID:(NSString* _Nullable)pairingUUID + piggybackingVersion:(uint64_t)piggybackingVersion + epoch:(uint64_t)epoch + NS_DESIGNATED_INITIALIZER; - (instancetype) init NS_UNAVAILABLE; diff --git a/KeychainCircle/KCAESGCMDuplexSession.m b/KeychainCircle/KCAESGCMDuplexSession.m index b3d5516e9..3bc684cd9 100644 --- a/KeychainCircle/KCAESGCMDuplexSession.m +++ b/KeychainCircle/KCAESGCMDuplexSession.m @@ -94,20 +94,29 @@ + (nullable instancetype) sessionAsReceiver: (NSData*) sharedSecret static NSString* KCDSSender = @"asSender"; static NSString* KCDSSecret = @"secret"; static NSString* KCDSContext = @"context"; +static NSString* KCDSPairingUUID = @"uuid"; +static NSString* KCDSPiggybackingVersion = @"piggy"; +static NSString* KCDSEpoch= @"epoch"; - (void)encodeWithCoder:(NSCoder *)aCoder { [aCoder encodeBool: self.asSender forKey:KCDSSender]; [aCoder encodeObject: self.secret forKey:KCDSSecret]; [aCoder encodeInt64: self.context forKey:KCDSContext]; + [aCoder encodeObject: self.pairingUUID forKey:KCDSPairingUUID]; + [aCoder encodeInt64: self.piggybackingVersion forKey:KCDSPiggybackingVersion]; + [aCoder encodeInt64:self.epoch forKey:KCDSEpoch]; } - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { - bool asSender = [aDecoder decodeBoolForKey:KCDSSender]; NSData* secret = [aDecoder decodeObjectOfClass:[NSData class] forKey:KCDSSecret]; uint64_t context = [aDecoder decodeInt64ForKey:KCDSContext]; - return [self initWithSecret:secret context:context as:asSender]; + NSString* pairingUUID = [aDecoder decodeObjectOfClass:[NSString class] forKey:KCDSPairingUUID]; + uint64_t piggybackingVersion = [aDecoder decodeInt64ForKey:KCDSPiggybackingVersion]; + uint64_t epoch = [aDecoder decodeInt64ForKey:KCDSEpoch]; + + return [self initWithSecret:secret context:context as:asSender pairingUUID:pairingUUID piggybackingVersion:piggybackingVersion epoch:epoch]; } + (BOOL)supportsSecureCoding { @@ -127,6 +136,21 @@ - (nullable instancetype) initAsReceiver: (NSData*) sharedSecret context: (uint6 - (nullable instancetype) initWithSecret: (NSData*) sharedSecret context: (uint64_t) context as: (bool) sender { + return [self initWithSecret:sharedSecret + context:context + as:sender + pairingUUID:nil + piggybackingVersion:0 + epoch:1]; +} + +- (nullable instancetype)initWithSecret:(NSData*)sharedSecret + context:(uint64_t)context + as:(bool) sender + pairingUUID:(NSString* _Nullable)pairingUUID + piggybackingVersion:(uint64_t)piggybackingVersion + epoch:(uint64_t)epoch +{ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ kdfInfoSendToReceive = [NSData dataWithBytesNoCopy: kdfInfoForwardString @@ -146,6 +170,10 @@ - (nullable instancetype) initWithSecret: (NSData*) sharedSecret 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; } @@ -299,6 +327,8 @@ - (nullable NSData*) decryptAndVerify: (NSData*) data error: (NSError**) error { error:error] ? decrypted : nil; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" - (void) finalize { if (self.send) { ccgcm_ctx_clear(sizeof(*self.send), self.send); @@ -310,5 +340,6 @@ - (void) finalize { } [super finalize]; } +#pragma clang diagnostic pop @end diff --git a/KeychainCircle/KCInitialMessageData.proto b/KeychainCircle/KCInitialMessageData.proto new file mode 100644 index 000000000..db6ffd305 --- /dev/null +++ b/KeychainCircle/KCInitialMessageData.proto @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +syntax = "proto2"; + +option objc_class_naming = "extended"; + +package KC; + +message InitialMessageData { + optional bytes prepareMessage = 1; +} diff --git a/KeychainCircle/KCJoiningAcceptSession+Internal.h b/KeychainCircle/KCJoiningAcceptSession+Internal.h new file mode 100644 index 000000000..ea2c1be2f --- /dev/null +++ b/KeychainCircle/KCJoiningAcceptSession+Internal.h @@ -0,0 +1,38 @@ +/* + * 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 + +#ifndef KCJoiningAcceptSession_Internal_h +#define KCJoiningAcceptSession_Internal_h + +#import +#import "keychain/ot/OTControl.h" +#import "KCJoiningSession.h" + +@interface KCJoiningAcceptSession (Internal) +-(void)setControlObject:(OTControl*)control; +- (void)setConfiguration:(OTJoiningConfiguration *)config; +@end +#endif /* Header_h */ +#endif diff --git a/KeychainCircle/KCJoiningAcceptSession.m b/KeychainCircle/KCJoiningAcceptSession.m index ec8b8b907..743b60e30 100644 --- a/KeychainCircle/KCJoiningAcceptSession.m +++ b/KeychainCircle/KCJoiningAcceptSession.m @@ -13,6 +13,7 @@ #import #import +#import "KCInitialMessageData.h" #include #include @@ -20,6 +21,17 @@ #include #include #include +#include + +#if OCTAGON +#import "keychain/ot/OTControl.h" +#import "keychain/ot/OTJoiningConfiguration.h" +#import "KeychainCircle/KCJoiningAcceptSession+Internal.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/OTPairingMessage.h" +#endif typedef enum { kExpectingA, @@ -38,6 +50,12 @@ @interface KCJoiningAcceptSession () @property (readwrite) NSData* startMessage; @property (readwrite) NSString *piggy_uuid; @property (readwrite) PiggyBackProtocolVersion piggy_version; +@property (readwrite) NSData* octagon; +#if OCTAGON +@property (nonatomic, strong) OTJoiningConfiguration* joiningConfiguration; +@property (nonatomic, strong) OTControl* otControl; +#endif +@property (nonatomic, strong) NSMutableDictionary *defaults; @end @implementation KCJoiningAcceptSession @@ -72,6 +90,10 @@ - (bool) setupSession: (NSError**) error { } self->_session = [KCAESGCMDuplexSession sessionAsReceiver:key context:self.dsid]; +#if OCTAGON + self.session.pairingUUID = self.joiningConfiguration.pairingUUID; +#endif + self.session.piggybackingVersion = self.piggy_version; return self.session != nil; } @@ -83,6 +105,8 @@ - (nullable instancetype) initWithSecretDelegate: (NSObject_context = [[KCSRPServerContext alloc] initWithUser: name @@ -95,7 +119,21 @@ - (nullable instancetype) initWithSecretDelegate: (NSObject_state = kExpectingA; self->_dsid = dsid; self->_piggy_uuid = nil; + self->_defaults = [NSMutableDictionary dictionary]; + +#if OCTAGON + self->_otControl = [OTControl controlObject:true error:error]; + self->_piggy_version = KCJoiningOctagonPiggybackingEnabled()? kPiggyV2 : kPiggyV1; + self->_joiningConfiguration = [[OTJoiningConfiguration alloc]initWithProtocolType:@"OctagonPiggybacking" + uniqueDeviceID:@"acceptor-deviceid" + uniqueClientID:@"requester-deviceid" + containerName:nil + contextID:OTDefaultContext + epoch:0 + isInitiator:false]; +#else self->_piggy_version = kPiggyV1; +#endif return self; } @@ -111,7 +149,7 @@ - (NSString*) stateString { } - (NSString *)description { - return [NSString stringWithFormat: @"", self, self.dsid, [self stateString], self.context]; + return [NSString stringWithFormat: @"", self.dsid, [self stateString], self.context, self.piggy_uuid]; } - (NSData*) copyChallengeMessage: (NSError**) error { @@ -125,20 +163,105 @@ - (NSData*) copyChallengeMessage: (NSError**) error { return srpMessage; } +#if OCTAGON +- (BOOL)shouldAcceptOctagonRequests { + dispatch_semaphore_t sema = dispatch_semaphore_create(0); + __block BOOL result = NO; + + OTOperationConfiguration* configuration = [[OTOperationConfiguration alloc] init]; + configuration.discretionaryNetwork = TRUE; + + [self.otControl fetchTrustStatus:self.joiningConfiguration.containerName context:self.joiningConfiguration.self.contextID + configuration:configuration + reply:^(CliqueStatus status, + NSString* peerID, + NSNumber * _Nullable numberOfPeersInOctagon, + BOOL isExcluded, NSError* _Nullable error) + { + secerror("octagon haveSelfEgo: status %d: %@ %@ %d: %@", (int)status, + peerID, numberOfPeersInOctagon, isExcluded, error); + + if (status == CliqueStatusIn) { + result = YES; + } + dispatch_semaphore_signal(sema); + }]; + + if(dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 30)) != 0) { + secerror("octagon: timed out fetching trust status"); + return NO; + } + return result; +} +#endif + - (NSData*) processInitialMessage: (NSData*) initialMessage error: (NSError**) error { - uint64_t version = 0; + __block uint64_t version = 0; NSString *uuid = nil; - - self.startMessage = extractStartFromInitialMessage(initialMessage, &version, &uuid, error); + NSData *octagon = nil; + NSError* localError = nil; + + self.startMessage = extractStartFromInitialMessage(initialMessage, &version, &uuid, &octagon, error); + if (self.startMessage == NULL) { + return nil; + } +#if OCTAGON + if(version == kPiggyV2 && KCJoiningOctagonPiggybackingEnabled()){ + /* before we go ahead with octagon, let see if we are an octagon peer */ + + if (![self shouldAcceptOctagonRequests]) { + secerror("octagon refusing octagon acceptor since we don't have a selfEgo"); + version = kPiggyV1; + } else { + self.octagon = octagon; + } + localError = nil; + } +#endif self.piggy_uuid = uuid; self.piggy_version = (PiggyBackProtocolVersion)version; - - if (self.startMessage == nil) return nil; NSData* srpMessage = [self copyChallengeMessage: error]; - if (srpMessage == nil) return nil; + if (srpMessage == nil) { + return nil; + } self->_state = kExpectingM; +#if OCTAGON + NSString* piggyVersionMessage = [[NSString alloc]initWithData:self.octagon encoding:NSUTF8StringEncoding]; + __block NSError *captureError = nil; + + if(version == kPiggyV2 && KCJoiningOctagonPiggybackingEnabled() && piggyVersionMessage && [piggyVersionMessage isEqualToString:@"o"]) { + __block NSData* next = nil; + dispatch_semaphore_t sema = dispatch_semaphore_create(0); + + //fetch epoch + [self.otControl rpcEpochWithConfiguration:self.joiningConfiguration reply:^(uint64_t epoch, NSError * _Nullable epochError) { + if(epochError){ + secerror("error retrieving next message! :%@", epochError); + captureError = epochError; + }else{ + OTPairingMessage* responseMessage = [[OTPairingMessage alloc] init]; + responseMessage.epoch = [[OTSponsorToApplicantRound1M2 alloc] init]; + responseMessage.epoch.epoch = epoch; + next = responseMessage.data; + } + dispatch_semaphore_signal(sema); + }]; + + if(dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 30)) != 0) { + secerror("octagon: timed out fetching epoch"); + return nil; + } + if(error && captureError){ + *error = captureError; + } + return [[KCJoiningMessage messageWithType:kChallenge + data:srpMessage + payload:next + error:error] der]; + } +#endif return [[KCJoiningMessage messageWithType:kChallenge data:srpMessage error:error] der]; @@ -156,7 +279,10 @@ - (NSData*) processResponse: (KCJoiningMessage*) message error:(NSError**) error // Find out what kind of error we should send. NSData* errorData = nil; - switch ([self.secretDelegate verificationFailed: error]) { + KCRetryOrNot status = [self.secretDelegate verificationFailed: error]; + secerror("processResponse: handle error: %d", (int)status); + + switch (status) { case kKCRetryError: // We fill in an error if they didn't, but if they did this wont bother. KCJoiningErrorCreate(kInternalError, error, @"Delegate returned error without filling in error: %@", self.secretDelegate); @@ -192,13 +318,9 @@ - (NSData*) processResponse: (KCJoiningMessage*) message error:(NSError**) error error:error] der]; } -- (NSData*) processApplication: (KCJoiningMessage*) message error:(NSError**) error { - if ([message type] != kPeerInfo) { - KCJoiningErrorCreate(kUnexpectedMessage, error, @"Expected peerInfo!"); - return nil; - } - - NSData* decryptedPayload = [self.session decryptAndVerify:message.firstData error:error]; +- (NSData*) processSOSApplication: (NSData*) message error:(NSError**) error +{ + NSData* decryptedPayload = [self.session decryptAndVerify:message error:error]; if (decryptedPayload == nil) return nil; CFErrorRef cfError = NULL; @@ -210,22 +332,142 @@ - (NSData*) processApplication: (KCJoiningMessage*) message error:(NSError**) er } NSData* joinData = [self.circleDelegate circleJoinDataFor:ref error:error]; + if(ref) { + CFRelease(ref); + ref = NULL; + } + if (joinData == nil) return nil; - + if(self->_piggy_version == kPiggyV1){ - //grab iCloud Identity, TLK, BackupV0 thing + //grab iCloud Identities, TLKs secnotice("acceptor", "piggy version is 1"); - NSData* initialSyncData = [self.circleDelegate circleGetInitialSyncViews:error]; + NSError *localV1Error = nil; + NSData* initialSyncData = [self.circleDelegate circleGetInitialSyncViews:&localV1Error]; + if(localV1Error){ + secnotice("piggy", "PB v1 threw an error: %@", localV1Error); + } + NSMutableData* growPacket = [[NSMutableData alloc] initWithData:joinData]; [growPacket appendData:initialSyncData]; joinData = growPacket; + } - + NSData* encryptedOutgoing = [self.session encrypt:joinData error:error]; if (encryptedOutgoing == nil) return nil; + return encryptedOutgoing; +} + +#if OCTAGON +- (OTPairingMessage *)createPairingMessageFromJoiningMessage:(KCJoiningMessage *)message error:(NSError**) error +{ + NSData *decryptInitialMessage = [self.session decryptAndVerify:message.firstData error:error]; + if(!decryptInitialMessage) { + secinfo("KeychainCircle", "Failed to decrypt message first data: %@. Trying legacy OTPairingMessage construction.", error ? *error : @""); + return [[OTPairingMessage alloc] initWithData:message.firstData]; + } else { + KCInitialMessageData *initialMessage = [[KCInitialMessageData alloc] initWithData:decryptInitialMessage]; + if(!initialMessage) { + secerror("Failed to parse InitialMessageData from decrypted message data"); + KCJoiningErrorCreate(kUnexpectedMessage, error, @"Failed to parse InitialMessageData from decrypted message data"); + return nil; + } + + if(!initialMessage.hasPrepareMessage) { + secerror("InitialMessageData does not contain prepare message"); + KCJoiningErrorCreate(kUnexpectedMessage, error, @"Expected prepare message inside InitialMessageData"); + return nil; + } + + return [[OTPairingMessage alloc] initWithData:initialMessage.prepareMessage]; + } +} +#endif + +- (NSData*) processApplication: (KCJoiningMessage*) message error:(NSError**) error { + if ([message type] != kPeerInfo) { + KCJoiningErrorCreate(kUnexpectedMessage, error, @"Expected peerInfo!"); + return nil; + } +#if OCTAGON + if(self.piggy_version == kPiggyV2 && KCJoiningOctagonPiggybackingEnabled()){ + __block NSData* next = nil; + __block NSError* localError = nil; + dispatch_semaphore_t sema = dispatch_semaphore_create(0); + + OTPairingMessage *pairingMessage = [self createPairingMessageFromJoiningMessage:message error:error]; + if(!pairingMessage) { + secerror("octagon, failed to create pairing message from JoiningMessage"); + KCJoiningErrorCreate(kUnexpectedMessage, error, @"Failed to create pairing message from JoiningMessage"); + return nil; + } + + if(!pairingMessage.hasPrepare) { + secerror("octagon, message does not contain prepare message"); + KCJoiningErrorCreate(kUnexpectedMessage, error, @"Expected prepare message!"); + return nil; + } + OTApplicantToSponsorRound2M1 *prepareMessage = pairingMessage.prepare; + + //handle identity, fetch voucher + [self.otControl rpcVoucherWithConfiguration:self.joiningConfiguration + peerID:prepareMessage.peerID + permanentInfo:prepareMessage.permanentInfo + permanentInfoSig:prepareMessage.permanentInfoSig + stableInfo:prepareMessage.stableInfo + stableInfoSig:prepareMessage.stableInfoSig reply:^(NSData *voucher, + NSData *voucherSig, + NSError *err) { + if(err){ + secerror("error producing octagon voucher: %@", err); + localError = err; + }else{ + OTPairingMessage *pairingResponse = [[OTPairingMessage alloc] init]; + pairingResponse.voucher = [[OTSponsorToApplicantRound2M2 alloc] init]; + pairingResponse.voucher.voucher = voucher; + pairingResponse.voucher.voucherSignature = voucherSig; + next = pairingResponse.data; + } + dispatch_semaphore_signal(sema); + }]; + + if(dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 30)) != 0) { + secerror("octagon: timed out producing octagon voucher"); + return nil; + } + if (next == NULL) { + if(error && localError){ + *error = localError; + } + return nil; + } + + NSData* encryptedOutgoing = nil; + if (OctagonPlatformSupportsSOS() && message.secondData) { + 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"); + } + + self->_state = kAcceptDone; + + return [[KCJoiningMessage messageWithType:kCircleBlob + data:next + payload:encryptedOutgoing + error:error] der]; + } +#endif + NSData* encryptedOutgoing = [self processSOSApplication: message.firstData error:error]; self->_state = kAcceptDone; + secnotice("joining", "posting kSOSCCCircleOctagonKeysChangedNotification"); + notify_post(kSOSCCCircleOctagonKeysChangedNotification); + return [[KCJoiningMessage messageWithType:kCircleBlob data:encryptedOutgoing error:error] der]; @@ -235,6 +477,8 @@ - (NSData*) processApplication: (KCJoiningMessage*) message error:(NSError**) er - (nullable NSData*) processMessage: (NSData*) incomingMessage error: (NSError**) error { NSData* result = nil; + secnotice("acceptor", "processMessages: %@", [self description]); + KCJoiningMessage *message = (self.state != kExpectingA) ? [KCJoiningMessage messageWithDER:incomingMessage error:error] : nil; switch(self.state) { @@ -259,4 +503,17 @@ - (bool) isDone { return self.state == kAcceptDone; } +/* for test*/ +#if OCTAGON +- (void)setControlObject:(OTControl *)control +{ + self.otControl = control; +} + +- (void)setConfiguration:(OTJoiningConfiguration *)config +{ + self.joiningConfiguration = config; +} +#endif + @end diff --git a/KeychainCircle/KCJoiningMessages.h b/KeychainCircle/KCJoiningMessages.h index 827e0e411..a6ad9e385 100644 --- a/KeychainCircle/KCJoiningMessages.h +++ b/KeychainCircle/KCJoiningMessages.h @@ -9,10 +9,11 @@ // Initial messages are versioned and not typed for negotiation. NS_ASSUME_NONNULL_BEGIN -NSData* extractStartFromInitialMessage(NSData* initialMessage, uint64_t* version, NSString* _Nullable * _Nullable uuidString, NSError** error); +NSData* extractStartFromInitialMessage(NSData* initialMessage, uint64_t* version, NSString* _Nullable * _Nullable uuidString, NSData* _Nullable * _Nullable octagon, NSError** error); size_t sizeof_initialmessage(NSData*data); size_t sizeof_initialmessage_version1(NSData*data, uint64_t version1, NSData *uuid); +size_t sizeof_initialmessage_version2(NSData*data, uint64_t version1, NSData *uuid, NSData* octagon); @@ -21,12 +22,19 @@ uint8_t* _Nullable encode_initialmessage(NSData* data, NSError**error, uint8_t* _Nullable encode_initialmessage_version1(NSData* data, NSData* uuidData, uint64_t piggy_version, NSError**error, const uint8_t *der, uint8_t *der_end); +uint8_t* encode_initialmessage_version2(NSData* data, NSData* uuidData, NSData* octagon_version, NSError**error, + const uint8_t *der, uint8_t *der_end); + const uint8_t* _Nullable decode_initialmessage(NSData* _Nonnull * _Nonnull data, NSError** error, const uint8_t* der, const uint8_t *der_end); const uint8_t* _Nullable decode_version1(NSData* _Nonnull* _Nonnull data, NSData* _Nullable* _Nullable uuid, uint64_t * _Nullable piggy_version, NSError** error, const uint8_t* der, const uint8_t *der_end); +const uint8_t* _Nullable decode_version2(NSData* _Nonnull* _Nonnull data, NSData* _Nullable* _Nullable uuid, NSData* _Nullable* _Nullable octagon, uint64_t* _Nullable piggy_version, NSError** error, + const uint8_t* der, const uint8_t *der_end); + + size_t sizeof_seq_data_data(NSData*data1, NSData*data2, NSError** error); uint8_t* _Nullable encode_seq_data_data(NSData* data, NSData*data2, NSError**error, const uint8_t *der, uint8_t *der_end); @@ -90,7 +98,6 @@ typedef enum { @property (readonly) KCJoiningMessageType type; @property (readonly) NSData* firstData; @property (nullable, readonly) NSData* secondData; - @property (readonly) NSData* der; + (nullable instancetype) messageWithDER: (NSData*) message diff --git a/KeychainCircle/KCJoiningMessages.m b/KeychainCircle/KCJoiningMessages.m index 7d83db0f6..2eb0c94be 100644 --- a/KeychainCircle/KCJoiningMessages.m +++ b/KeychainCircle/KCJoiningMessages.m @@ -13,7 +13,7 @@ #import #import #import - +#import #include @@ -30,6 +30,13 @@ + (nullable instancetype) messageWithType: (KCJoiningMessageType) type return [[KCJoiningMessage alloc] initWithType:type data:firstData payload:nil error:error]; } ++ (nullable instancetype) messageWithType: (KCJoiningMessageType) type + data: (NSData*) firstData + secondData: (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 @@ -255,7 +262,7 @@ + (nullable instancetype) decodeFromDER: (NSData*)der error: (NSError** _Nullabl @end -NSData* extractStartFromInitialMessage(NSData* initialMessage, uint64_t* version, NSString** uuidString, NSError** error) { +NSData* extractStartFromInitialMessage(NSData* initialMessage, uint64_t* version, NSString** uuidString, NSData** octagon, NSError** error) { NSData* result = nil; const uint8_t *der = [initialMessage bytes]; const uint8_t *der_end = der + [initialMessage length]; @@ -267,12 +274,30 @@ + (nullable instancetype) decodeFromDER: (NSData*)der error: (NSError** _Nullabl } else if (parse_end != der_end) { NSData *extraStuff = nil; - NSData *uuid = nil; + NSData *uuidData = nil; uint64_t piggy_version = 0; - parse_end = decode_version1(&extraStuff, &uuid, &piggy_version, error, parse_end, der_end); - require_action_quiet(parse_end != NULL, fail, secerror("decoding piggybacking uuid and version failed (v1)")); - *uuidString = [[NSString alloc] initWithData:uuid encoding:NSUTF8StringEncoding]; - *version = piggy_version; + NSData* octagonData = nil; + + parse_end = decode_version2(&extraStuff, &uuidData, &octagonData, &piggy_version, error, parse_end, der_end); + require_action_quiet(parse_end != NULL, fail, secerror("decoding piggybacking message failed for version (%llu)", piggy_version)); + + switch(piggy_version){ + case kPiggyV2: + *octagon = octagonData; + //fall through to pick up v1 + case kPiggyV1:{ + NSUUID *uuid = [[NSUUID alloc]initWithUUIDBytes:uuidData.bytes]; + *uuidString = uuid.UUIDString; + *version = piggy_version; + break; + } + case kPiggyV0: + *version = kPiggyV0; + break; + default: + secerror("unsupported version"); + break; + } } fail: return result; @@ -294,11 +319,12 @@ + (nullable instancetype) decodeFromDER: (NSData*)der error: (NSError** _Nullabl } if(versionFromBlob == 1){ //decode uuid - size_t payload_size = 0; - const uint8_t *payload = ccder_decode_tl(CCDER_OCTET_STRING, &payload_size, der, der_end); + size_t payloadSize = 0; + const uint8_t *payload = ccder_decode_tl(CCDER_OCTET_STRING, &payloadSize, der, der_end); - *uuid = [NSData dataWithBytes: (void*)payload length: payload_size]; + *uuid = [NSData dataWithBytes: (void*)payload length: payloadSize]; *piggy_version = versionFromBlob; + der = payload + payloadSize; } else{ KCJoiningErrorCreate(kDERUnknownVersion, error, @"Bad version: %llu", versionFromBlob); @@ -307,6 +333,41 @@ + (nullable instancetype) decodeFromDER: (NSData*)der error: (NSError** _Nullabl return der; } + +const uint8_t* decode_version2(NSData** data, NSData** uuid, NSData** octagon, uint64_t *piggy_version, NSError** error, + const uint8_t* der, const uint8_t *der_end) +{ + const uint8_t* end = nil; + + const uint8_t* parse_version1 = decode_version1(data, uuid, piggy_version, error, der, der_end); + + if(parse_version1 == NULL){ + secerror("error parsing version 1"); + return NULL; + } + else if (parse_version1 == der_end){ + secnotice("octagon", "first message is piggybacking v1, no more data"); + return parse_version1; + } + else{ + end = kcder_decode_data(octagon, error, parse_version1, der_end); + + if(end == NULL){ + secerror("failed to decode v2"); + return NULL; + } + else if(*octagon && [*octagon length] != 0){ + *piggy_version = kPiggyV2; + } + else{ + secerror("no octagon version set"); + return NULL; + } + } + + return end; +} + const uint8_t* decode_initialmessage(NSData** data, NSError** error, const uint8_t* der, const uint8_t *der_end) { @@ -356,7 +417,8 @@ size_t sizeof_initialmessage(NSData*data) { kcder_encode_data(data, error, der, der_end))); } -size_t sizeof_initialmessage_version1(NSData*data, uint64_t version1, NSData *uuid) { +size_t sizeof_initialmessage_version2(NSData*data, uint64_t version1, NSData *uuid, NSData* octagon) +{ size_t version_size = ccder_sizeof_uint64(0); if (version_size == 0) { return 0; @@ -370,9 +432,35 @@ size_t sizeof_initialmessage_version1(NSData*data, uint64_t version1, NSData *uu return 0; } size_t uuid_size = kcder_sizeof_data(uuid, nil); + if (uuid_size == 0) { + return 0; + } + size_t octagon_size = kcder_sizeof_data(octagon, nil); + if (octagon_size == 0) { + return 0; + } + return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, version_size + message_size + + version1_size + uuid_size + + octagon_size); +} + +size_t sizeof_initialmessage_version1(NSData*data, uint64_t version1, NSData *uuid) { + size_t version_size = ccder_sizeof_uint64(0); + if (version_size == 0) { + return 0; + } + size_t message_size = kcder_sizeof_data(data, nil); if (message_size == 0) { return 0; } + size_t version1_size = ccder_sizeof_uint64(version1); + if (version1_size == 0) { + return 0; + } + size_t uuid_size = kcder_sizeof_data(uuid, nil); + if (uuid_size == 0) { + return 0; + } return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, version_size + message_size + version1_size + uuid_size); } @@ -388,6 +476,17 @@ size_t sizeof_initialmessage_version1(NSData*data, uint64_t version1, NSData *uu } +uint8_t* encode_initialmessage_version2(NSData* data, NSData* uuidData, NSData* octagon_version, NSError**error, + const uint8_t *der, uint8_t *der_end) +{ + + return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, + ccder_encode_uint64(0, der, + kcder_encode_data(data, error, der, + ccder_encode_uint64(kPiggyV1, der, + kcder_encode_data(uuidData, error, der, kcder_encode_data(octagon_version, error, der, der_end)))))); +} + size_t sizeof_seq_data_data(NSData*data1, NSData*data2, NSError**error) { size_t data1_size = kcder_sizeof_data(data1, error); if (data1_size == 0) { diff --git a/KeychainCircle/KCJoiningRequestCircleSession.m b/KeychainCircle/KCJoiningRequestCircleSession.m new file mode 100644 index 000000000..ed9db9508 --- /dev/null +++ b/KeychainCircle/KCJoiningRequestCircleSession.m @@ -0,0 +1,332 @@ +// +// KCJoiningRequestCircleSession.m +// Security +// + +#import + +#import + +#import +#import +#import + +#import + +#include +#include "KCInitialMessageData.h" + +#if OCTAGON +#import +#import "keychain/ot/OTControl.h" +#import "keychain/ot/OTControlProtocol.h" +#import "keychain/ot/OctagonControlServer.h" +#import "keychain/ot/OTJoiningConfiguration.h" +#import "KeychainCircle/KCJoiningRequestSession+Internal.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/OTPairingMessage.h" +#endif +#import + +typedef enum { + kExpectingCircleBlob, + kRequestCircleDone +} KCJoiningRequestCircleSessionState; + +@interface KCJoiningRequestCircleSession () +@property (readonly) NSObject* circleDelegate; +@property (readonly) KCAESGCMDuplexSession* session; +@property (readwrite) KCJoiningRequestCircleSessionState state; +@property (nonatomic) uint64_t piggy_version; +#if OCTAGON +@property (nonatomic, strong) OTControl *otControl; +@property (nonatomic, strong) OTJoiningConfiguration* joiningConfiguration; +#endif +@end + +@implementation KCJoiningRequestCircleSession + +#if OCTAGON +- (void)setControlObject:(OTControl *)control{ + self.otControl = control; +} +- (void)setJoiningConfigurationObject:(OTJoiningConfiguration *)joiningConfiguration +{ + self.joiningConfiguration = joiningConfiguration; +} + +#endif + +- (nullable NSData*) encryptedPeerInfo: (NSError**) error { + // Get our peer info and send it along: + if (self->_session == nil) { + KCJoiningErrorCreate(kInternalError, error, @"Attempt to encrypt with no session"); + return nil; + } + + SOSPeerInfoRef us = [self.circleDelegate copyPeerInfoError:error]; + if (us == NULL) return nil; + CFErrorRef cfError = NULL; + NSData* piEncoded = (__bridge_transfer NSData*) SOSPeerInfoCopyEncodedData(us, NULL, &cfError); + if(us) { + CFRelease(us); + us = NULL; + } + + if (piEncoded == nil) { + if (error != nil) { + *error = (__bridge_transfer NSError*) cfError; + } + return nil; + } + + return [self->_session encrypt:piEncoded error:error]; +} + +- (nullable NSData*) encryptedInitialMessage:(NSData*)prepareMessage error:(NSError**) error { + + if (self->_session == nil) { + KCJoiningErrorCreate(kInternalError, error, @"Attempt to encrypt with no session"); + return nil; + } + + KCInitialMessageData *initialMessage = [[KCInitialMessageData alloc] init]; + [initialMessage setPrepareMessage:prepareMessage]; + + return [self->_session encrypt:initialMessage.data error:error]; +} + +- (nullable NSData*) initialMessage: (NSError**) error { + secnotice("joining", "joining: KCJoiningRequestCircleSession initialMessage called"); + +#if OCTAGON + if(KCJoiningOctagonPiggybackingEnabled() && self.piggy_version == kPiggyV2){ + __block NSData* next = nil; + __block NSError* localError = nil; + + if(!self.joiningConfiguration.epoch) { + secerror("octagon: expected epoch! returning from piggybacking."); + return nil; + } + + dispatch_semaphore_t sema = dispatch_semaphore_create(0); + //giving securityd the epoch, expecting identity message + [self.otControl rpcPrepareIdentityAsApplicantWithConfiguration:self.joiningConfiguration + reply:^(NSString *peerID, + NSData *permanentInfo, + NSData *permanentInfoSig, + NSData *stableInfo, + NSData *stableInfoSig, + NSError *err) { + if(err){ + secerror("octagon: error preparing identity: %@", err); + localError = err; + } else{ + OTPairingMessage *pairingMessage = [[OTPairingMessage alloc]init]; + OTApplicantToSponsorRound2M1 *prepareMessage = [[OTApplicantToSponsorRound2M1 alloc]init]; + prepareMessage.peerID = peerID; + prepareMessage.permanentInfo = permanentInfo; + prepareMessage.permanentInfoSig = permanentInfoSig; + prepareMessage.stableInfo = stableInfo; + prepareMessage.stableInfoSig = stableInfoSig; + + pairingMessage.prepare = prepareMessage; + next = pairingMessage.data; + } + dispatch_semaphore_signal(sema); + }]; + + if(dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 30)) != 0) { + secerror("octagon: timed out preparing identity"); + return nil; + } + if(error){ + *error = localError; + } + + NSData* encryptedPi = nil; + if (OctagonPlatformSupportsSOS()) { + secnotice("joining", "doing SOS encryptedPeerInfo"); + encryptedPi = [self encryptedPeerInfo:error]; + if (encryptedPi == nil) return nil; + } else { + secnotice("joining", "no platform support for encryptedPeerInfo"); + } + + self->_state = kExpectingCircleBlob; + NSData *encryptedInitialMessage = [self encryptedInitialMessage:next error:error]; + + return [[KCJoiningMessage messageWithType: kPeerInfo + data:encryptedInitialMessage + payload:encryptedPi + error:error] der]; + } +#endif + + NSData* encryptedPi = [self encryptedPeerInfo:error]; + if (encryptedPi == nil) return nil; + + self->_state = kExpectingCircleBlob; + + return [[KCJoiningMessage messageWithType:kPeerInfo + data:encryptedPi + error:error] der]; + +} + +- (void) attemptSosUpgrade +{ + [self.otControl attemptSosUpgrade:self.joiningConfiguration.containerName context:self.joiningConfiguration.contextID reply:^(NSError *error) { + if(error){ + secerror("pairing: failed to upgrade initiator into Octagon: %@", error); + } + }]; +} + +- (NSData*) handleCircleBlob: (KCJoiningMessage*) message error: (NSError**) error { + secnotice("joining", "joining: KCJoiningRequestCircleSession handleCircleBlob called"); + if ([message type] != kCircleBlob) { + KCJoiningErrorCreate(kUnexpectedMessage, error, @"Expected CircleBlob!"); + return nil; + } +#if OCTAGON + if(self.piggy_version == kPiggyV2 && KCJoiningOctagonPiggybackingEnabled() && message.firstData != nil){ + __block NSData* nextMessage = nil; + __block NSError* localError = nil; + dispatch_semaphore_t sema = dispatch_semaphore_create(0); + + OTPairingMessage* pairingMessage = [[OTPairingMessage alloc]initWithData:message.firstData]; + if(!pairingMessage.hasVoucher) { + secerror("octagon: expected voucher! returning from piggybacking."); + return nil; + } + OTSponsorToApplicantRound2M2 *voucher = pairingMessage.voucher; + + //handle voucher message then join octagon + [self.otControl rpcJoinWithConfiguration:self.joiningConfiguration vouchData:voucher.voucher vouchSig:voucher.voucherSignature preapprovedKeys:voucher.preapprovedKeys reply:^(NSError * _Nullable err) { + if(err){ + secerror("octagon: error joining octagon: %@", err); + localError = err; + }else{ + secnotice("octagon", "successfully joined octagon"); + } + dispatch_semaphore_signal(sema); + }]; + + if(dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 30)) != 0) { + + secerror("octagon: timed out joining octagon"); + return nil; + } + + if (OctagonPlatformSupportsSOS()) { + 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]) + return nil; + } else { + secnotice("joining", "platform doesn't support SOS"); + } + + self->_state = kRequestCircleDone; + + NSData* final = nil; + if(nextMessage == nil){ + final = [NSData data]; + } + self->_state = kRequestCircleDone; + return final; + } +#endif + NSData* circleBlob = [self.session decryptAndVerify:message.firstData error:error]; + if (circleBlob == nil) return nil; + + if (![self.circleDelegate processCircleJoinData: circleBlob version:kPiggyV1 error:error]) { + return nil; + } else { + secnotice("joining", "joined the SOS circle!"); + if(OctagonIsEnabled()) { + secnotice("joining", "kicking off SOS Upgrade into Octagon!"); + [self attemptSosUpgrade]; + } + } + self->_state = kRequestCircleDone; + + return [NSData data]; // Success, an empty message. +} + +- (NSData*) processMessage: (NSData*) incomingMessage error: (NSError**) error { + secnotice("joining", "joining: KCJoiningRequestCircleSession processMessage called"); + NSData* result = nil; + KCJoiningMessage* message = [KCJoiningMessage messageWithDER: incomingMessage error: error]; + if (message == nil) return nil; + + switch(self.state) { + case kExpectingCircleBlob: + return [self handleCircleBlob:message error:error]; + case kRequestCircleDone: + KCJoiningErrorCreate(kUnexpectedMessage, error, @"Done, no messages expected."); + break; + } + + return result; +} + +- (bool) isDone { + return self.state = kRequestCircleDone; +} + ++ (instancetype) sessionWithCircleDelegate: (NSObject*) circleDelegate + session: (KCAESGCMDuplexSession*) session + error: (NSError**) error { + return [[KCJoiningRequestCircleSession alloc] initWithCircleDelegate:circleDelegate + session:session + error:error]; +} + +- (instancetype) initWithCircleDelegate: (NSObject*) circleDelegate + session: (KCAESGCMDuplexSession*) session + error: (NSError**) error { + return [self initWithCircleDelegate:circleDelegate + session:session + otcontrol:[OTControl controlObject:true error:error] + error:error]; +} + +- (instancetype)initWithCircleDelegate:(NSObject*)circleDelegate + session:(KCAESGCMDuplexSession*) session + otcontrol:(OTControl*)otcontrol + 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 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; +#else + self->_piggy_version = kPiggyV1; +#endif + + return self; +} + +@end + diff --git a/KeychainCircle/KCJoiningRequestSecretSession.m b/KeychainCircle/KCJoiningRequestSecretSession.m new file mode 100644 index 000000000..f251465c4 --- /dev/null +++ b/KeychainCircle/KCJoiningRequestSecretSession.m @@ -0,0 +1,399 @@ +// +// KCJoiningSession.m +// Security +// +// + +#import + +#import + +#import +#import +#import + +#import + +#include +#include +#include +#include +#include +#import +#include + +#if OCTAGON +#import +#import "keychain/ot/OTControl.h" +#import "keychain/ot/OTControlProtocol.h" +#import "keychain/ot/OctagonControlServer.h" +#import "keychain/ot/OTJoiningConfiguration.h" +#import "KeychainCircle/KCJoiningRequestSession+Internal.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/OTPairingMessage.h" +#endif +#import + +typedef enum { + kExpectingB, + kExpectingHAMK, + kRequestSecretDone +} KCJoiningRequestSecretSessionState; + +#if OCTAGON +static bool KCJoiningOctagonPiggybackingDefault = false; +bool KCSetJoiningOctagonPiggybackingEnabled(bool value) +{ + KCJoiningOctagonPiggybackingDefault = value; + return value; +} + +// defaults write com.apple.security.octagon enable -bool YES +bool KCJoiningOctagonPiggybackingEnabled() { + bool result = KCJoiningOctagonPiggybackingDefault ? KCJoiningOctagonPiggybackingDefault : OctagonIsEnabled(); + secnotice("octagon", "Octagon Piggybacking is %@ ", result ? @"on" : @"off"); + return result; +} +#endif + + +@interface KCJoiningRequestSecretSession () +@property (readonly) NSObject* secretDelegate; +@property (readonly) KCSRPClientContext* context; +@property (readonly) uint64_t dsid; +@property (readonly) KCJoiningRequestSecretSessionState state; +@property (readwrite) NSString* piggy_uuid; +@property (readwrite) uint64_t piggy_version; +@property (readwrite) uint64_t epoch; +@property (readwrite) NSData* challenge; +@property (readwrite) NSData* salt; +#if OCTAGON +@property (nonatomic, strong) OTJoiningConfiguration* joiningConfiguration; +@property (nonatomic, strong) OTControl *otControl; +#endif +@property (nonatomic, strong) NSMutableDictionary *defaults; +@end + +@implementation KCJoiningRequestSecretSession : NSObject + + +- (nullable NSData*) createUUID +{ + NSUUID *uuid = [NSUUID UUID]; + uuid_t uuidBytes; + + self.piggy_uuid = [uuid UUIDString]; + [uuid getUUIDBytes:uuidBytes]; + NSData *uuidData = [NSData dataWithBytes:uuidBytes length:sizeof(uuid_t)]; + return uuidData; +} + +- (nullable NSData*) initialMessage: (NSError**) error { + NSData* start = [self->_context copyStart: error]; + if (start == nil) return nil; + + NSMutableData* initialMessage = NULL; + secnotice("joining", "joining: KCJoiningRequestSecretSession initialMessage called"); + + if(self.piggy_version == kPiggyV2){ +#if OCTAGON + if(KCJoiningOctagonPiggybackingEnabled()){ + NSData* uuidData = [self createUUID]; + + NSString* version = @"o"; + NSData* octagonVersion = [version dataUsingEncoding:kCFStringEncodingUTF8]; + + initialMessage = [NSMutableData dataWithLength: sizeof_initialmessage_version2(start, kPiggyV1, uuidData, octagonVersion)]; + + if (NULL == encode_initialmessage_version2(start, uuidData, octagonVersion, error, initialMessage.mutableBytes, initialMessage.mutableBytes + initialMessage.length)){ + secerror("failed to create version 2 message"); + return nil; + } + } +#endif + } + else if(self.piggy_version == kPiggyV1){ + NSData* uuidData = [self createUUID]; + initialMessage = [NSMutableData dataWithLength: sizeof_initialmessage_version1(start, kPiggyV1, uuidData)]; + + if (NULL == encode_initialmessage_version1(start, uuidData, kPiggyV1, error, initialMessage.mutableBytes, initialMessage.mutableBytes + initialMessage.length)){ + secerror("failed to create version 1 message: %@", *error); + return nil; + } + } + else{ + initialMessage = [NSMutableData dataWithLength: sizeof_initialmessage(start)]; + if (NULL == encode_initialmessage(start, error, initialMessage.mutableBytes, initialMessage.mutableBytes + initialMessage.length)){ + return nil; + } + } + + return initialMessage; +} + +- (bool) isDone { + return self->_state == kRequestSecretDone; +} + +- (bool) setupSession: (NSError**) error { + NSData* key = [self->_context getKey]; + + if (key == nil) { + KCJoiningErrorCreate(kInternalError, error, @"No session key available"); + return nil; + } + + self->_session = [KCAESGCMDuplexSession sessionAsSender:key context:self.dsid]; + self.session.pairingUUID = self.joiningConfiguration.pairingUUID; + self.session.piggybackingVersion = self.piggy_version; + + return self.session != nil; +} + +- (nullable NSData*) copyResponseForChallenge:(NSData*) challenge + salt:(NSData*) salt + secret: (NSString*) password + error: (NSError**) error { + + secnotice("joining", "joining: KCJoiningRequestSecretSession copyResponseForChallenge called"); + NSData* response = [self->_context copyResposeToChallenge:challenge + password:password + salt:salt + error:error]; + + if (!response) { + // @@@ return error to other side??? + return nil; + } else { + if (![self setupSession: error]) return nil; + + self.challenge = challenge; + self.salt = salt; + + self->_state = kExpectingHAMK; + return [[KCJoiningMessage messageWithType:kResponse + data:response + error:error] der]; + } +} + + +- (nullable NSData*) copyResponseForSecret: (NSString*) password + error: (NSError**) error { + return [self copyResponseForChallenge:self.challenge salt:self.salt secret:password error:error]; +} + +- (nullable NSData*) handleChallengeData: (NSData*) challengeData + secret: (NSString*) password + error: (NSError**) error { + secnotice("joining", "joining: KCJoiningRequestSecretSession handleChallengeData called"); + NSData* challenge = nil; + NSData* salt = nil; + + if (![challengeData decodeSequenceData:&salt data:&challenge error:error]) return nil; + + return [self copyResponseForChallenge:challenge salt:salt secret:password error:error]; + +} + +- (nullable NSData*) handleChallenge: (KCJoiningMessage*) message + secret: (NSString*) password + error: (NSError**)error { + secnotice("joining", "joining: KCJoiningRequestSecretSession handleChallenge called"); + // Parse the challenge message + // Salt and Challenge packet + if ([message type] != kChallenge) { + KCJoiningErrorCreate(kUnexpectedMessage, error, @"Expected challenge!"); + return nil; + } +#if OCTAGON + //handle octagon data if it exists + 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){ + OTPairingMessage* pairingMessage = [[OTPairingMessage alloc]initWithData: [message secondData]]; + + if(pairingMessage.epoch.epoch){ + secnotice("octagon", "received epoch"); + self.epoch = pairingMessage.epoch.epoch; + } + else{ + secerror("octagon: acceptor did not send its epoch. discontinuing octagon protocol. downgrading to verison 1"); + self.piggy_version = kPiggyV1; + } + } + }else{ + self.piggy_version = kPiggyV1; + } +#endif + return [self handleChallengeData:[message firstData] secret:password error:error]; +} + +- (NSData*) handleChallenge: (KCJoiningMessage*) message error: (NSError**)error { + return [self handleChallenge:message + secret:[self.secretDelegate secret] + error:error]; + +} + +- (NSData*) handleVerification: (KCJoiningMessage*) message error: (NSError**) error { + secnotice("joining", "joining: KCJoiningRequestSecretSession handleVerification called"); + if ([message type] == kError) { + bool newCode = [[message firstData] length] == 0; + NSString* nextSecret = [self.secretDelegate verificationFailed: newCode]; + + if (nextSecret) { + if (newCode) { + return [self copyResponseForSecret:nextSecret error:error]; + } else { + return [self handleChallengeData:[message firstData] secret:nextSecret error:error]; + } + } else { + return nil; + } + } + + if ([message type] != kVerification) { + KCJoiningErrorCreate(kUnexpectedMessage, error, @"Expected verification!"); + return nil; + } + + if (![self.context verifyConfirmation:[message firstData] error:error]) { + // Sender thought we had it right, but he can't prove he has it right! + KCJoiningErrorCreate(kInternalError, error, @"Got verification but acceptor doesn't have matching secret: %@", self); + secnotice("request-session", "Verification failed: %@", self); + return nil; + } + + { + NSData* payload = [self.session decryptAndVerify:[message secondData] error:error]; + if (payload == nil) return nil; + + NSString* accountCode = [NSString decodeFromDER:payload error:error]; + if (accountCode == nil) return nil; + + if (![self.secretDelegate processAccountCode:accountCode error:error]) return nil; + } + + self->_state = kRequestSecretDone; + + return [NSData data]; +} + +- (NSData*) processMessage: (NSData*) incomingMessage error: (NSError**) error { + secnotice("joining", "joining: KCJoiningRequestSecretSession processMessage called"); + NSData* result = nil; + KCJoiningMessage* message = [KCJoiningMessage messageWithDER: incomingMessage error: error]; + if (message == nil) return nil; + + switch(self->_state) { + case kExpectingB: + return [self handleChallenge:message error: error]; + break; + case kExpectingHAMK: + return [self handleVerification:message error:error]; + break; + case kRequestSecretDone: + KCJoiningErrorCreate(kUnexpectedMessage, error, @"Done, no messages expected."); + break; + } + + return result; +} + ++ (nullable instancetype)sessionWithSecretDelegate: (NSObject*) secretDelegate + dsid: (uint64_t)dsid + error: (NSError**) error { + return [[KCJoiningRequestSecretSession alloc] initWithSecretDelegate:secretDelegate + dsid:dsid + error:error]; +} + +- (nullable instancetype)initWithSecretDelegate: (NSObject*) secretDelegate + dsid: (uint64_t)dsid + error: (NSError**)error { + int cc_error = 0; + struct ccrng_state * rng = ccrng(&cc_error); + + if (rng == nil) { + CoreCryptoError(cc_error, error, @"RNG fetch failed"); + return nil; + } + + return [self initWithSecretDelegate: secretDelegate + dsid: dsid + rng: rng + error: error]; +} + +- (nullable instancetype)initWithSecretDelegate: (NSObject*) secretDelegate + dsid: (uint64_t)dsid + 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 OCTAGON + self->_piggy_version = KCJoiningOctagonPiggybackingEnabled() ? kPiggyV2 : kPiggyV1; + self->_otControl = [OTControl controlObject:true error:error]; + self->_joiningConfiguration = [[OTJoiningConfiguration alloc]initWithProtocolType:OTProtocolPiggybacking + uniqueDeviceID:@"requester-id" + uniqueClientID:@"requester-id" + containerName:nil + contextID:OTDefaultContext + epoch:0 + isInitiator:true]; +#else + self->_piggy_version = kPiggyV1; +#endif + + secnotice("joining", "joining: initWithSecretDelegate called, uuid=%@", self.joiningConfiguration.pairingUUID); + + NSString* name = [NSString stringWithFormat: @"%llu", dsid]; + + self->_context = [[KCSRPClientContext alloc] initWithUser: name + digestInfo: ccsha256_di() + group: ccsrp_gp_rfc5054_3072() + randomSource: rng]; + + return self; +} + +- (NSString*) stateString { + switch (self.state) { + case kExpectingB: return @"→B"; + case kExpectingHAMK: return @"→HAMK"; + case kRequestSecretDone: return @"SecretDone"; + default: return [NSString stringWithFormat:@"%d", self.state]; + } +} + +- (NSString *)description { + return [NSString stringWithFormat: @"", self, self.dsid, [self stateString], self.context]; +} +#if OCTAGON +/* for test */ +-(void)setControlObject:(OTControl*)control +{ + self.otControl = control; +} + +- (void)setConfiguration:(OTJoiningConfiguration *)config +{ + self.joiningConfiguration = config; +} +#endif + +@end diff --git a/KeychainCircle/KCJoiningRequestSession+Internal.h b/KeychainCircle/KCJoiningRequestSession+Internal.h new file mode 100644 index 000000000..917529c33 --- /dev/null +++ b/KeychainCircle/KCJoiningRequestSession+Internal.h @@ -0,0 +1,44 @@ +/* + * 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 + +#ifndef KCJoiningRequestSession_Internal_h +#define KCJoiningRequestSession_Internal_h + +#import +#import "keychain/ot/OTControl.h" +#import "KCJoiningSession.h" + +@interface KCJoiningRequestSecretSession (Internal) +- (void)setControlObject:(OTControl*)control; +- (void)setConfiguration:(OTJoiningConfiguration *)config; +@end + +@interface KCJoiningRequestCircleSession (Internal) + +- (void)setControlObject:(OTControl*)control; +- (void)setJoiningConfigurationObject:(OTJoiningConfiguration *)config; +@end +#endif /* Header_h */ +#endif diff --git a/KeychainCircle/KCJoiningRequestSession.m b/KeychainCircle/KCJoiningRequestSession.m deleted file mode 100644 index 731a11c80..000000000 --- a/KeychainCircle/KCJoiningRequestSession.m +++ /dev/null @@ -1,392 +0,0 @@ -// -// KCJoiningSession.m -// Security -// -// - -#import - -#import - -#import -#import -#import - -#import - -#include -#include -#include -#include -#include - -#include - -#import - -typedef enum { - kExpectingB, - kExpectingHAMK, - kRequestSecretDone -} KCJoiningRequestSecretSessionState; - -typedef enum { - kExpectingCircleBlob, - kRequestCircleDone -} KCJoiningRequestCircleSessionState; - - -@interface KCJoiningRequestSecretSession () -@property (readonly) NSObject* secretDelegate; -@property (readonly) KCSRPClientContext* context; -@property (readonly) uint64_t dsid; -@property (readonly) KCJoiningRequestSecretSessionState state; -@property (readwrite) NSString* piggy_uuid; -@property (readwrite) uint64_t piggy_version; -@property (readwrite) NSData* challenge; -@property (readwrite) NSData* salt; -@end - -static const uint64_t KCProtocolVersion = kPiggyV1; - -@implementation KCJoiningRequestSecretSession : NSObject - -- (nullable NSData*) initialMessage: (NSError**) error { - NSData* start = [self->_context copyStart: error]; - if (start == nil) return nil; - - NSMutableData* initialMessage = NULL; - - - if(KCProtocolVersion == kPiggyV1) - { - NSUUID *uuid = [NSUUID UUID]; - uuid_t uuidBytes; - - self.piggy_uuid = [uuid UUIDString]; - [uuid getUUIDBytes:uuidBytes]; - NSData *uuidData = [NSData dataWithBytes:uuidBytes length:sizeof(uuid_t)]; - - initialMessage = [NSMutableData dataWithLength: sizeof_initialmessage_version1(start, KCProtocolVersion, uuidData)]; - - if (NULL == encode_initialmessage_version1(start, uuidData, KCProtocolVersion, error, initialMessage.mutableBytes, initialMessage.mutableBytes + initialMessage.length)) - return nil; - } - else{ - initialMessage = [NSMutableData dataWithLength: sizeof_initialmessage(start)]; - if (NULL == encode_initialmessage(start, error, initialMessage.mutableBytes, initialMessage.mutableBytes + initialMessage.length)) - return nil; - } - - return initialMessage; -} - -- (bool) isDone { - return self->_state == kRequestSecretDone; -} - -- (bool) setupSession: (NSError**) error { - NSData* key = [self->_context getKey]; - - if (key == nil) { - KCJoiningErrorCreate(kInternalError, error, @"No session key available"); - return nil; - } - - self->_session = [KCAESGCMDuplexSession sessionAsSender:key context:self.dsid]; - - return self.session != nil; -} - -- (nullable NSData*) copyResponseForChallenge:(NSData*) challenge - salt:(NSData*) salt - secret: (NSString*) password - error: (NSError**) error { - NSData* response = [self->_context copyResposeToChallenge:challenge - password:password - salt:salt - error:error]; - - if (!response) { - // @@@ return error to other side??? - return nil; - } else { - if (![self setupSession: error]) return nil; - - self.challenge = challenge; - self.salt = salt; - - self->_state = kExpectingHAMK; - return [[KCJoiningMessage messageWithType:kResponse - data:response - error:error] der]; - } -} - - -- (nullable NSData*) copyResponseForSecret: (NSString*) password - error: (NSError**) error { - return [self copyResponseForChallenge:self.challenge salt:self.salt secret:password error:error]; -} - -- (nullable NSData*) handleChallengeData: (NSData*) challengeData - secret: (NSString*) password - error: (NSError**) error { - NSData* challenge = nil; - NSData* salt = nil; - - if (![challengeData decodeSequenceData:&salt data:&challenge error:error]) return nil; - - return [self copyResponseForChallenge:challenge salt:salt secret:password error:error]; - -} - -- (nullable NSData*) handleChallenge: (KCJoiningMessage*) message - secret: (NSString*) password - error: (NSError**)error { - // Parse the challenge message - // Salt and Challenge packet - if ([message type] != kChallenge) { - KCJoiningErrorCreate(kUnexpectedMessage, error, @"Expected challenge!"); - return nil; - } - - return [self handleChallengeData:[message firstData] secret:password error:error]; -} - -- (NSData*) handleChallenge: (KCJoiningMessage*) message error: (NSError**)error { - return [self handleChallenge:message - secret:[self.secretDelegate secret] - error:error]; - -} - -- (NSData*) handleVerification: (KCJoiningMessage*) message error: (NSError**) error { - if ([message type] == kError) { - bool newCode = [[message firstData] length] == 0; - NSString* nextSecret = [self.secretDelegate verificationFailed: newCode]; - - if (nextSecret) { - if (newCode) { - return [self copyResponseForSecret:nextSecret error:error]; - } else { - return [self handleChallengeData:[message firstData] secret:nextSecret error:error]; - } - } else { - return nil; - } - } - - if ([message type] != kVerification) { - KCJoiningErrorCreate(kUnexpectedMessage, error, @"Expected verification!"); - return nil; - } - - if (![self.context verifyConfirmation:[message firstData] error:error]) { - // Sender thought we had it right, but he can't prove he has it right! - KCJoiningErrorCreate(kInternalError, error, @"Got verification but acceptor doesn't have matching secret: %@", self); - secnotice("request-session", "Verification failed: %@", self); - return nil; - } - - { - NSData* payload = [self.session decryptAndVerify:[message secondData] error:error]; - if (payload == nil) return nil; - - NSString* accountCode = [NSString decodeFromDER:payload error:error]; - if (accountCode == nil) return nil; - - if (![self.secretDelegate processAccountCode:accountCode error:error]) return nil; - } - - self->_state = kRequestSecretDone; - - return [NSData data]; -} - - - - -// [self.delegate processCircleJoinData:circleData error:error]; - -- (NSData*) processMessage: (NSData*) incomingMessage error: (NSError**) error { - NSData* result = nil; - KCJoiningMessage* message = [KCJoiningMessage messageWithDER: incomingMessage error: error]; - if (message == nil) return nil; - - switch(self->_state) { - case kExpectingB: - return [self handleChallenge:message error: error]; - break; - case kExpectingHAMK: - return [self handleVerification:message error:error]; - break; - case kRequestSecretDone: - KCJoiningErrorCreate(kUnexpectedMessage, error, @"Done, no messages expected."); - break; - } - - return result; -} - -+ (nullable instancetype)sessionWithSecretDelegate: (NSObject*) secretDelegate - dsid: (uint64_t)dsid - error: (NSError**) error { - return [[KCJoiningRequestSecretSession alloc] initWithSecretDelegate:secretDelegate - dsid:dsid - error:error]; -} - -- (nullable instancetype)initWithSecretDelegate: (NSObject*) secretDelegate - dsid: (uint64_t)dsid - error: (NSError**)error { - int cc_error = 0; - struct ccrng_state * rng = ccrng(&cc_error); - - if (rng == nil) { - CoreCryptoError(cc_error, error, @"RNG fetch failed"); - return nil; - } - - return [self initWithSecretDelegate: secretDelegate - dsid: dsid - rng: rng - error: error]; -} - -- (nullable instancetype)initWithSecretDelegate: (NSObject*) secretDelegate - dsid: (uint64_t)dsid - rng: (struct ccrng_state *)rng - error: (NSError**)error { - - self = [super init]; - - self->_secretDelegate = secretDelegate; - self->_state = kExpectingB; - self->_dsid = dsid; - - NSString* name = [NSString stringWithFormat: @"%llu", dsid]; - - self->_context = [[KCSRPClientContext alloc] initWithUser: name - digestInfo: ccsha256_di() - group: ccsrp_gp_rfc5054_3072() - randomSource: rng]; - - return self; -} - -- (NSString*) stateString { - switch (self.state) { - case kExpectingB: return @"→B"; - case kExpectingHAMK: return @"→HAMK"; - case kRequestSecretDone: return @"SecretDone"; - default: return [NSString stringWithFormat:@"%d", self.state]; - } -} - -- (NSString *)description { - return [NSString stringWithFormat: @"", self, self.dsid, [self stateString], self.context]; -} - -@end - -@interface KCJoiningRequestCircleSession () -@property (readonly) NSObject* circleDelegate; -@property (readonly) KCAESGCMDuplexSession* session; -@property (readwrite) KCJoiningRequestCircleSessionState state; -@end - -@implementation KCJoiningRequestCircleSession -- (nullable NSData*) encryptedPeerInfo: (NSError**) error { - // Get our peer info and send it along: - if (self->_session == nil) { - KCJoiningErrorCreate(kInternalError, error, @"Attempt to encrypt with no session"); - return nil; - } - - SOSPeerInfoRef us = [self.circleDelegate copyPeerInfoError:error]; - if (us == NULL) return nil; - CFErrorRef cfError = NULL; - NSData* piEncoded = (__bridge_transfer NSData*) SOSPeerInfoCopyEncodedData(us, NULL, &cfError); - - if (piEncoded == nil) { - if (error != nil) { - *error = (__bridge_transfer NSError*) cfError; - } - return nil; - } - - return [self->_session encrypt:piEncoded error:error]; -} - -- (nullable NSData*) initialMessage: (NSError**) error { - NSData* encryptedPi = [self encryptedPeerInfo:error]; - if (encryptedPi == nil) return nil; - - self->_state = kExpectingCircleBlob; - - return [[KCJoiningMessage messageWithType:kPeerInfo - data:encryptedPi - error:error] der]; - -} - -- (NSData*) handleCircleBlob: (KCJoiningMessage*) message error: (NSError**) error { - if ([message type] != kCircleBlob) { - KCJoiningErrorCreate(kUnexpectedMessage, error, @"Expected CircleBlob!"); - return nil; - } - - NSData* circleBlob = [self.session decryptAndVerify:message.firstData error:error]; - if (circleBlob == nil) return nil; - - if (![self.circleDelegate processCircleJoinData: circleBlob version:kPiggyV1 error:error]) - return nil; - - self->_state = kRequestCircleDone; - - return [NSData data]; // Success, an empty message. -} - -- (NSData*) processMessage: (NSData*) incomingMessage error: (NSError**) error { - NSData* result = nil; - KCJoiningMessage* message = [KCJoiningMessage messageWithDER: incomingMessage error: error]; - if (message == nil) return nil; - - switch(self.state) { - case kExpectingCircleBlob: - return [self handleCircleBlob:message error:error]; - case kRequestCircleDone: - KCJoiningErrorCreate(kUnexpectedMessage, error, @"Done, no messages expected."); - break; - } - - return result; -} - -- (bool) isDone { - return self.state = kRequestCircleDone; -} - -+ (instancetype) sessionWithCircleDelegate: (NSObject*) circleDelegate - session: (KCAESGCMDuplexSession*) session - error: (NSError**) error { - return [[KCJoiningRequestCircleSession alloc] initWithCircleDelegate:circleDelegate - session:session - error:error]; -} - -- (instancetype) initWithCircleDelegate: (NSObject*) circleDelegate - session: (KCAESGCMDuplexSession*) session - error: (NSError**) error { - self = [super init]; - - self->_circleDelegate = circleDelegate; - self->_session = session; - self.state = kExpectingCircleBlob; - - return self; -} - -@end - diff --git a/KeychainCircle/KCJoiningSession.h b/KeychainCircle/KCJoiningSession.h index 5c251ed57..f94064a07 100644 --- a/KeychainCircle/KCJoiningSession.h +++ b/KeychainCircle/KCJoiningSession.h @@ -9,9 +9,13 @@ #include #include + +bool KCJoiningOctagonPiggybackingEnabled(void); +bool KCSetJoiningOctagonPiggybackingEnabled(bool value); + NS_ASSUME_NONNULL_BEGIN -@protocol KCJoiningRequestCircleDelegate +@protocol KCJoiningRequestCircleDelegate /*! Get this devices peer info (As Application) @@ -34,7 +38,7 @@ NS_ASSUME_NONNULL_BEGIN @end -@protocol KCJoiningRequestSecretDelegate +@protocol KCJoiningRequestSecretDelegate /*! Get the shared secret for this session. Not called during creation or initialMessage: to allow the initial message to be sent before @@ -88,7 +92,7 @@ NS_ASSUME_NONNULL_BEGIN @end - +@class OTControl; @interface KCJoiningRequestCircleSession : NSObject - (bool) isDone; @@ -102,13 +106,19 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype) initWithCircleDelegate: (NSObject*) circleDelegate session: (KCAESGCMDuplexSession*) session - error: (NSError**) error NS_DESIGNATED_INITIALIZER; + error: (NSError**) error; + + +- (instancetype)initWithCircleDelegate:(NSObject*) circleDelegate + session:(KCAESGCMDuplexSession*) session + otcontrol:(OTControl*)otcontrol + error:(NSError**) error NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE; @end -@protocol KCJoiningAcceptCircleDelegate +@protocol KCJoiningAcceptCircleDelegate /*! Handle the request's peer info and get the blob they can use to get in circle @param peer @@ -137,7 +147,7 @@ typedef enum { kKCRetryWithNewChallenge } KCRetryOrNot; -@protocol KCJoiningAcceptSecretDelegate +@protocol KCJoiningAcceptSecretDelegate /*! Get the shared secret for this session @result diff --git a/KeychainCircle/KCSRPContext.m b/KeychainCircle/KCSRPContext.m index 8686fdcd5..3d9d8a8ec 100644 --- a/KeychainCircle/KCSRPContext.m +++ b/KeychainCircle/KCSRPContext.m @@ -61,6 +61,8 @@ - (instancetype) initWithUser: (NSString*) user return self; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" - (void) finalize { ccsrp_ctx_clear(ccsrp_ctx_di(self.context), ccsrp_ctx_gp(self.context), @@ -68,6 +70,7 @@ - (void) finalize { free(self.context); } +#pragma clang diagnostic pop - (NSData*) getKey { size_t key_length = 0; diff --git a/KeychainCircle/PairingChannel.h b/KeychainCircle/PairingChannel.h index 66522092c..6f65dd6fc 100644 --- a/KeychainCircle/PairingChannel.h +++ b/KeychainCircle/PairingChannel.h @@ -11,16 +11,35 @@ extern NSString *kKCPairingChannelErrorDomain; #define KCPairingErrorNoControlChannel 1 #define KCPairingErrorTooManySteps 2 #define KCPairingErrorAccountCredentialMissing 3 +#define KCPairingErrorOctagonMessageMissing 4 +#define KCPairingErrorTypeConfusion 5 +#define KCPairingErrorNoTrustAvailable 6 +#define KCPairingErrorNoStashedCredential 7 typedef void(^KCPairingChannelCompletion)(BOOL complete, NSData *packet, NSError *error); -@interface KCPairingChannelContext : NSObject +typedef NSString* KCPairingIntent_Type NS_STRING_ENUM; +extern KCPairingIntent_Type KCPairingIntent_Type_None; +extern KCPairingIntent_Type KCPairingIntent_Type_SilentRepair; +extern KCPairingIntent_Type KCPairingIntent_Type_UserDriven; + +@interface KCPairingChannelContext : NSObject @property (strong) NSString *model; @property (strong) NSString *modelVersion; @property (strong) NSString *modelClass; @property (strong) NSString *osVersion; +@property (strong) NSString *uniqueDeviceID; +@property (strong) NSString *uniqueClientID; +@property (strong) KCPairingIntent_Type intent; @end +/** + * Pairing channel provides the channel used in OOBE / D2D and HomePod/AppleTV (TapToFix) setup. + * + * The initiator is the device that wants to get into the circle, the acceptor is the device that is already in. + * The interface require the caller to hold a lock assertion over the whole transaction, both on the initiator and acceptor. +*/ + @interface KCPairingChannel : NSObject @property (assign,readonly) BOOL needInitialSync; @@ -28,12 +47,19 @@ typedef void(^KCPairingChannelCompletion)(BOOL complete, NSData *packet, NSError + (instancetype)pairingChannelInitiator:(KCPairingChannelContext *)peerVersionContext; + (instancetype)pairingChannelAcceptor:(KCPairingChannelContext *)peerVersionContext; -- (instancetype)initAsInitiator:(bool)initator version:(KCPairingChannelContext *)peerVersionContext; +- (instancetype)initAsInitiator:(bool)initiator version:(KCPairingChannelContext *)peerVersionContext; - (void)validateStart:(void(^)(bool result, NSError *error))complete; - (NSData *)exchangePacket:(NSData *)data complete:(bool *)complete error:(NSError **)error; +- (void)exchangePacket:(NSData *)inputCompressedData complete:(KCPairingChannelCompletion)complete; /* async version of above */ /* for tests cases only */ - (void)setXPCConnectionObject:(NSXPCConnection *)connection; +- (void)setControlObject:(id)control; +- (void)setConfiguration:(id)config; +- (void)setSOSMessageFailForTesting:(BOOL)value; +- (void)setOctagonMessageFailForTesting:(BOOL)value; ++ (bool)isSupportedPlatform; +- (void)setSessionSupportsOctagonForTesting:(bool)value; @end diff --git a/KeychainCircle/PairingChannel.m b/KeychainCircle/PairingChannel.m index 166ad460c..e2d2b6771 100644 --- a/KeychainCircle/PairingChannel.m +++ b/KeychainCircle/PairingChannel.m @@ -11,31 +11,115 @@ #import #import #import +#import +#import "keychain/ot/OTManager.h" +#import "keychain/ot/OctagonControlServer.h" +#import "keychain/ot/OTControl.h" +#import "keychain/ot/OctagonControlServer.h" +#import "keychain/ot/OTJoiningConfiguration.h" +#import "keychain/ot/proto/generated_source/OTPairingMessage.h" +#import "keychain/ot/proto/generated_source/OTSOSMessage.h" +#import "keychain/ot/proto/generated_source/OTApplicantToSponsorRound2M1.h" +#import "keychain/ot/proto/generated_source/OTSponsorToApplicantRound2M2.h" +#import "keychain/ot/proto/generated_source/OTSponsorToApplicantRound1M2.h" +#import "keychain/ot/proto/generated_source/OTPairingMessage.h" +#include #import -#if TARGET_OS_EMBEDDED +#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR #import #endif -#import "SecADWrapper.h" +#import "utilities/SecADWrapper.h" + +KCPairingIntent_Type KCPairingIntent_Type_None = @"none"; +KCPairingIntent_Type KCPairingIntent_Type_SilentRepair = @"repair"; +KCPairingIntent_Type KCPairingIntent_Type_UserDriven = @"userdriven"; typedef void(^KCPairingInternalCompletion)(BOOL complete, NSDictionary *outdict, NSError *error); typedef void(^KCNextState)(NSDictionary *indict, KCPairingInternalCompletion complete); NSString *kKCPairingChannelErrorDomain = @"com.apple.security.kcparingchannel"; +const char* pairingScope = "ot-pairing"; + +typedef void(^OTPairingInternalCompletion)(BOOL complete, NSData * _Nullable outData, NSError * _Nullable error); +typedef void(^OTNextState)(NSData *inData, OTPairingInternalCompletion complete); + @implementation KCPairingChannelContext + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object +{ + KCPairingChannelContext *other = (KCPairingChannelContext *)object; + + return [other isMemberOfClass:[self class]] + && ((!self->_model && !other->_model) || [self->_model isEqual:other->_model]) + && ((!self->_modelVersion && !other->_modelVersion) || [self->_modelVersion isEqual:other->_modelVersion]) + && ((!self->_modelClass && !other->_modelClass) || [self->_modelClass isEqual:other->_modelClass]) + && ((!self->_osVersion && !other->_osVersion) || [self->_osVersion isEqual:other->_osVersion]) + && ((!self->_uniqueDeviceID && !other->_uniqueDeviceID) || [self->_uniqueDeviceID isEqual:other->_uniqueDeviceID]) + && ((!self->_uniqueClientID && !other->_uniqueClientID) || [self->_uniqueClientID isEqual:other->_uniqueClientID]) + && ((!self->_intent && !other->_intent) || [self->_intent isEqual:other->_intent]) + ; +} + +- (void)encodeWithCoder:(NSCoder *)coder { + [coder encodeObject:_model forKey:@"model"]; + [coder encodeObject:_modelVersion forKey:@"modelVersion"]; + [coder encodeObject:_modelClass forKey:@"modelClass"]; + [coder encodeObject:_osVersion forKey:@"osVersion"]; + [coder encodeObject:_uniqueDeviceID forKey:@"uniqueDeviceID"]; + [coder encodeObject:_uniqueClientID forKey:@"uniqueClientID"]; + [coder encodeObject:_intent forKey:@"intent"]; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)decoder +{ + self = [super init]; + if (self) { + _model = [decoder decodeObjectOfClass:[NSString class] forKey:@"model"]; + _modelVersion = [decoder decodeObjectOfClass:[NSString class] forKey:@"modelVersion"]; + _modelClass = [decoder decodeObjectOfClass:[NSString class] forKey:@"modelClass"]; + _osVersion = [decoder decodeObjectOfClass:[NSString class] forKey:@"osVersion"]; + _uniqueDeviceID = [decoder decodeObjectOfClass:[NSString class] forKey:@"uniqueDeviceID"]; + _uniqueClientID = [decoder decodeObjectOfClass:[NSString class] forKey:@"uniqueClientID"]; + _intent = [decoder decodeObjectOfClass:[NSString class] forKey:@"intent"]; + + /* validate intent if we have one */ + if (_intent != NULL && + !([_intent isEqualToString:KCPairingIntent_Type_None] || + [_intent isEqualToString:KCPairingIntent_Type_SilentRepair] || + [_intent isEqualToString:KCPairingIntent_Type_UserDriven])) + { + return nil; + } + } + return self; +} + @end @interface KCPairingChannel () @property (assign) KCPairingChannelContext *peerVersionContext; -@property (assign) bool initator; +@property (assign) bool initiator; @property (assign) unsigned counter; @property (assign) bool acceptorWillSendInitialSyncCredentials; @property (strong) NSXPCConnection *connection; - +@property (strong) OTControl *otControl; +@property (strong) NSString* contextID; +@property (strong) OTNextState nextOctagonState; @property (strong) KCNextState nextState; +@property (nonatomic, strong) OTJoiningConfiguration* joiningConfiguration; +@property (nonatomic) bool testFailSOS; +@property (nonatomic) bool testFailOctagon; + +@property (assign) bool sessionSupportsSOS; +@property (assign) bool sessionSupportsOctagon; @end @@ -51,18 +135,20 @@ + (instancetype)pairingChannelAcceptor:(KCPairingChannelContext *)peerVersionCon return [[KCPairingChannel alloc] initAsInitiator:false version:peerVersionContext]; } -- (instancetype)initAsInitiator:(bool)initator version:(KCPairingChannelContext *)peerVersionContext +- (instancetype)initAsInitiator:(bool)initiator version:(KCPairingChannelContext *)peerVersionContext { - if (![KCPairingChannel isSupportedPlatform]) + if (![KCPairingChannel isSupportedPlatform]) { + secerror("platform not supported for pairing"); return NULL; + } if (self = [super init]) { __weak typeof(self) weakSelf = self; - _initator = initator; + _initiator = initiator; _peerVersionContext = peerVersionContext; - if (_initator) { + if (_initiator) { _nextState = ^(NSDictionary *nsdata, KCPairingInternalCompletion kscomplete){ - [weakSelf initatorFirstPacket:nsdata complete:kscomplete]; + [weakSelf initiatorFirstPacket:nsdata complete:kscomplete]; }; } else { _nextState = ^(NSDictionary *nsdata, KCPairingInternalCompletion kscomplete){ @@ -70,21 +156,30 @@ - (instancetype)initAsInitiator:(bool)initator version:(KCPairingChannelContext }; } _needInitialSync = true; + _testFailSOS = false; + _contextID = OTDefaultContext; + + /* only apply to acceptor right now */ + _sessionSupportsSOS = OctagonPlatformSupportsSOS(); + _sessionSupportsOctagon = OctagonIsEnabled(); + NSError *localError = nil; + _otControl = [OTControl controlObject:true error:&localError]; + if(localError){ + secerror("could not stand up otcontrol connection"); + } + _joiningConfiguration = [[OTJoiningConfiguration alloc]initWithProtocolType:OTProtocolPairing + uniqueDeviceID:peerVersionContext.uniqueDeviceID + uniqueClientID:peerVersionContext.uniqueClientID + containerName:nil + contextID:OTDefaultContext + epoch:0 + isInitiator:initiator]; } return self; } + (bool)isSupportedPlatform { - CFStringRef deviceClass = NULL; -#if TARGET_OS_EMBEDDED && !RC_HIDE_HARDWARE_WINTER_2017_IOS - deviceClass = MGCopyAnswer(kMGQDeviceClass, NULL); - if (deviceClass && CFEqual(deviceClass, kMGDeviceClassAudioAccessory)){ - CFReleaseNull(deviceClass); - return false; - } -#endif - CFReleaseNull(deviceClass); return true; } @@ -160,117 +255,273 @@ - (NSData *)decompressData:(NSData *)data //MARK: - Initiator -- (void)initatorFirstPacket:(NSDictionary * __unused)indata complete:(KCPairingInternalCompletion)complete +- (void) attemptSosUpgrade +{ + [self.otControl attemptSosUpgrade:nil context:self.contextID reply:^(NSError *error) { + if(error){ + secerror("pairing: failed to upgrade initiator into Octagon: %@", error); + } + }]; +} + +- (void)initiatorFirstPacket:(NSDictionary * __unused)indata complete:(KCPairingInternalCompletion)complete { - secnotice("pairing", "initator packet 1"); + secnotice("pairing", "initiator packet 1"); - if (![self ensureControlChannel]) { + if (OctagonPlatformSupportsSOS() && ![self ensureControlChannel]) { [self setNextStateError:[NSError errorWithDomain:kKCPairingChannelErrorDomain code:KCPairingErrorNoControlChannel userInfo:NULL] complete:complete]; return; } - __weak typeof(self) weakSelf = self; - self.nextState = ^(NSDictionary *nsdata, KCPairingInternalCompletion kscomplete){ - [weakSelf initatorSecondPacket:nsdata complete:kscomplete]; - }; - complete(false, @{ @"d" : @YES }, NULL); + if(OctagonIsEnabled() && self.sessionSupportsOctagon && !self.testFailOctagon) { + __weak typeof(self) weakSelf = self; + self.nextState = ^(NSDictionary *nsdata, KCPairingInternalCompletion kscomplete){ + [weakSelf initiatorSecondPacket:nsdata complete:kscomplete]; + }; + complete(false, @{ @"d" : @YES, @"o" : @{@"v" : @"O"} }, NULL); + } else if (OctagonIsEnabled() && self.testFailOctagon) { + complete(true, nil, NULL); + return; + } else { + __weak typeof(self) weakSelf = self; + self.nextState = ^(NSDictionary *nsdata, KCPairingInternalCompletion kscomplete){ + [weakSelf initiatorSecondPacket:nsdata complete:kscomplete]; + }; + complete(false, @{ @"d" : @YES }, NULL); + } } -- (void)initatorSecondPacket:(NSDictionary *)indata complete:(KCPairingInternalCompletion)complete +- (void)initiatorSecondPacket:(NSDictionary *)indata complete:(KCPairingInternalCompletion)complete { - secnotice("pairing", "initator packet 2"); + secnotice("pairing", "initiator packet 2"); + + NSData *octagonData = indata[@"o"]; + + if(octagonData == nil) { + secnotice("pairing", "acceptor didn't send a octagon packet, so skipping all octagon flows"); + self.sessionSupportsOctagon = false; + } NSData *credential = indata[@"c"]; - if (credential == NULL) { - secnotice("pairing", "no credential"); - [self setNextStateError:[NSError errorWithDomain:kKCPairingChannelErrorDomain code:KCPairingErrorAccountCredentialMissing userInfo:NULL] complete:complete]; - return; + if (![credential isKindOfClass:[NSData class]]) { + if(!OctagonIsEnabled() && OctagonPlatformSupportsSOS()) { + secnotice("pairing", "no credential"); + [self setNextStateError:[NSError errorWithDomain:kKCPairingChannelErrorDomain code:KCPairingErrorAccountCredentialMissing userInfo:NULL] complete:complete]; + return; + } } - if (indata[@"d"]) { + if (OctagonPlatformSupportsSOS() && indata[@"d"]) { secnotice("pairing", "acceptor will send send initial credentials"); self.acceptorWillSendInitialSyncCredentials = true; } - - [[self.connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { - complete(true, NULL, error); - }] stashAccountCredential:credential complete:^(bool success, NSError *error) { - [self setNextStateError:NULL complete:NULL]; - if (!success) { - secnotice("pairing", "failed stash credentials: %@", error); + if(OctagonPlatformSupportsSOS()) { + [[self.connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { complete(true, NULL, error); - return; - } - [self initatorCompleteSecondPacket:complete]; - }]; + }] stashAccountCredential:credential complete:^(bool success, NSError *error) { + [self setNextStateError:NULL complete:NULL]; + if (!success || self.testFailSOS) { + secnotice("pairing", "failed stash credentials: %@", error); + if(!OctagonIsEnabled() || !self.sessionSupportsOctagon){ + complete(true, NULL, error); + return; + } else { + [self initiatorCompleteSecondPacketOctagon:indata application:nil complete:complete]; + } + } else{ + [self initiatorCompleteSecondPacketWithSOS:indata complete:complete]; + } + }]; + } else if(OctagonIsEnabled() && self.sessionSupportsOctagon) { + [self initiatorCompleteSecondPacketOctagon:indata application:nil complete:complete]; + return; + } } -- (void)initatorCompleteSecondPacket:(KCPairingInternalCompletion)complete + +- (void)initiatorCompleteSecondPacketWithSOS:(NSDictionary *)indata complete:(KCPairingInternalCompletion)complete { + secnotice("pairing", "initiator complete second packet 2"); + __weak typeof(self) weakSelf = self; - secnotice("pairing", "initator complete second packet 2"); [self setNextStateError:NULL complete:NULL]; [[self.connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { complete(true, NULL, error); }] myPeerInfo:^(NSData *application, NSError *error) { - if (application) { - complete(false, @{ @"p" : application }, error); + if (application && !self.testFailSOS) { + if(OctagonIsEnabled() && self.sessionSupportsOctagon) { + [self initiatorCompleteSecondPacketOctagon:indata application:application complete:complete]; + } else{ + complete(false, @{ @"p" : application }, error); + weakSelf.nextState = ^(NSDictionary *nsdata, KCPairingInternalCompletion kscomplete){ + [weakSelf initiatorThirdPacket:nsdata complete:kscomplete]; + }; + } + } else { + if(OctagonIsEnabled() && self.sessionSupportsOctagon){ + [self initiatorCompleteSecondPacketOctagon:indata application:application complete:complete]; + } else { + secnotice("pairing", "failed getting application: %@", error); + complete(true, @{}, error); + } + } + }]; +} - weakSelf.nextState = ^(NSDictionary *nsdata, KCPairingInternalCompletion kscomplete){ - [weakSelf initatorThirdPacket:nsdata complete:kscomplete]; - }; +- (void)initiatorCompleteSecondPacketOctagon:(NSDictionary*)indata application:(NSData*)application complete:(KCPairingInternalCompletion)complete +{ + secnotice("pairing", "initiator complete second packet 2 with octagon"); + + __weak typeof(self) weakSelf = self; + NSData *octagonData = indata[@"o"]; + + if(![octagonData isKindOfClass:[NSData class]]) { + secnotice(pairingScope, "initiatorCompleteSecondPacketOctagon octagonData missing or wrong class"); + [self setNextStateError:[NSError errorWithDomain:kKCPairingChannelErrorDomain code:KCPairingErrorOctagonMessageMissing userInfo:NULL] complete:complete]; + return; + } + //handle epoch and create identity message + [self.otControl rpcPrepareIdentityAsApplicantWithConfiguration:self.joiningConfiguration + reply:^(NSString *peerID, + NSData *permanentInfo, + NSData *permanentInfoSig, + NSData *stableInfo, + NSData *stableInfoSig, + NSError *error) { + if (error || self.testFailOctagon) { + secerror("ot-pairing: failed to create %d message: %@", self.counter, error); + complete(true, nil, error); + return; } else { - secnotice("pairing", "failed getting application: %@", error); - complete(true, @{}, error); + OTPairingMessage *octagonMessage = [[OTPairingMessage alloc]init]; + OTApplicantToSponsorRound2M1 *prepare = [[OTApplicantToSponsorRound2M1 alloc] init]; + prepare.peerID = peerID; + prepare.permanentInfo = permanentInfo; + prepare.permanentInfoSig = permanentInfoSig; + prepare.stableInfo = stableInfo; + prepare.stableInfoSig = stableInfoSig; + octagonMessage.prepare = prepare; + if(application){ + secnotice(pairingScope, "initiatorCompleteSecondPacketOctagon returning octagon and sos data"); + complete(false, @{ @"p" : application, @"o" : octagonMessage.data }, nil); + } else { + secnotice(pairingScope, "initiatorCompleteSecondPacketOctagon returning octagon data"); + complete(false, @{ @"o" : octagonMessage.data }, nil); + } + weakSelf.nextState = ^(NSDictionary *nsdata, KCPairingInternalCompletion kscomplete){ + [weakSelf initiatorThirdPacket:nsdata complete:kscomplete]; + }; } }]; } -- (void)initatorThirdPacket:(NSDictionary *)indata complete:(KCPairingInternalCompletion)complete +- (void)initiatorThirdPacket:(NSDictionary *)indata complete:(KCPairingInternalCompletion)complete { __weak typeof(self) weakSelf = self; - secnotice("pairing", "initator packet 3"); + secnotice("pairing", "initiator packet 3"); [self setNextStateError:NULL complete:NULL]; NSData *circleBlob = indata[@"b"]; if (circleBlob == NULL) { - complete(true, NULL, NULL); - return; - } - - [[self.connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { - complete(true, NULL, error); - }] joinCircleWithBlob:circleBlob version:kPiggyV1 complete:^(bool success, NSError *error){ - typeof(self) strongSelf = weakSelf; - secnotice("pairing", "initator cirle join complete, more data: %s: %@", - strongSelf->_acceptorWillSendInitialSyncCredentials ? "yes" : "no", error); - - if (strongSelf->_acceptorWillSendInitialSyncCredentials) { - strongSelf.nextState = ^(NSDictionary *nsdata, KCPairingInternalCompletion kscomplete){ - [weakSelf initatorFourthPacket:nsdata complete:kscomplete]; - }; - - complete(false, @{}, NULL); - } else { + if(!OctagonIsEnabled() && OctagonPlatformSupportsSOS()) { + secnotice("pairing", "no sos circle"); complete(true, NULL, NULL); + return; } - }]; + } else if(OctagonPlatformSupportsSOS()) { + if(![circleBlob isKindOfClass:[NSData class]]) { + complete(true, NULL, [NSError errorWithDomain:kKCPairingChannelErrorDomain code:KCPairingErrorTypeConfusion userInfo:NULL]); + return; + } + + [[self.connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { + complete(true, NULL, error); + }] joinCircleWithBlob:circleBlob version:kPiggyV1 complete:^(bool success, NSError *error){ + if(error || self.testFailSOS) { + if(OctagonIsEnabled() && self.sessionSupportsOctagon) { + secnotice("pairing", "failed to join circle with blob, continuing to handle octagon protocol"); + } else { + secnotice("pairing", "failed to join circle with blob"); + complete(true, NULL, NULL); + } + } else{ + if(OctagonIsEnabled() && self.sessionSupportsOctagon) { + secnotice("pairing","initiator circle join complete"); + } else { + //kick off SOS ugprade + if(OctagonIsEnabled() && !self.sessionSupportsOctagon) { + [self attemptSosUpgrade]; + } + typeof(self) strongSelf = weakSelf; + secnotice("pairing", "initiator circle join complete, more data: %s: %@", + strongSelf->_acceptorWillSendInitialSyncCredentials ? "yes" : "no", error); + + if (strongSelf->_acceptorWillSendInitialSyncCredentials) { + strongSelf.nextState = ^(NSDictionary *nsdata, KCPairingInternalCompletion kscomplete){ + [weakSelf initiatorFourthPacket:nsdata complete:kscomplete]; + }; + + complete(false, @{}, NULL); + } else { + complete(true, NULL, NULL); + } + } + } + }]; + } + if(OctagonIsEnabled() && self.sessionSupportsOctagon){ + NSData *octagonData = indata[@"o"]; + if(![octagonData isKindOfClass:[NSData class]]) { + secnotice(pairingScope, "initiatorThirdPacket octagonData missing or wrong class"); + [self setNextStateError:[NSError errorWithDomain:kKCPairingChannelErrorDomain code:KCPairingErrorOctagonMessageMissing userInfo:NULL] complete:complete]; + return; + } + OTPairingMessage *pairingMessage = [[OTPairingMessage alloc] initWithData:octagonData]; + if(!pairingMessage.hasVoucher){ + secnotice(pairingScope, "initiatorThirdPacket pairingMessage has no voucher"); + [self setNextStateError:[NSError errorWithDomain:kKCPairingChannelErrorDomain code:KCPairingErrorOctagonMessageMissing userInfo:NULL] complete:complete]; + return; + } + OTSponsorToApplicantRound2M2 *voucher = pairingMessage.voucher; + + //handle voucher and join octagon + [self.otControl rpcJoinWithConfiguration:self.joiningConfiguration vouchData:voucher.voucher vouchSig:voucher.voucherSignature preapprovedKeys:voucher.preapprovedKeys reply:^(NSError *error) { + if (error || self.testFailOctagon) { + secerror("ot-pairing: failed to create %d message: %@", self.counter, error); + complete(true, NULL, error); + return; + }else{ + secnotice(pairingScope, "initiatorThirdPacket successfully joined Octagon"); + typeof(self) strongSelf = weakSelf; + if(OctagonPlatformSupportsSOS() && strongSelf->_acceptorWillSendInitialSyncCredentials == true) { + strongSelf.nextState = ^(NSDictionary *nsdata, KCPairingInternalCompletion kscomplete){ + [weakSelf initiatorFourthPacket:nsdata complete:kscomplete]; + }; + complete(false, @{}, nil); + + } else { + complete(true, nil, nil); + + } + } + }]; + } } -- (void)initatorFourthPacket:(NSDictionary *)indata complete:(KCPairingInternalCompletion)complete +- (void)initiatorFourthPacket:(NSDictionary *)indata complete:(KCPairingInternalCompletion)complete { - secnotice("pairing", "initator packet 4"); + secnotice("pairing", "initiator packet 4"); [self setNextStateError:NULL complete:NULL]; NSArray *items = indata[@"d"]; if (![items isKindOfClass:[NSArray class]]) { - secnotice("pairing", "initator no items to import"); + secnotice("pairing", "initiator no items to import"); complete(true, NULL, NULL); return; } @@ -280,10 +531,10 @@ - (void)initatorFourthPacket:(NSDictionary *)indata complete:(KCPairingInternalC [[self.connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { complete(true, NULL, error); }] importInitialSyncCredentials:items complete:^(bool success, NSError *error) { - secnotice("pairing", "initator importInitialSyncCredentials: %s: %@", success ? "yes" : "no", error); + secnotice("pairing", "initiator importInitialSyncCredentials: %s: %@", success ? "yes" : "no", error); if (success) self->_needInitialSync = false; - complete(true, NULL, NULL); + complete(true, nil, nil); }]; } @@ -296,42 +547,104 @@ - (void)acceptorFirstPacket:(NSDictionary *)indata complete:(KCPairingInternalCo __weak typeof(self) weakSelf = self; secnotice("pairing", "acceptor packet 1"); - [self setNextStateError:NULL complete:NULL]; - if (![self ensureControlChannel]) { + if (self.sessionSupportsSOS && ![self ensureControlChannel]) { + secnotice("pairing", "unable to establish a channel to sos control"); [self setNextStateError:[NSError errorWithDomain:kKCPairingChannelErrorDomain code:KCPairingErrorNoControlChannel userInfo:NULL] complete:complete]; return; } - if (indata[@"d"]) { + if (self.sessionSupportsSOS && indata[@"d"]) { secnotice("pairing", "acceptor initialSyncCredentials requested"); self.acceptorWillSendInitialSyncCredentials = true; } - [[self.connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { - complete(true, NULL, error); - }] validatedStashedAccountCredential:^(NSData *credential, NSError *error) { - if (!credential) { - secnotice("pairing", "acceptor doesn't have a stashed credential: %@", error); - [self setNextStateError:error complete:complete]; - return; - } + if (indata[@"o"] == nil) { + secnotice("pairing", "initiator didn't send a octagon packet, so skipping all octagon flows"); + self.sessionSupportsOctagon = false; + } + // XXX Before we go here we should check if we are trusted or not, if we are not, there is no point proposing octagon - self.nextState = ^(NSDictionary *nsdata, KCPairingInternalCompletion kscomplete){ - [weakSelf acceptorSecondPacket:nsdata complete:kscomplete]; - }; + NSMutableDictionary *reply = [NSMutableDictionary dictionary]; - NSMutableDictionary *reply = [@{ - @"c" : credential, - } mutableCopy]; + if(self.sessionSupportsSOS) { + [[self.connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { + complete(true, NULL, error); + }] validatedStashedAccountCredential:^(NSData *credential, NSError *error) { + secnotice("pairing", "acceptor validatedStashedAccountCredential: %@ (%@)", credential != NULL ? @"yes" : @"no", error); + if(credential){ + reply[@"c"] = credential; - if (self.acceptorWillSendInitialSyncCredentials) { - reply[@"d"] = @YES; - }; + if (self.acceptorWillSendInitialSyncCredentials) { + reply[@"d"] = @YES; + }; + if(self.sessionSupportsOctagon) { + [self acceptorFirstOctagonPacket:indata reply:reply complete:complete]; + } else { + self.nextState = ^(NSDictionary *nsdata, KCPairingInternalCompletion kscomplete){ + [weakSelf acceptorSecondPacket:nsdata complete:kscomplete]; + }; + secnotice("pairing", "acceptor reply to packet 1"); + complete(false, reply, NULL); + } + } + else if ((!credential && !self.sessionSupportsOctagon) || self.testFailSOS) { + secnotice("pairing", "acceptor doesn't have a stashed credential: %@", error); + NSError *noStashCredentail = [NSError errorWithDomain:kKCPairingChannelErrorDomain code:KCPairingErrorNoStashedCredential userInfo:NULL]; + [self setNextStateError:noStashCredentail complete:complete]; + return; + } + else if(self.sessionSupportsOctagon) { + [self acceptorFirstOctagonPacket:indata reply:reply complete:complete]; + } + }]; + } else if(self.sessionSupportsOctagon){ + [self acceptorFirstOctagonPacket:indata reply:reply complete:complete]; + } else { + secnotice("pairing", "acceptor neither of octagon nor SOS"); + NSError *notSupported = [NSError errorWithDomain:kKCPairingChannelErrorDomain code:KCPairingErrorNoTrustAvailable userInfo:NULL]; + [self setNextStateError:notSupported complete:complete]; + } +} +- (void)acceptorFirstOctagonPacket:(NSDictionary *)indata reply:(NSMutableDictionary*)reply complete:(KCPairingInternalCompletion)complete +{ + __weak typeof(self) weakSelf = self; + NSDictionary *octagonData = indata[@"o"]; + + if(![octagonData isKindOfClass:[NSDictionary class]]) { + secnotice(pairingScope, "acceptorFirstOctagonPacket octagon data missing"); + [self setNextStateError:[NSError errorWithDomain:kKCPairingChannelErrorDomain code:KCPairingErrorOctagonMessageMissing userInfo:NULL] complete:complete]; + return; + } + + NSDictionary *unpackedMessage = octagonData; - secnotice("pairing", "acceptor reply to packet 1"); - complete(false, reply, NULL); + if(![unpackedMessage[@"v"] isEqualToString:@"O"]){ + secnotice(pairingScope, "acceptorFirstOctagonPacket 'v' contents wrong"); + [self setNextStateError:[NSError errorWithDomain:kKCPairingChannelErrorDomain code:KCPairingErrorOctagonMessageMissing userInfo:NULL] complete:complete]; + return; + } + + //handle epoch request and fetch epoch + [self.otControl rpcEpochWithConfiguration:self.joiningConfiguration reply:^(uint64_t epoch, NSError * _Nullable error) { + secnotice("pairing", "acceptor rpcEpochWithConfiguration: %ld (%@)", (long)epoch, error); + if(error || self.testFailOctagon){ + secerror("error acceptor handling packet %d", self.counter); + complete(true, nil, error); + }else{ + secnotice(pairingScope, "acceptor handled packet %d", self.counter); + self.nextState = ^(NSDictionary *nsdata, KCPairingInternalCompletion kscomplete){ + [weakSelf acceptorSecondPacket:nsdata complete:kscomplete]; + }; + OTPairingMessage *response = [[OTPairingMessage alloc] init]; + response.epoch = [[OTSponsorToApplicantRound1M2 alloc] init]; + response.epoch.epoch = epoch; + reply[@"o"] = response.data; + + secnotice("pairing", "acceptor reply to packet 1"); + complete(false, reply, error); + } }]; } @@ -342,32 +655,96 @@ - (void)acceptorSecondPacket:(NSDictionary *)indata complete:(KCPairingInternalC [self setNextStateError:NULL complete:NULL]; secnotice("pairing", "acceptor packet 2"); + __block NSMutableDictionary *reply = [NSMutableDictionary dictionary]; - [[self.connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { - complete(true, NULL, error); - }] circleJoiningBlob:indata[@"p"] complete:^(NSData *blob, NSError *error){ - NSMutableDictionary *reply = [NSMutableDictionary dictionary]; + NSData *peerJoinBlob = indata[@"p"]; + + if(self.sessionSupportsSOS && [peerJoinBlob isKindOfClass:[NSData class]]) { + [[self.connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { + complete(true, NULL, error); + }] circleJoiningBlob:peerJoinBlob complete:^(NSData *blob, NSError *error){ - if (blob) { - secnotice("pairing", "acceptor pairing complete (will send: %s): %@", - self.acceptorWillSendInitialSyncCredentials ? "YES" : "NO", - error); + if (blob) { + secnotice("pairing", "acceptor pairing complete (will send: %s): %@", + self.acceptorWillSendInitialSyncCredentials ? "YES" : "NO", + error); - reply[@"b"] = blob; + reply[@"b"] = blob; + } + if(self.sessionSupportsOctagon) { + [self acceptorSecondOctagonPacket:indata reply:reply complete:complete]; + } else { + secnotice("pairing", "posting kSOSCCCircleOctagonKeysChangedNotification"); + notify_post(kSOSCCCircleOctagonKeysChangedNotification); + if (self.acceptorWillSendInitialSyncCredentials) { + self.nextState = ^(NSDictionary *nsdata, KCPairingInternalCompletion kscomplete){ + [weakSelf acceptorThirdPacket:nsdata complete:kscomplete]; + }; + + complete(false, reply, NULL); + } else { + complete(true, reply, NULL); + } + secnotice("pairing", "acceptor reply to packet 2"); + } + }]; + } else if(self.sessionSupportsOctagon){ + [self acceptorSecondOctagonPacket:indata reply:reply complete:complete]; + } +} + +- (void)acceptorSecondOctagonPacket:(NSDictionary*)indata reply:(NSMutableDictionary*)reply complete:(KCPairingInternalCompletion)complete +{ + __weak typeof(self) weakSelf = self; + NSData *octagonData = indata[@"o"]; + + if(![octagonData isKindOfClass:[NSData class]]) { + secnotice(pairingScope, "acceptorSecondOctagonPacket octagon data missing"); + [self setNextStateError:[NSError errorWithDomain:kKCPairingChannelErrorDomain code:KCPairingErrorOctagonMessageMissing userInfo:NULL] complete:complete]; + return; + } + + OTPairingMessage *pairingMessage = [[OTPairingMessage alloc] initWithData:octagonData]; + if(!pairingMessage.hasPrepare){ + secerror("ot-pairing: acceptorSecondOctagonPacket: no octagon message"); + [self setNextStateError:[NSError errorWithDomain:kKCPairingChannelErrorDomain code:KCPairingErrorOctagonMessageMissing userInfo:NULL] complete:complete]; + return; + } + OTApplicantToSponsorRound2M1 *prepare = pairingMessage.prepare; + + //handle identity and fetch voucher + [self.otControl rpcVoucherWithConfiguration:self.joiningConfiguration + peerID:prepare.peerID + permanentInfo:prepare.permanentInfo + permanentInfoSig:prepare.permanentInfoSig + stableInfo:prepare.stableInfo + stableInfoSig:prepare.stableInfoSig + reply:^(NSData *voucher, + NSData *voucherSig, + NSError *error) { + if(error || self.testFailOctagon){ + secerror("error acceptor handling octagon packet %d", self.counter); + complete(true, nil, error); + return; + } else { + bool finished = true; - if (self.acceptorWillSendInitialSyncCredentials) { + secnotice(pairingScope, "acceptor handled octagon packet %d", self.counter); + if (OctagonPlatformSupportsSOS() && self.acceptorWillSendInitialSyncCredentials) { self.nextState = ^(NSDictionary *nsdata, KCPairingInternalCompletion kscomplete){ [weakSelf acceptorThirdPacket:nsdata complete:kscomplete]; }; - - complete(false, reply, NULL); - } else { - complete(true, reply, NULL); + finished = false; } - } else { - complete(true, reply, error); + OTPairingMessage *response = [[OTPairingMessage alloc] init]; + response.voucher = [[OTSponsorToApplicantRound2M2 alloc] init]; + response.voucher.voucher = voucher; + response.voucher.voucherSignature = voucherSig; + reply[@"o"] = response.data; + + secnotice("pairing", "acceptor reply to packet 2"); + complete(finished ? true : false, reply, error); } - secnotice("pairing", "acceptor reply to packet 2"); }]; } @@ -375,9 +752,14 @@ - (void)acceptorThirdPacket:(NSDictionary *)indata complete:(KCPairingInternalCo { secnotice("pairing", "acceptor packet 3"); + const uint32_t initialSyncCredentialsFlags = + SOSControlInitialSyncFlagTLK| + SOSControlInitialSyncFlagPCS| + SOSControlInitialSyncFlagBluetoothMigration; + [[self.connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { complete(true, NULL, error); - }] initialSyncCredentials:(SOSControlInitialSyncFlagTLK|SOSControlInitialSyncFlagPCS) complete:^(NSArray *items, NSError *error2) { + }] initialSyncCredentials:initialSyncCredentialsFlags complete:^(NSArray *items, NSError *error2) { NSMutableDictionary *reply = [NSMutableDictionary dictionary]; secnotice("pairing", "acceptor initialSyncCredentials complete: items %u: %@", (unsigned)[items count], error2); @@ -397,19 +779,12 @@ - (bool)ensureControlChannel if (self.connection) return true; - xpc_endpoint_t endpoint = _SecSecuritydCopySOSStatusEndpoint(NULL); - if (endpoint == NULL) - return false; - NSXPCInterface *interface = [NSXPCInterface interfaceWithProtocol:@protocol(SOSControlProtocol)]; - NSXPCListenerEndpoint *listenerEndpoint = [[NSXPCListenerEndpoint alloc] init]; - [listenerEndpoint _setEndpoint:endpoint]; - - self.connection = [[NSXPCConnection alloc] initWithListenerEndpoint:listenerEndpoint]; - if (self.connection == NULL) + self.connection = [[NSXPCConnection alloc] initWithMachServiceName:@(kSecuritydSOSServiceName) options:0]; + if (self.connection == NULL){ return false; - + } self.connection.remoteObjectInterface = interface; [self.connection resume]; @@ -419,7 +794,7 @@ - (bool)ensureControlChannel - (void)validateStart:(void(^)(bool result, NSError *error))complete { - if (!self.initator) { + if (!self.initiator) { [[self.connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { complete(false, error); }] stashedCredentialPublicKey:^(NSData *publicKey, NSError *error) { @@ -435,6 +810,8 @@ - (void)validateStart:(void(^)(bool result, NSError *error))complete - (void)exchangePacket:(NSData *)inputCompressedData complete:(KCPairingChannelCompletion)complete { NSDictionary *indict = NULL; + secnotice("pairing", "Exchange packet: %u", self.counter); + self.counter++; if (inputCompressedData) { @@ -467,11 +844,12 @@ - (void)exchangePacket:(NSData *)inputCompressedData complete:(KCPairingChannelC if (compressedData) { NSString *key = [NSString stringWithFormat:@"com.apple.ckks.pairing.packet-size.%s.%u", - self->_initator ? "initator" : "acceptor", self->_counter]; + self->_initiator ? "initiator" : "acceptor", self->_counter]; SecADClientPushValueForDistributionKey((__bridge CFStringRef)key, [compressedData length]); secnotice("pairing", "pairing packet size %lu", (unsigned long)[compressedData length]); } } + secnotice("pairing", "Exchange packet complete data: %@: %@", outdata ? @"YES" : @"NO", error); complete(completed, compressedData, error); }); } @@ -482,7 +860,6 @@ - (NSData *)exchangePacket:(NSData *)data complete:(bool *)complete error:(NSErr __block NSData *rData = NULL; __block NSError* processingError; [self exchangePacket:data complete:^(BOOL cComplete, NSData *cData, NSError *cError) { - self.counter++; *complete = cComplete; rData = cData; processingError = cError; @@ -499,5 +876,28 @@ - (void)setXPCConnectionObject:(NSXPCConnection *)connection self.connection = connection; } +- (void)setControlObject:(OTControl *)control +{ + self.otControl = control; +} + +- (void)setConfiguration:(OTJoiningConfiguration *)config +{ + self.joiningConfiguration = config; +} + +- (void)setSOSMessageFailForTesting:(BOOL)value +{ + self.testFailSOS = value; +} +- (void)setOctagonMessageFailForTesting:(BOOL)value +{ + self.testFailOctagon = value; +} + +- (void)setSessionSupportsOctagonForTesting:(bool)value +{ + self.sessionSupportsOctagon = value; +} @end diff --git a/KeychainCircle/Tests/FakeSOSControl.h b/KeychainCircle/Tests/FakeSOSControl.h new file mode 100644 index 000000000..ff3f99923 --- /dev/null +++ b/KeychainCircle/Tests/FakeSOSControl.h @@ -0,0 +1,43 @@ +#ifndef FakeSOSControl_h +#define FakeSOSControl_h + +#import +#import +#import +#import +#import "keychain/SecureObjectSync/SOSAccount.h" +#include "keychain/SecureObjectSync/SOSAccountPriv.h" +#include "keychain/SecureObjectSync/SOSCircle.h" +#import +#import "utilities/SecCFWrappers.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FCPairingFakeSOSControl : NSObject +@property (assign) SecKeyRef accountPrivateKey; +@property (assign) SecKeyRef accountPublicKey; +@property (assign) SecKeyRef deviceKey; +@property (assign) SecKeyRef octagonSigningKey; +@property (assign) SecKeyRef octagonEncryptionKey; +@property (assign) SOSCircleRef circle; +@property (assign) SOSFullPeerInfoRef fullPeerInfo; +@property (assign) bool application; +- (instancetype)initWithRandomAccountKey:(bool)randomAccountKey circle:(SOSCircleRef)circle; +- (void)dealloc; +- (SOSPeerInfoRef)peerInfo; +- (void)signApplicationIfNeeded; +@end + +@interface FakeNSXPCConnection : NSObject +- (instancetype) initWithControl:(id)control; +- (id)remoteObjectProxyWithErrorHandler:(void(^)(NSError * _Nonnull error))failureHandler; +@end + +@interface FakeNSXPCConnection () +@property id control; +@end + +NS_ASSUME_NONNULL_END +#endif /* FakeSOSControl_h */ + + diff --git a/KeychainCircle/Tests/FakeSOSControl.m b/KeychainCircle/Tests/FakeSOSControl.m new file mode 100644 index 000000000..e0a2c500f --- /dev/null +++ b/KeychainCircle/Tests/FakeSOSControl.m @@ -0,0 +1,331 @@ + +#import "FakeSOSControl.h" + +@implementation FakeNSXPCConnection +- (instancetype) initWithControl:(id)control +{ + self = [super init]; + if (self) { + _control = control; + } + return self; +} +- (id)remoteObjectProxyWithErrorHandler:(void(^)(NSError * _Nonnull error))failureHandler +{ + (void)failureHandler; + return _control; +} +@end + +@implementation FCPairingFakeSOSControl + +- (instancetype)initWithRandomAccountKey:(bool)randomAccountKey circle:(SOSCircleRef)circle +{ + if ((self = [super init])) { + SecKeyRef publicKey = NULL; + NSDictionary* parameters = @{ + (__bridge NSString*)kSecAttrKeyType:(__bridge NSString*) kSecAttrKeyTypeEC, + (__bridge NSString*)kSecAttrKeySizeInBits: @(256), + (__bridge NSString*)kSecUseDataProtectionKeychain : @YES, + (__bridge NSString*)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleAfterFirstUnlock, + (__bridge id)kSecPrivateKeyAttrs : @{ + (__bridge NSString*)kSecAttrLabel : @"delete me test case - private", + (__bridge NSString*)kSecAttrIsPermanent : @YES, + (__bridge NSString*)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleAfterFirstUnlock, + }, + (__bridge id)kSecPublicKeyAttrs : @{ + (__bridge NSString*)kSecAttrLabel : @"delete me test case - public", + (__bridge NSString*)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleAfterFirstUnlock, + } + }; + if(SecKeyGeneratePair((__bridge CFDictionaryRef)parameters, &publicKey, &_deviceKey) != 0) { + NSLog(@"failed to create device key"); + return nil; + } + CFReleaseNull(publicKey); + + NSMutableDictionary* octagonParameters = [parameters mutableCopy]; + octagonParameters[(__bridge NSString*)kSecAttrKeySizeInBits] = @(384); + if(SecKeyGeneratePair((__bridge CFDictionaryRef)octagonParameters, &publicKey, &_octagonSigningKey) != 0) { + NSLog(@"failed to create octagon signing key"); + return nil; + } + CFReleaseNull(publicKey); + + if(SecKeyGeneratePair((__bridge CFDictionaryRef)octagonParameters, &publicKey, &_octagonEncryptionKey) != 0) { + NSLog(@"failed to create octagon signing key"); + return nil; + } + CFReleaseNull(publicKey); + + + _circle = (SOSCircleRef)CFRetain(circle); + + CFErrorRef error = NULL; + + CFDictionaryRef gestalt = (__bridge CFDictionaryRef)@{ + @"ComputerName" : @"name", + }; + + _fullPeerInfo = SOSFullPeerInfoCreate(NULL, gestalt, NULL, _deviceKey, _octagonSigningKey, _octagonEncryptionKey, &error); + CFReleaseNull(error); + + if (randomAccountKey) { + + NSDictionary* accountParams = @{ + (__bridge NSString*)kSecAttrKeyType:(__bridge NSString*) kSecAttrKeyTypeEC, + (__bridge NSString*)kSecAttrKeySizeInBits: @(256), + (__bridge NSString*)kSecUseDataProtectionKeychain : @YES, + (__bridge NSString*)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleAfterFirstUnlock, + }; + + if(SecKeyGeneratePair((__bridge CFDictionaryRef)accountParams, &publicKey, &_accountPrivateKey) != 0) { + NSLog(@"failed to create account signing key"); + return nil; + } + CFReleaseNull(publicKey); + + _accountPublicKey = SecKeyCopyPublicKey(_accountPrivateKey); + + [self signApplicationIfNeeded]; + } + } + return self; +} + +- (void)dealloc +{ + if (_accountPrivateKey) { + SecItemDelete((__bridge CFTypeRef)@{ (__bridge id)kSecValueRef : (__bridge id)_accountPrivateKey }); + CFReleaseNull(_accountPrivateKey); + } + if (_deviceKey) { + SecItemDelete((__bridge CFTypeRef)@{ (__bridge id)kSecValueRef : (__bridge id)_deviceKey }); + CFReleaseNull(_deviceKey); + } + if (_octagonSigningKey) { + SecItemDelete((__bridge CFTypeRef)@{ (__bridge id)kSecValueRef : (__bridge id)_octagonSigningKey }); + CFReleaseNull(_octagonSigningKey); + } + if (_octagonEncryptionKey) { + SecItemDelete((__bridge CFTypeRef)@{ (__bridge id)kSecValueRef : (__bridge id)_octagonEncryptionKey }); + CFReleaseNull(_octagonEncryptionKey); + } + CFReleaseNull(_circle); + CFReleaseNull(_fullPeerInfo); +} + +- (SOSPeerInfoRef)peerInfo +{ + return SOSFullPeerInfoGetPeerInfo(_fullPeerInfo); +} + +- (void)signApplicationIfNeeded +{ + CFErrorRef error = NULL; + + _application = SOSFullPeerInfoPromoteToApplication(_fullPeerInfo, _accountPrivateKey, &error); + if (!_application) + abort(); +} + +- (void)initialSyncCredentials:(uint32_t)flags complete:(void (^)(NSArray *, NSError *))complete +{ + complete(@[], NULL); +} + +- (void)importInitialSyncCredentials:(NSArray *)items complete:(void (^)(bool success, NSError *))complete +{ + complete(true, NULL); +} + +- (void)triggerSync:(NSArray *)peers complete:(void(^)(bool success, NSError *))complete +{ + complete(true, NULL); +} + +//MARK - FCPairingFakeSOSControl SOSControlProtocol + +- (void)userPublicKey:(void ((^))(BOOL trusted, NSData *spki, NSError *error))complete +{ + complete(false, NULL, NULL); +} + +- (void)performanceCounters:(void(^)(NSDictionary *))complete +{ + complete(@{}); +} +- (void)kvsPerformanceCounters:(void(^)(NSDictionary *))complete +{ + complete(@{}); +} + +- (void)rateLimitingPerformanceCounters:(void(^)(NSDictionary *))complete +{ + complete(@{}); +} +- (void)stashedCredentialPublicKey:(void(^)(NSData *, NSError *error))complete +{ + NSData *publicKey = NULL; + NSError *error = NULL; + if (self.accountPrivateKey) { + publicKey = CFBridgingRelease(SecKeyCopySubjectPublicKeyInfo(self.accountPrivateKey)); + } else { + error = [NSError errorWithDomain:@"FCPairingFakeSOSControl" code:2 userInfo:NULL]; + } + complete(publicKey, error); +} + +- (void)assertStashedAccountCredential:(void(^)(BOOL result, NSError *error))complete +{ + complete(self.accountPrivateKey != NULL, NULL); +} + +- (void)validatedStashedAccountCredential:(void(^)(NSData *credential, NSError *error))complete +{ + NSData *key = NULL; + CFErrorRef error = NULL; + if (self.accountPrivateKey) { + key = CFBridgingRelease(SecKeyCopyExternalRepresentation(self.accountPrivateKey, &error)); + } else { + error = (CFErrorRef)CFBridgingRetain([NSError errorWithDomain:@"FCPairingFakeSOSControl" code:1 userInfo:NULL]); + } + complete(key, (__bridge NSError *)error); + CFReleaseNull(error); +} + +- (void)stashAccountCredential:(NSData *)credential complete:(void(^)(bool success, NSError *error))complete +{ + 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); + CFReleaseNull(error); + return; + } + + _accountPrivateKey = accountPrivateKey; + _accountPublicKey = SecKeyCopyPublicKey(_accountPrivateKey); + + [self signApplicationIfNeeded]; + + complete(true, NULL); +} + +- (void)myPeerInfo:(void(^)(NSData *application, NSError *error))complete +{ + CFErrorRef error = NULL; + + [self signApplicationIfNeeded]; + + NSData *application = CFBridgingRelease(SOSPeerInfoCopyEncodedData([self peerInfo], NULL, &error)); + complete(application, (__bridge NSError *)error); + + CFReleaseNull(error); +} + +- (void)circleHash:(void (^)(NSString *, NSError *))complete +{ + NSString *data = CFBridgingRelease(SOSCircleCopyHashString(_circle)); + complete(data, NULL); +} + +- (void)circleJoiningBlob:(NSData *)applicantData complete:(void (^)(NSData *blob, NSError *))complete +{ + CFErrorRef error = NULL; + CFDataRef signature = NULL; + SOSCircleRef prunedCircle = SOSCircleCopyCircle(NULL, _circle, &error); + (void)SOSCirclePreGenerationSign(prunedCircle, _accountPublicKey, &error); + + SOSGenCountRef gencount = SOSGenerationIncrementAndCreate(SOSCircleGetGeneration(prunedCircle)); + if (gencount == NULL) + abort(); + + + SOSPeerInfoRef applicant = SOSPeerInfoCreateFromData(NULL, &error, (__bridge CFDataRef)applicantData); + if (applicant == NULL) + abort(); + + signature = SOSCircleCopyNextGenSignatureWithPeerAdded(prunedCircle, applicant, _deviceKey, &error); + if(applicant) { + CFRelease(applicant); + applicant = NULL; + } + + NSData *pbblob = CFBridgingRelease(SOSPiggyBackBlobCopyEncodedData(gencount, _deviceKey, signature, &error)); + + CFReleaseNull(signature); + CFReleaseNull(gencount); + CFReleaseNull(prunedCircle); + + complete(pbblob, NULL); +} + +- (void)joinCircleWithBlob:(NSData *)blob version:(PiggyBackProtocolVersion)version complete:(void (^)(bool success, NSError *))complete +{ + SOSGenCountRef gencount = NULL; + SecKeyRef pubKey = NULL; + CFDataRef signature = NULL; + CFErrorRef error = NULL; + bool setInitialSyncTimeoutToV0 = false; + + if (!SOSPiggyBackBlobCreateFromData(&gencount, &pubKey, &signature, (__bridge CFDataRef)blob, kPiggyV1, &setInitialSyncTimeoutToV0, &error)) { + complete(true, (__bridge NSError *)error); + CFReleaseNull(error); + return; + } + + (void)SOSCircleAcceptPeerFromHSA2(_circle, + _accountPrivateKey, + gencount, + pubKey, + signature, + _fullPeerInfo, + &error); + + CFReleaseNull(gencount); + CFReleaseNull(pubKey); + CFReleaseNull(signature); + + complete(true, (__bridge NSError *)error); + + CFReleaseNull(error); + +} + +- (void)getWatchdogParameters:(void (^)(NSDictionary*, NSError*))complete +{ + // intentionally left blank + // these are used by the security/2 tool and are only declared here to make the compiler happy about conforming the protocol we shoved the methods into +} + + +- (void)setWatchdogParmeters:(NSDictionary*)parameters complete:(void (^)(NSError*))complete +{ + // intentionally left blank + // these are used by the security/2 tool and are only declared here to make the compiler happy about conforming the protocol we shoved the methods into +} + +- (void)ghostBust:(SOSAccountGhostBustingOptions)options complete:(void (^)(bool, NSError *))complete { + complete(false, nil); +} + +- (void)ghostBustPeriodic:(SOSAccountGhostBustingOptions)options complete: (void(^)(bool busted, NSError *error))complete{ + complete(false, nil); +} + +- (void)ghostBustTriggerTimed:(SOSAccountGhostBustingOptions)options complete: (void(^)(bool ghostBusted, NSError *error))complete { + complete(false, nil); +} + +- (void) ghostBustInfo: (void(^)(NSData *json, NSError *error))complete { + complete(nil, nil); +} + +@end diff --git a/KeychainCircle/Tests/KCAESGCMTest.m b/KeychainCircle/Tests/KCAESGCMTest.m index 708a53a73..602e5afbc 100644 --- a/KeychainCircle/Tests/KCAESGCMTest.m +++ b/KeychainCircle/Tests/KCAESGCMTest.m @@ -8,6 +8,7 @@ #import #import +#import @interface KCAESGCMTest : XCTestCase @@ -66,13 +67,10 @@ - (void)testAESGCMDuplex { } - (KCAESGCMDuplexSession*) archiveDearchive: (KCAESGCMDuplexSession*) original { - NSMutableData *data = [NSMutableData data]; - NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; + NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]; [archiver encodeObject:original forKey:@"Top"]; - [archiver finishEncoding]; - NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; - unarchiver.requiresSecureCoding = YES; + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:archiver.encodedData error:nil]; // Customize the unarchiver. KCAESGCMDuplexSession *result = [unarchiver decodeObjectForKey:@"Top"]; diff --git a/KeychainCircle/Tests/KCDerTest.m b/KeychainCircle/Tests/KCDerTest.m index c4dcc319d..16bf0ba7b 100644 --- a/KeychainCircle/Tests/KCDerTest.m +++ b/KeychainCircle/Tests/KCDerTest.m @@ -34,28 +34,28 @@ - (void) roundTripData: (NSData*) data { if (size == 0) return; - uint8_t buffer[size]; + NSMutableData *buffer = [NSMutableData dataWithLength:size]; error = nil; - uint8_t* beginning = kcder_encode_data(data, &error, buffer, buffer + sizeof(buffer)); + uint8_t* beginning = kcder_encode_data(data, &error, [buffer mutableBytes], [buffer mutableBytes] + size); XCTAssert(beginning != NULL, "Error encoding: %@", error); if (beginning == NULL) return; - XCTAssertEqual(beginning, &buffer[0], @"Size != buffer use"); + XCTAssertEqual(beginning, [buffer mutableBytes], @"Size != buffer use"); NSData* recovered = nil; error = nil; - const uint8_t* end = kcder_decode_data(&recovered, &error, buffer, buffer + sizeof(buffer)); + const uint8_t* end = kcder_decode_data(&recovered, &error, [buffer mutableBytes], [buffer mutableBytes] + size); XCTAssert(end != NULL, "Error decoding: %@", error); if (end == NULL) return; - XCTAssertEqual(end, buffer + sizeof(buffer), @"readback didn't use all the buffer"); + XCTAssertEqual(end, [buffer mutableBytes] + size, @"readback didn't use all the buffer"); XCTAssertEqualObjects(data, recovered, @"Didn't get equal object"); @@ -78,28 +78,28 @@ - (void) roundTripString: (NSString*) string { if (size == 0) return; - uint8_t buffer[size]; + NSMutableData *buffer = [NSMutableData dataWithLength:size]; error = nil; - uint8_t* beginning = kcder_encode_string(string, &error, buffer, buffer + sizeof(buffer)); + uint8_t* beginning = kcder_encode_string(string, &error, [buffer mutableBytes], [buffer mutableBytes] + size); XCTAssert(beginning != NULL, "Error encoding: %@", error); if (beginning == NULL) return; - XCTAssertEqual(beginning, &buffer[0], @"Size != buffer use"); + XCTAssertEqual(beginning, [buffer mutableBytes], @"Size != buffer use"); NSString* recovered = nil; error = nil; - const uint8_t* end = kcder_decode_string(&recovered, &error, buffer, buffer + sizeof(buffer)); + const uint8_t* end = kcder_decode_string(&recovered, &error, [buffer mutableBytes], [buffer mutableBytes] + size); XCTAssert(end != NULL, "Error decoding: %@", error); if (end == NULL) return; - XCTAssertEqual(end, buffer + sizeof(buffer), @"readback didn't use all the buffer"); + XCTAssertEqual(end, [buffer mutableBytes] + size, @"readback didn't use all the buffer"); XCTAssertEqualObjects(string, recovered, @"Didn't get equal object"); diff --git a/KeychainCircle/Tests/KCJoiningSessionTest.m b/KeychainCircle/Tests/KCJoiningSessionTest.m index 4f95e3c50..a8919e9dc 100644 --- a/KeychainCircle/Tests/KCJoiningSessionTest.m +++ b/KeychainCircle/Tests/KCJoiningSessionTest.m @@ -14,19 +14,21 @@ #import #include -#include -#include +#include "keychain/SecureObjectSync/SOSFullPeerInfo.h" +#include "keychain/SecureObjectSync/SOSPeerInfoInternal.h" #include __unused static SOSFullPeerInfoRef SOSNSFullPeerInfoCreate(NSDictionary* gestalt, - NSData* backupKey, SecKeyRef signingKey, SecKeyRef octagonSigningKey, - NSError**error) + NSData* backupKey, SecKeyRef signingKey, + SecKeyRef octagonSigningKey, + SecKeyRef octagonEncryptionKey, + NSError**error) { CFErrorRef errorRef = NULL; - SOSFullPeerInfoRef result = SOSFullPeerInfoCreate(NULL, (__bridge CFDictionaryRef) gestalt, (__bridge CFDataRef) backupKey, signingKey, octagonSigningKey, &errorRef); + SOSFullPeerInfoRef result = SOSFullPeerInfoCreate(NULL, (__bridge CFDictionaryRef) gestalt, (__bridge CFDataRef) backupKey, signingKey, octagonSigningKey, octagonEncryptionKey, &errorRef); if (errorRef && error) { *error = (__bridge_transfer NSError*) errorRef; @@ -54,24 +56,6 @@ static SecKeyRef GenerateFullECKey(int keySize, NSError** error) { } -__unused static SOSFullPeerInfoRef SOSCreateFullPeerInfoFromName(NSString* name, SecKeyRef* outSigningKey, SecKeyRef* outOctagonSigningKey, NSError** error) -{ - if (outSigningKey == NULL || outOctagonSigningKey == NULL) - return NULL; - - *outSigningKey = GenerateFullECKey(256, error); - if (*outSigningKey == NULL) - return NULL; - - *outOctagonSigningKey = GenerateFullECKey(384, error); - if (*outOctagonSigningKey == NULL) { - return NULL; - } - - return SOSNSFullPeerInfoCreate(@{(__bridge NSString*)kPIUserDefinedDeviceNameKey:name}, nil, *outSigningKey, *outOctagonSigningKey, error); -} - - @interface KCJoiningRequestTestDelegate : NSObject @property (readwrite) NSString* sharedSecret; @@ -98,6 +82,12 @@ - (bool) processAccountCode: (NSString*) accountCode error: (NSError**)error; @implementation KCJoiningRequestTestDelegate +- (void)dealloc { + if(_peerInfo) { + CFRelease(_peerInfo); + } +} + + (id) requestDelegateWithSecret:(NSString*) secret { return [[KCJoiningRequestTestDelegate alloc] initWithSecret:secret incorrectSecret:@"" @@ -120,11 +110,16 @@ - (id) initWithSecret: (NSString*) secret SecKeyRef signingKey = GenerateFullECKey(256, NULL); SecKeyRef octagonSigningKey = GenerateFullECKey(384, NULL); + SecKeyRef octagonEncryptionKey = GenerateFullECKey(384, NULL); - self.peerInfo = SOSPeerInfoCreate(NULL, (__bridge CFDictionaryRef) @{(__bridge NSString*)kPIUserDefinedDeviceNameKey:@"Fakey"}, NULL, signingKey, octagonSigningKey, NULL); + SOSPeerInfoRef newPeerInfo = SOSPeerInfoCreate(NULL, (__bridge CFDictionaryRef) @{(__bridge NSString*)kPIUserDefinedDeviceNameKey:@"Fakey"}, NULL, signingKey, octagonSigningKey, octagonEncryptionKey, NULL); - if (self.peerInfo == NULL) + if (newPeerInfo == NULL) { return nil; + } + self.peerInfo = newPeerInfo; + CFRelease(newPeerInfo); + newPeerInfo = NULL; self.sharedSecret = secret; self.incorrectSecret = incorrectSecret; @@ -150,7 +145,11 @@ - (NSString*) verificationFailed: (bool) codeChanged { } - (SOSPeerInfoRef) copyPeerInfoError: (NSError**) error { - return self.peerInfo; + if(!self.peerInfo) { + return NULL; + } + + return (SOSPeerInfoRef) CFRetain(self.peerInfo); } - (bool) processCircleJoinData: (NSData*) circleJoinData version:(PiggyBackProtocolVersion)version error: (NSError**)error { diff --git a/KeychainCircle/Tests/KCPairingTest.m b/KeychainCircle/Tests/KCPairingTest.m index eb77f2dd5..2196443db 100644 --- a/KeychainCircle/Tests/KCPairingTest.m +++ b/KeychainCircle/Tests/KCPairingTest.m @@ -9,419 +9,63 @@ #import #import #import -#import -#import -#import +#import "keychain/SecureObjectSync/SOSAccount.h" +#include "keychain/SecureObjectSync/SOSAccountPriv.h" +#include "keychain/SecureObjectSync/SOSCircle.h" #import #import #import "SecCFWrappers.h" #import "SOSRegressionUtilities.h" - -@interface FakeNSXPCConnection : NSObject -- (instancetype) initWithControl:(id)control; -- (id)remoteObjectProxyWithErrorHandler:(void(^)(NSError * _Nonnull error))failureHandler; -@end -@interface FakeNSXPCConnection () -@property id control; -@end -@implementation FakeNSXPCConnection -- (instancetype) initWithControl:(id)control -{ - self = [super init]; - if (self) { - _control = control; - } - return self; -} -- (id)remoteObjectProxyWithErrorHandler:(void(^)(NSError * _Nonnull error))failureHandler -{ - (void)failureHandler; - return _control; -} -@end - +#import "FakeSOSControl.h" @interface KCPairingTest : XCTestCase @end -@interface FCPairingFakeSOSControl : NSObject -@property (assign) SecKeyRef accountPrivateKey; -@property (assign) SecKeyRef accountPublicKey; -@property (assign) SecKeyRef deviceKey; -@property (assign) SecKeyRef octagonSigningKey; -@property (assign) SOSCircleRef circle; -@property (assign) SOSFullPeerInfoRef fullPeerInfo; -@property (assign) bool application; -@end - -@implementation FCPairingFakeSOSControl - -- (instancetype)initWithRandomAccountKey:(bool)randomAccountKey circle:(SOSCircleRef)circle -{ - if ((self = [super init])) { - SecKeyRef publicKey = NULL; - NSDictionary* parameters = @{ - (__bridge NSString*)kSecAttrKeyType:(__bridge NSString*) kSecAttrKeyTypeEC, - (__bridge NSString*)kSecAttrKeySizeInBits: @(256), - (__bridge NSString*)kSecAttrNoLegacy : @YES, - (__bridge NSString*)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleAfterFirstUnlock, - (__bridge id)kSecPrivateKeyAttrs : @{ - (__bridge NSString*)kSecAttrLabel : @"delete me test case - private", - (__bridge NSString*)kSecAttrIsPermanent : @YES, - (__bridge NSString*)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleAfterFirstUnlock, - }, - (__bridge id)kSecPublicKeyAttrs : @{ - (__bridge NSString*)kSecAttrLabel : @"delete me test case - public", - (__bridge NSString*)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleAfterFirstUnlock, - } - }; - if(SecKeyGeneratePair((__bridge CFDictionaryRef)parameters, &publicKey, &_deviceKey) != 0) { - NSLog(@"failed to create device key"); - return nil; - } - CFReleaseNull(publicKey); - - NSMutableDictionary* octagonParameters = [parameters mutableCopy]; - octagonParameters[(__bridge NSString*)kSecAttrKeySizeInBits] = @(384); - if(SecKeyGeneratePair((__bridge CFDictionaryRef)octagonParameters, &publicKey, &_octagonSigningKey) != 0) { - NSLog(@"failed to create octagon signing key"); - return nil; - } - CFReleaseNull(publicKey); - - _circle = (SOSCircleRef)CFRetain(circle); - - CFErrorRef error = NULL; - - CFDictionaryRef gestalt = (__bridge CFDictionaryRef)@{ - @"ComputerName" : @"name", - }; - - _fullPeerInfo = SOSFullPeerInfoCreate(NULL, gestalt, NULL, _deviceKey, _octagonSigningKey, &error); - CFReleaseNull(error); - - if (randomAccountKey) { - - NSDictionary* accountParams = @{ - (__bridge NSString*)kSecAttrKeyType:(__bridge NSString*) kSecAttrKeyTypeEC, - (__bridge NSString*)kSecAttrKeySizeInBits: @(256), - (__bridge NSString*)kSecAttrNoLegacy : @YES, - (__bridge NSString*)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleAfterFirstUnlock, - }; - - if(SecKeyGeneratePair((__bridge CFDictionaryRef)accountParams, &publicKey, &_accountPrivateKey) != 0) { - NSLog(@"failed to create account signing key"); - return nil; - } - CFReleaseNull(publicKey); - - _accountPublicKey = SecKeyCopyPublicKey(_accountPrivateKey); - - [self signApplicationIfNeeded]; - } - } - return self; -} - -- (void)dealloc -{ - if (_accountPrivateKey) { - SecItemDelete((__bridge CFTypeRef)@{ (__bridge id)kSecValueRef : (__bridge id)_accountPrivateKey }); - CFReleaseNull(_accountPrivateKey); - } - if (_deviceKey) { - SecItemDelete((__bridge CFTypeRef)@{ (__bridge id)kSecValueRef : (__bridge id)_deviceKey }); - CFReleaseNull(_deviceKey); - } - if (_octagonSigningKey) { - SecItemDelete((__bridge CFTypeRef)@{ (__bridge id)kSecValueRef : (__bridge id)_octagonSigningKey }); - CFReleaseNull(_octagonSigningKey); - } - CFReleaseNull(_circle); - CFReleaseNull(_fullPeerInfo); -} - -- (SOSPeerInfoRef)peerInfo -{ - return SOSFullPeerInfoGetPeerInfo(_fullPeerInfo); -} - -- (void)signApplicationIfNeeded -{ - CFErrorRef error = NULL; - - _application = SOSFullPeerInfoPromoteToApplication(_fullPeerInfo, _accountPrivateKey, &error); - if (!_application) - abort(); -} - -- (void)initialSyncCredentials:(uint32_t)flags complete:(void (^)(NSArray *, NSError *))complete -{ - complete(@[], NULL); -} - -- (void)importInitialSyncCredentials:(NSArray *)items complete:(void (^)(bool success, NSError *))complete -{ - complete(true, NULL); -} - -- (void)triggerSync:(NSArray *)peers complete:(void(^)(bool success, NSError *))complete -{ - complete(true, NULL); -} - -//MARK - FCPairingFakeSOSControl SOSControlProtocol - -- (void)userPublicKey:(void ((^))(BOOL trusted, NSData *spki, NSError *error))complete -{ - complete(false, NULL, NULL); -} - -- (void)performanceCounters:(void(^)(NSDictionary *))complete -{ - complete(@{}); -} -- (void)kvsPerformanceCounters:(void(^)(NSDictionary *))complete -{ - complete(@{}); -} -- (void)idsPerformanceCounters:(void(^)(NSDictionary *))complete -{ - complete(@{}); -} -- (void)rateLimitingPerformanceCounters:(void(^)(NSDictionary *))complete -{ - complete(@{}); -} -- (void)stashedCredentialPublicKey:(void(^)(NSData *, NSError *error))complete -{ - NSData *publicKey = NULL; - NSError *error = NULL; - if (self.accountPrivateKey) { - publicKey = CFBridgingRelease(SecKeyCopySubjectPublicKeyInfo(self.accountPrivateKey)); - } else { - error = [NSError errorWithDomain:@"FCPairingFakeSOSControl" code:2 userInfo:NULL]; - } - complete(publicKey, error); -} - -- (void)assertStashedAccountCredential:(void(^)(BOOL result, NSError *error))complete -{ - complete(self.accountPrivateKey != NULL, NULL); -} - -- (void)validatedStashedAccountCredential:(void(^)(NSData *credential, NSError *error))complete -{ - NSData *key = NULL; - CFErrorRef error = NULL; - if (self.accountPrivateKey) { - key = CFBridgingRelease(SecKeyCopyExternalRepresentation(self.accountPrivateKey, &error)); - } else { - error = (CFErrorRef)CFBridgingRetain([NSError errorWithDomain:@"FCPairingFakeSOSControl" code:1 userInfo:NULL]); - } - complete(key, (__bridge NSError *)error); - CFReleaseNull(error); -} - -- (void)stashAccountCredential:(NSData *)credential complete:(void(^)(bool success, NSError *error))complete -{ - 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); - CFReleaseNull(error); - return; - } - - _accountPrivateKey = accountPrivateKey; - _accountPublicKey = SecKeyCopyPublicKey(_accountPrivateKey); - - [self signApplicationIfNeeded]; - - complete(true, NULL); -} +@implementation KCPairingTest -- (void)myPeerInfo:(void(^)(NSData *application, NSError *error))complete +- (void)checkRoundtrip:(KCPairingChannelContext *)c1 check:(NSString *)check { - CFErrorRef error = NULL; + KCPairingChannelContext *c2; + NSData *data; - [self signApplicationIfNeeded]; + data = [NSKeyedArchiver archivedDataWithRootObject:c1 requiringSecureCoding:TRUE error:NULL]; + XCTAssertNotNil(data, "data should be valid: %@", check); - NSData *application = CFBridgingRelease(SOSPeerInfoCopyEncodedData([self peerInfo], NULL, &error)); - complete(application, (__bridge NSError *)error); + NSKeyedUnarchiver* unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data error:nil]; + c2 = [unarchiver decodeObjectOfClass:[KCPairingChannelContext class] forKey:NSKeyedArchiveRootObjectKey]; - CFReleaseNull(error); + XCTAssertEqualObjects(c1, c2, "c1 should be same as c2: %@", check); } -- (void)circleJoiningBlob:(NSData *)applicantData complete:(void (^)(NSData *blob, NSError *))complete -{ - CFErrorRef error = NULL; - CFDataRef signature = NULL; - SOSCircleRef prunedCircle = SOSCircleCopyCircle(NULL, _circle, &error); - (void)SOSCirclePreGenerationSign(prunedCircle, _accountPublicKey, &error); - - SOSGenCountRef gencount = SOSGenerationIncrementAndCreate(SOSCircleGetGeneration(prunedCircle)); - if (gencount == NULL) - abort(); - +- (void)testPairingChannelContextValid { + KCPairingChannelContext *c; - SOSPeerInfoRef applicant = SOSPeerInfoCreateFromData(NULL, &error, (__bridge CFDataRef)applicantData); - if (applicant == NULL) - abort(); + c = [[KCPairingChannelContext alloc] init]; - signature = SOSCircleCopyNextGenSignatureWithPeerAdded(prunedCircle, applicant, _deviceKey, &error); + [self checkRoundtrip:c check:@"empty"]; - NSData *pbblob = CFBridgingRelease(SOSPiggyBackBlobCopyEncodedData(gencount, _deviceKey, signature, &error)); + c.intent = KCPairingIntent_Type_None; + [self checkRoundtrip:c check:@"with intent"]; - CFReleaseNull(signature); - CFReleaseNull(gencount); - CFReleaseNull(prunedCircle); - - complete(pbblob, NULL); + c.intent = @"invalid"; } -- (void)joinCircleWithBlob:(NSData *)blob version:(PiggyBackProtocolVersion)version complete:(void (^)(bool success, NSError *))complete -{ - SOSGenCountRef gencount = NULL; - SecKeyRef pubKey = NULL; - CFDataRef signature = NULL; - CFErrorRef error = NULL; - bool setInitialSyncTimeoutToV0 = false; - - if (!SOSPiggyBackBlobCreateFromData(&gencount, &pubKey, &signature, (__bridge CFDataRef)blob, kPiggyV1, &setInitialSyncTimeoutToV0, &error)) { - complete(true, (__bridge NSError *)error); - CFReleaseNull(error); - return; - } - - (void)SOSCircleAcceptPeerFromHSA2(_circle, - _accountPrivateKey, - gencount, - pubKey, - signature, - _fullPeerInfo, - &error); +- (void)testPairingChannelContextInvalid { + KCPairingChannelContext *c1, *c2; + NSData *data; - CFReleaseNull(gencount); - CFReleaseNull(pubKey); - CFReleaseNull(signature); + c1 = [[KCPairingChannelContext alloc] init]; + c1.intent = @"invalid"; - complete(true, (__bridge NSError *)error); + data = [NSKeyedArchiver archivedDataWithRootObject:c1 requiringSecureCoding:TRUE error:NULL]; + XCTAssertNotNil(data, "data should be valid"); - CFReleaseNull(error); + NSKeyedUnarchiver* unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data error:nil]; + c2 = [unarchiver decodeObjectOfClass:[KCPairingChannelContext class] forKey:NSKeyedArchiveRootObjectKey]; + XCTAssertNil(c2, "c2 should be NULL"); } -- (void)getWatchdogParameters:(void (^)(NSDictionary*, NSError*))complete -{ - // intentionally left blank - // these are used by the security/2 tool and are only declared here to make the compiler happy about conforming the protocol we shoved the methods into -} - - -- (void)setWatchdogParmeters:(NSDictionary*)parameters complete:(void (^)(NSError*))complete -{ - // intentionally left blank - // these are used by the security/2 tool and are only declared here to make the compiler happy about conforming the protocol we shoved the methods into -} - - -@end - -@implementation KCPairingTest - -- (void)testSecPairBasicTest -{ - bool sp1compete = false, sp2compete = false; - NSData *sp1data = NULL; - NSData *sp2data = NULL; - SOSCircleRef circle = NULL; - unsigned count = 0; - CFErrorRef cferror = NULL; - KCPairingChannel *sp1, *sp2; - - circle = SOSCircleCreate(NULL, CFSTR("TEST DOMAIN"), NULL); - XCTAssert(circle, "circle"); - - FCPairingFakeSOSControl *fc1 = [[FCPairingFakeSOSControl alloc] initWithRandomAccountKey:false circle:circle]; - XCTAssert(fc1, "create fake soscontrol 1"); - - FCPairingFakeSOSControl *fc2 = [[FCPairingFakeSOSControl alloc] initWithRandomAccountKey:true circle:circle]; - XCTAssert(fc2, "create fake soscontrol 2"); - - - XCTAssert(SOSCircleRequestAdmission(circle, fc2.accountPrivateKey, fc2.fullPeerInfo, &cferror), "SOSCircleRequestAdmission: %@", cferror); - CFReleaseNull(cferror); - - XCTAssert(SOSCircleAcceptRequest(circle, fc2.accountPrivateKey, fc2.fullPeerInfo, [fc2 peerInfo], &cferror), "SOSCircleAcceptRequest device 1: %@", cferror); - CFReleaseNull(cferror); - - XCTAssert(SOSCircleHasPeer(circle, [fc2 peerInfo], &cferror), "HasPeer 2: %@", cferror); - CFReleaseNull(cferror); - - - sp1 = [KCPairingChannel pairingChannelInitiator:NULL]; - [sp1 setXPCConnectionObject:(NSXPCConnection *)[[FakeNSXPCConnection alloc] initWithControl:fc1]]; - - sp2 = [KCPairingChannel pairingChannelAcceptor:NULL]; - [sp2 setXPCConnectionObject:(NSXPCConnection *)[[FakeNSXPCConnection alloc] initWithControl:fc2]] ; - - while(1) { - NSError *error = NULL; - - sp1data = [sp1 exchangePacket:sp2data complete:&sp1compete error:&error]; - - if (sp1compete && sp2compete) { - XCTAssert(sp1data == NULL, "sp1 done, yet there is data"); - break; - } - XCTAssert(!sp2compete, "sp2 completed w/o sp1"); - - XCTAssert(sp1data != NULL, "sp1 not done, yet there is no data: %@", error); - if (sp1data == NULL) - break; - - /* send sp1data to peer : BOB CHANNEL HERE */ - - sp2data = [sp2 exchangePacket:sp1data complete:&sp2compete error:&error]; - XCTAssert(sp2data != NULL, "sp2 didn't return data: %@", error); - if (sp2data == NULL) - break; - - if (sp1compete && sp2compete) - break; - - XCTAssert(!sp1compete, "sp2 completed w/o sp1"); - - count++; - if (count > 10) - abort(); - }; - - XCTAssert(sp1compete && sp2compete, "both parties not completed"); - - XCTAssert(fc1.accountPrivateKey, "no accountPrivateKey in fc1"); - XCTAssert(fc2.accountPrivateKey, "no accountPrivateKey in fc2"); - XCTAssert(CFEqualSafe(fc1.accountPrivateKey, fc2.accountPrivateKey), "no accountPrivateKey not same in both"); - - if (sp1compete && sp2compete) - NSLog(@"pairing complete"); - - XCTAssert(SOSCircleHasPeer(circle, [fc1 peerInfo], &cferror), "HasPeer 1: %@", cferror); - CFReleaseNull(cferror); - XCTAssert(SOSCircleHasPeer(circle, [fc2 peerInfo], &cferror), "HasPeer 2: %@", cferror); - CFReleaseNull(cferror); - - XCTAssert(sp1.needInitialSync == false, "no longer need initial sync"); - - -} @end diff --git a/KeychainCircle/generated_source/KCInitialMessageData.h b/KeychainCircle/generated_source/KCInitialMessageData.h new file mode 100644 index 000000000..41b4830b1 --- /dev/null +++ b/KeychainCircle/generated_source/KCInitialMessageData.h @@ -0,0 +1,35 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from KCInitialMessageData.proto + +#import +#import + +#ifdef __cplusplus +#define KCINITIALMESSAGEDATA_FUNCTION extern "C" +#else +#define KCINITIALMESSAGEDATA_FUNCTION extern +#endif + +@interface KCInitialMessageData : PBCodable +{ + NSData *_prepareMessage; +} + + +@property (nonatomic, readonly) BOOL hasPrepareMessage; +@property (nonatomic, retain) NSData *prepareMessage; + +// Performs a shallow copy into other +- (void)copyTo:(KCInitialMessageData *)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:(KCInitialMessageData *)other; + +KCINITIALMESSAGEDATA_FUNCTION BOOL KCInitialMessageDataReadFrom(__unsafe_unretained KCInitialMessageData *self, __unsafe_unretained PBDataReader *reader); + +@end + diff --git a/KeychainCircle/generated_source/KCInitialMessageData.m b/KeychainCircle/generated_source/KCInitialMessageData.m new file mode 100644 index 000000000..1762d809f --- /dev/null +++ b/KeychainCircle/generated_source/KCInitialMessageData.m @@ -0,0 +1,124 @@ +// This file was automatically generated by protocompiler +// DO NOT EDIT! +// Compiled from KCInitialMessageData.proto + +#import "KCInitialMessageData.h" +#import +#import +#import + +#if !__has_feature(objc_arc) +# error This generated file depends on ARC but it is not enabled; turn on ARC, or use 'objc_use_arc' option to generate non-ARC code. +#endif + +@implementation KCInitialMessageData + +- (BOOL)hasPrepareMessage +{ + return _prepareMessage != nil; +} +@synthesize prepareMessage = _prepareMessage; + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], [self dictionaryRepresentation]]; +} + +- (NSDictionary *)dictionaryRepresentation +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self->_prepareMessage) + { + [dict setObject:self->_prepareMessage forKey:@"prepareMessage"]; + } + return dict; +} + +BOOL KCInitialMessageDataReadFrom(__unsafe_unretained KCInitialMessageData *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 /* prepareMessage */: + { + NSData *new_prepareMessage = PBReaderReadData(reader); + self->_prepareMessage = new_prepareMessage; + } + break; + default: + if (!PBReaderSkipValueWithTag(reader, tag, aType)) + return NO; + break; + } + } + return !PBReaderHasError(reader); +} + +- (BOOL)readFrom:(PBDataReader *)reader +{ + return KCInitialMessageDataReadFrom(self, reader); +} +- (void)writeTo:(PBDataWriter *)writer +{ + /* prepareMessage */ + { + if (self->_prepareMessage) + { + PBDataWriterWriteDataField(writer, self->_prepareMessage, 1); + } + } +} + +- (void)copyTo:(KCInitialMessageData *)other +{ + if (_prepareMessage) + { + other.prepareMessage = _prepareMessage; + } +} + +- (id)copyWithZone:(NSZone *)zone +{ + KCInitialMessageData *copy = [[[self class] allocWithZone:zone] init]; + copy->_prepareMessage = [_prepareMessage copyWithZone:zone]; + return copy; +} + +- (BOOL)isEqual:(id)object +{ + KCInitialMessageData *other = (KCInitialMessageData *)object; + return [other isMemberOfClass:[self class]] + && + ((!self->_prepareMessage && !other->_prepareMessage) || [self->_prepareMessage isEqual:other->_prepareMessage]) + ; +} + +- (NSUInteger)hash +{ + return 0 + ^ + [self->_prepareMessage hash] + ; +} + +- (void)mergeFrom:(KCInitialMessageData *)other +{ + if (other->_prepareMessage) + { + [self setPrepareMessage:other->_prepareMessage]; + } +} + +@end + diff --git a/KeychainEntitledTestApp_ios/Assets.xcassets/AppIcon.appiconset/Contents.json b/KeychainEntitledTestApp_ios/Assets.xcassets/AppIcon.appiconset/Contents.json index 1d060ed28..d8db8d65f 100644 --- a/KeychainEntitledTestApp_ios/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/KeychainEntitledTestApp_ios/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -84,6 +84,11 @@ "idiom" : "ipad", "size" : "83.5x83.5", "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" } ], "info" : { diff --git a/KeychainEntitledTestApp_ios/Base.lproj/LaunchScreen.storyboard b/KeychainEntitledTestApp_ios/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index fdf3f97d1..000000000 --- a/KeychainEntitledTestApp_ios/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/KeychainEntitledTestApp_ios/Base.lproj/Main.storyboard b/KeychainEntitledTestApp_ios/Base.lproj/Main.storyboard deleted file mode 100644 index 4529698c4..000000000 --- a/KeychainEntitledTestApp_ios/Base.lproj/Main.storyboard +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/KeychainEntitledTestApp_mac/Base.lproj/Main.storyboard b/KeychainEntitledTestApp_mac/Base.lproj/Main.storyboard deleted file mode 100644 index 6f7fdad6c..000000000 --- a/KeychainEntitledTestApp_mac/Base.lproj/Main.storyboard +++ /dev/null @@ -1,693 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/KeychainEntitledTestApp_mac/Info.plist b/KeychainEntitledTestApp_mac/Info.plist index f16cc0681..8a4ebbf1c 100644 --- a/KeychainEntitledTestApp_mac/Info.plist +++ b/KeychainEntitledTestApp_mac/Info.plist @@ -22,8 +22,6 @@ 1 LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) - NSMainStoryboardFile - Main NSPrincipalClass NSApplication diff --git a/KeychainSyncAccountNotification/KeychainSyncAccountNotification-Info.plist b/KeychainSyncAccountNotification/KeychainSyncAccountNotification-Info.plist index 40f3f2eaa..a1b3b5c74 100644 --- a/KeychainSyncAccountNotification/KeychainSyncAccountNotification-Info.plist +++ b/KeychainSyncAccountNotification/KeychainSyncAccountNotification-Info.plist @@ -27,6 +27,7 @@ ACSupportedAccountTypes com.apple.account.AppleAccount + com.apple.account.idms diff --git a/KeychainSyncAccountNotification/KeychainSyncAccountNotification.m b/KeychainSyncAccountNotification/KeychainSyncAccountNotification.m index 2aeb9955f..7120509f0 100644 --- a/KeychainSyncAccountNotification/KeychainSyncAccountNotification.m +++ b/KeychainSyncAccountNotification/KeychainSyncAccountNotification.m @@ -6,50 +6,154 @@ #import "KeychainSyncAccountNotification.h" #import #import -#if TARGET_OS_IPHONE #import -#else -#import -#endif #import #import - +#import +#import +#if OCTAGON +#import +#include +#endif #import "utilities/debugging.h" +#import "OT.h" @implementation KeychainSyncAccountNotification - (bool)accountIsPrimary:(ACAccount *)account { -#if TARGET_OS_IPHONE - return [account aa_isPrimaryAccount]; -#else - return [account icaIsPrimaryAccount]; -#endif + return [account aa_isAccountClass:AAAccountClassPrimary]; } -- (BOOL)account:(ACAccount *)account willChangeWithType:(ACAccountChangeType)changeType inStore:(ACDAccountStore *)store oldAccount:(ACAccount *)oldAccount { - NSString* oldAccountIdentifier = oldAccount.identifier; - NSString* accountIdentifier = account.identifier; - +// this is where we initialize SOS and OT for account sign-in +// in the future we may bring this logic over to KeychainDataclassOwner and delete KeychainSyncAccountNotification, but accounts people say that's a change that today would require coordination across multiple teams +// was asked to file this radar for accounts: Invoke DataclassOwner when enabling or signing into an account +- (void)account:(ACAccount *)account didChangeWithType:(ACAccountChangeType)changeType inStore:(ACDAccountStore *)store oldAccount:(ACAccount *)oldAccount { + + if((changeType == kACAccountChangeTypeAdded || changeType == kACAccountChangeTypeModified) && + [account.accountType.identifier isEqualToString: ACAccountTypeIdentifierAppleAccount] && + [self accountIsPrimary:account]) { + +#if OCTAGON + if(OctagonIsEnabled()){ + __block NSError* error = nil; + + NSString* altDSID = [account aa_altDSID]; + + OTControl* otcontrol = [OTControl controlObject:&error]; + + if (nil == otcontrol) { + secerror("octagon: Failed to get OTControl: %@", error.localizedDescription); + } else { + dispatch_semaphore_t sema = dispatch_semaphore_create(0); + + [otcontrol signIn:altDSID container:nil context:OTDefaultContext reply:^(NSError * _Nullable signedInError) { + if(signedInError) { + secerror("octagon: error signing in: %s", [[signedInError description] UTF8String]); + } else { + secnotice("octagon", "account now signed in for octagon operation"); + } + dispatch_semaphore_signal(sema); + + }]; + if (0 != dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 60 * 5))) { + secerror("octagon: Timed out signing in"); + } + } + }else{ + secerror("Octagon not enabled; not signing in"); + } +#endif + } + + // If there is any change to any AuthKit account's security level, notify octagon + +#if OCTAGON + if([account.accountType.identifier isEqualToString: ACAccountTypeIdentifierIDMS]) { + secnotice("octagon-authkit", "Received an IDMS account modification"); + + AKAccountManager *manager = [AKAccountManager sharedInstance]; + + AKAppleIDSecurityLevel oldSecurityLevel = [manager securityLevelForAccount:oldAccount]; + AKAppleIDSecurityLevel newSecurityLevel = [manager securityLevelForAccount:account]; + + if(oldSecurityLevel != newSecurityLevel) { + NSString* identifier = account.identifier; + secnotice("octagon-authkit", "IDMS security level has now moved to %ld for %@", (unsigned long)newSecurityLevel, identifier); + + __block NSError* error = nil; + OTControl* otcontrol = [OTControl controlObject:&error]; + if(!otcontrol || error) { + secerror("octagon-authkit: Failed to get OTControl: %@", error); + } else { + dispatch_semaphore_t sema = dispatch_semaphore_create(0); + + [otcontrol notifyIDMSTrustLevelChangeForContainer:nil context:OTDefaultContext reply:^(NSError * _Nullable idmsError) { + if(idmsError) { + secerror("octagon-authkit: error with idms trust level change in: %s", [[idmsError description] UTF8String]); + } else { + secnotice("octagon-authkit", "informed octagon of IDMS trust level change"); + } + dispatch_semaphore_signal(sema); + }]; + + if (0 != dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 5))) { + secerror("octagon-authkit: Timed out altering IDMS change in"); + } + } + + } else { + secnotice("octagon-authkit", "No change to IDMS security level"); + } + } +#endif + if ((changeType == kACAccountChangeTypeDeleted) && [oldAccount.accountType.identifier isEqualToString:ACAccountTypeIdentifierAppleAccount]) { - if(oldAccountIdentifier != NULL && oldAccount.username !=NULL) { + + NSString *accountIdentifier = oldAccount.identifier; + NSString *username = oldAccount.username; + + if(accountIdentifier != NULL && username !=NULL) { if ([self accountIsPrimary:oldAccount]) { CFErrorRef removalError = NULL; - - secinfo("accounts", "Performing SOS circle credential removal for account %@: %@", oldAccountIdentifier, oldAccount.username); - + + secinfo("accounts", "Performing SOS circle credential removal for account %@: %@", accountIdentifier, username); + if (!SOSCCLoggedOutOfAccount(&removalError)) { - secerror("Account %@ could not leave the SOS circle: %@", oldAccountIdentifier, removalError); + secerror("Account %@ could not leave the SOS circle: %@", accountIdentifier, removalError); } - } else { - secinfo("accounts", "NOT performing SOS circle credential removal for secondary account %@: %@", accountIdentifier, account.username); + +#if OCTAGON + if(OctagonIsEnabled()){ + __block NSError* error = nil; + + OTControl* otcontrol = [OTControl controlObject:&error]; + + if (nil == otcontrol) { + secerror("octagon: Failed to get OTControl: %@", error.localizedDescription); + } else { + dispatch_semaphore_t sema = dispatch_semaphore_create(0); + + [otcontrol signOut:nil context:OTDefaultContext reply:^(NSError * _Nullable signedInError) { + if(signedInError) { + secerror("octagon: error signing out: %s", [[signedInError description] UTF8String]); + } else { + secnotice("octagon", "signed out of octagon trust"); + } + dispatch_semaphore_signal(sema); + + }]; + if (0 != dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 60 * 5))) { + secerror("octagon: Timed out signing out"); + } + } + } else { + secerror("Octagon not enabled; not signing out"); + } +#endif } - } else{ - secinfo("accounts", "Already logged out of account"); } } - - return YES; } @end diff --git a/KeychainSyncingOverIDSProxy/IDSPersistentState.h b/KeychainSyncingOverIDSProxy/IDSPersistentState.h deleted file mode 100644 index ce5da2d4e..000000000 --- a/KeychainSyncingOverIDSProxy/IDSPersistentState.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -// -// IDSPersistentState.h -// - -#import - -@interface KeychainSyncingOverIDSProxyPersistentState : NSObject -{ -} - -+ (id)read:(NSURL *)path error:(NSError **)error; -+ (BOOL)write:(NSURL *)path data:(id)plist error:(NSError **)error; -+ (NSString *)dictionaryDescription: (NSDictionary *)state; -+ (NSMutableDictionary *)idsState; -+ (void)setUnhandledMessages: (NSDictionary *)unhandledMessages; -+ (NSURL *)registrationFileURL; - -@end - diff --git a/KeychainSyncingOverIDSProxy/IDSPersistentState.m b/KeychainSyncingOverIDSProxy/IDSPersistentState.m deleted file mode 100644 index 0c8844674..000000000 --- a/KeychainSyncingOverIDSProxy/IDSPersistentState.m +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -// -// IDSPersistentState.m -// - -#import -#import -#import -#import -#import -#import -#import -#import - -#import "IDSPersistentState.h" - -#if ! __has_feature(objc_arc) -#error This file must be compiled with ARC. Either turn on ARC for the project or use -fobjc-arc flag -#endif - -static CFStringRef kRegistrationFileName = CFSTR("com.apple.security.keychainsyncingoveridsproxy.unhandledMessages.plist"); - -@implementation KeychainSyncingOverIDSProxyPersistentState - -+ (BOOL)write:(NSURL *)path data:(id)plist error:(NSError **)error -{ - if (![NSPropertyListSerialization propertyList: plist isValidForFormat: NSPropertyListXMLFormat_v1_0]) - { - secerror("can't save PersistentState as XML"); - return false; - } - - NSData *data = [NSPropertyListSerialization dataWithPropertyList: plist - format: NSPropertyListXMLFormat_v1_0 options: 0 error: error]; - if (data == nil) - { - secerror("error serializing PersistentState to xml: %@", *error); - return false; - } - - BOOL writeStatus = [data writeToURL: path options: NSDataWritingAtomic error: error]; - if (!writeStatus) - secerror("error writing PersistentState to file: %@", *error); - - return writeStatus; -} - -+ (id)read: (NSURL *)path error:(NSError **)error -{ - NSData *data = [NSData dataWithContentsOfURL: path options: 0 error: error]; - if (data == nil) - { - secdebug("unhandledmessages", "error reading PersistentState from %@: %@", path, *error); - return nil; - } - - // Now the deserializing: - - NSPropertyListFormat format; - id plist = [NSPropertyListSerialization propertyListWithData: data - options: NSPropertyListMutableContainersAndLeaves format: &format error: error]; - - if (plist == nil) - secerror("could not deserialize PersistentState from %@: %@", path, *error); - - return plist; -} - -+ (NSURL *)registrationFileURL -{ - return (NSURL *)CFBridgingRelease(SecCopyURLForFileInPreferencesDirectory(kRegistrationFileName)); -} - -+ (NSString *)dictionaryDescription: (NSDictionary *)state -{ - NSMutableArray *elements = [NSMutableArray array]; - [state enumerateKeysAndObjectsUsingBlock: ^(NSString *key, id obj, BOOL *stop) { - [elements addObject: [key stringByAppendingString: @":"]]; - if ([obj isKindOfClass:[NSArray class]]) { - [elements addObject: [(NSArray *)obj componentsJoinedByString: @" "]]; - } else { - [elements addObject: [NSString stringWithFormat:@"%@", obj]]; - } - }]; - return [elements componentsJoinedByString: @" "]; -} - -+ (NSMutableDictionary *)idsState -{ - NSError *error = NULL; - id stateDictionary = [KeychainSyncingOverIDSProxyPersistentState read:[[self class] registrationFileURL] error:&error]; - secdebug("keyregister", "Read registeredKeys: <%@>", [self dictionaryDescription: stateDictionary]); - // Ignore older states with an NSArray - if (![stateDictionary isKindOfClass:[NSDictionary class]]) - return NULL; - return [NSMutableDictionary dictionaryWithDictionary:stateDictionary]; -} - -+ (void)setUnhandledMessages: (NSDictionary *)unhandledMessages -{ - NSError *error = NULL; - secdebug("IDS unhandled message", "Write unhandled Messages and monitor state: <%@>", [self dictionaryDescription: unhandledMessages]); - [KeychainSyncingOverIDSProxyPersistentState write:[[self class] registrationFileURL] data:unhandledMessages error:&error]; -} - -@end diff --git a/KeychainSyncingOverIDSProxy/IDSProxy.h b/KeychainSyncingOverIDSProxy/IDSProxy.h deleted file mode 100644 index 9985fe041..000000000 --- a/KeychainSyncingOverIDSProxy/IDSProxy.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2012-2017 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#import -#import -#import -#import -#import "SOSCloudKeychainClient.h" -#import -#import - -typedef enum { - kIDSStartPingTestMessage = 1, - kIDSEndPingTestMessage= 2, - kIDSSendOneMessage = 3, - kIDSPeerReceivedACK = 4, - kIDSPeerAvailability = 6, - kIDSPeerAvailabilityDone = 7, - kIDSKeychainSyncIDSFragmentation = 8, -} idsOperation; - -@interface KeychainSyncingOverIDSProxy : NSObject -{ - IDSService *_service; - NSString *deviceID; - NSMutableDictionary *deviceIDFromAuthToken; -} - -@property (retain, nonatomic) NSMutableDictionary *deviceIDFromAuthToken; -@property (retain, nonatomic) NSString *deviceID; -@property (retain, nonatomic) NSMutableDictionary *shadowPendingMessages; -@property (retain, nonatomic) NSMutableDictionary *allFragmentedMessages; -@property (retain, atomic) NSMutableDictionary *pingTimers; -@property (retain, nonatomic) NSMutableDictionary *peerNextSendCache; //dictionary of device ID -> time stamp of when to send next - -// Only touch these three dictionaries from the dataQueue or you will crash, eventually. -@property (retain, nonatomic) NSMutableDictionary *messagesInFlight; -@property (retain, nonatomic) NSMutableDictionary *unhandledMessageBuffer; -@property (retain, nonatomic) NSMutableDictionary *monitor; - -@property (retain, nonatomic) NSArray* listOfDevices; - -@property (atomic) dispatch_source_t penaltyTimer; -@property (atomic) bool penaltyTimerScheduled; -@property (retain, atomic) NSDictionary *queuedMessages; - -@property (retain, atomic) NSMutableDictionary *counterValues; -@property (atomic) NSInteger outgoingMessages; -@property (atomic) NSInteger incomingMessages; - -@property (atomic) bool isIDSInitDone; -@property (atomic) bool shadowDoInitializeIDSService; -@property (atomic) bool isSecDRunningAsRoot; -@property (atomic) bool doesSecDHavePeer; - -@property (atomic) dispatch_queue_t calloutQueue; -@property (atomic) dispatch_queue_t pingQueue; -@property dispatch_queue_t dataQueue; - -@property (atomic) bool isLocked; -@property (atomic) bool unlockedSinceBoot; -@property (atomic) dispatch_source_t retryTimer; -@property (atomic) bool retryTimerScheduled; -@property (atomic) bool inCallout; -@property (atomic) bool setIDSDeviceID; -@property (atomic) bool shadowDoSetIDSDeviceID; - -@property (atomic) bool handleAllPendingMessages; -@property (atomic) bool shadowHandleAllPendingMessages; -@property (atomic) bool sendRestoredMessages; - -+ (KeychainSyncingOverIDSProxy *) idsProxy; - -- (id)init; - -- (void) doSetIDSDeviceID; -- (void) doIDSInitialization; -- (void) calloutWith: (void(^)(NSMutableDictionary *pending, - bool handlePendingMesssages, - bool doSetDeviceID, - dispatch_queue_t queue, - void(^done)(NSMutableDictionary *handledMessages, - bool handledPendingMessage, - bool handledSettingDeviceID))) callout; -- (void) sendKeysCallout: (NSMutableDictionary *(^)(NSMutableDictionary* pending, NSError** error)) handleMessages; -- (void) persistState; -- (void) sendPersistedMessagesAgain; -- (NSDictionary*) retrievePendingMessages; -- (NSDictionary*) collectStats; -- (void) scheduleRetryRequestTimer; -- (BOOL) haveMessagesInFlight; -@end - -NSString* createErrorString(NSString* format, ...) - NS_FORMAT_FUNCTION(1, 2); diff --git a/KeychainSyncingOverIDSProxy/IDSProxy.m b/KeychainSyncingOverIDSProxy/IDSProxy.m deleted file mode 100644 index c6cbe5bb5..000000000 --- a/KeychainSyncingOverIDSProxy/IDSProxy.m +++ /dev/null @@ -1,558 +0,0 @@ -/* - * Copyright (c) 2012-2017 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#import -#import - -#import -#import -#import -#import - -#include -#include -#include -#include - -#import -#import - -#include -#include -#include -#include - -#import "IDSProxy.h" -#import "KeychainSyncingOverIDSProxy+ReceiveMessage.h" -#import "KeychainSyncingOverIDSProxy+SendMessage.h" -#import "IDSPersistentState.h" - -#define kSecServerKeychainChangedNotification "com.apple.security.keychainchanged" -#define kSecServerPeerInfoAvailable "com.apple.security.fpiAvailable" - -#define IDSServiceNameKeychainSync "com.apple.private.alloy.keychainsync" -static NSString *kMonitorState = @"MonitorState"; -static NSString *kExportUnhandledMessages = @"UnhandledMessages"; -static NSString *kMessagesInFlight = @"MessagesInFlight"; -static const char *kStreamName = "com.apple.notifyd.matching"; -static NSString *const kIDSMessageUseACKModel = @"UsesAckModel"; - -static NSString *const kOutgoingMessages = @"IDS Outgoing Messages"; -static NSString *const kIncomingMessages = @"IDS Incoming Messages"; - -NSString *const IDSSendMessageOptionForceEncryptionOffKey = @"IDSSendMessageOptionForceEncryptionOff"; -static const int64_t kRetryTimerLeeway = (NSEC_PER_MSEC * 250); // 250ms leeway for handling unhandled messages. -static const int64_t kMinMessageRetryDelay = (NSEC_PER_SEC * 8); - -CFIndex SECD_RUN_AS_ROOT_ERROR = 1041; - -#define IDSPROXYSCOPE "IDSProxy" - -@implementation KeychainSyncingOverIDSProxy - -@synthesize deviceID = deviceID; -@synthesize deviceIDFromAuthToken = deviceIDFromAuthToken; - -+ (KeychainSyncingOverIDSProxy *) idsProxy -{ - static KeychainSyncingOverIDSProxy *idsProxy; - if (!idsProxy) { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - idsProxy = [[self alloc] init]; - }); - } - return idsProxy; -} - --(NSDictionary*) exportState -{ - return @{ kMonitorState:self.monitor, - kExportUnhandledMessages:self.unhandledMessageBuffer, - kMessagesInFlight:self.messagesInFlight - }; - -} - --(NSDictionary*) retrievePendingMessages -{ - NSDictionary * __block messages; - dispatch_sync(self.dataQueue, ^{ - messages = [[KeychainSyncingOverIDSProxy idsProxy].messagesInFlight copy]; - }); - return messages; -} - -@synthesize unhandledMessageBuffer = _unhandledMessageBuffer; - -- (NSMutableDictionary *) unhandledMessageBuffer { - dispatch_assert_queue(self.dataQueue); - return _unhandledMessageBuffer; -} - -- (void) setUnhandledMessageBuffer:(NSMutableDictionary *)unhandledMessageBuffer { - dispatch_assert_queue(self.dataQueue); - _unhandledMessageBuffer = unhandledMessageBuffer; -} - -@ synthesize messagesInFlight = _messagesInFlight; - -- (NSMutableDictionary *) messagesInFlight { - dispatch_assert_queue(self.dataQueue); - return _messagesInFlight; -} - -- (void) setMessagesInFlight:(NSMutableDictionary *)messagesInFlight { - dispatch_assert_queue(self.dataQueue); - _messagesInFlight = messagesInFlight; -} - -@synthesize monitor = _monitor; - -- (NSMutableDictionary *) monitor { - dispatch_assert_queue(self.dataQueue); - return _monitor; -} - -- (void) setMonitor:(NSMutableDictionary *)monitor { - dispatch_assert_queue(self.dataQueue); - _monitor = monitor; -} - -- (void) persistState -{ - dispatch_sync(self.dataQueue, ^{ - [KeychainSyncingOverIDSProxyPersistentState setUnhandledMessages:[self exportState]]; - }); -} - -- (BOOL) haveMessagesInFlight { - BOOL __block inFlight = NO; - dispatch_sync(self.dataQueue, ^{ - inFlight = [self.messagesInFlight count] > 0; - }); - return inFlight; -} - -- (void) sendPersistedMessagesAgain -{ - NSMutableDictionary * __block copy; - - dispatch_sync(self.dataQueue, ^{ - copy = [NSMutableDictionary dictionaryWithDictionary:self.messagesInFlight]; - }); - - if(copy && [copy count] > 0){ - [copy enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { - NSDictionary* idsMessage = (NSDictionary*)obj; - NSString *uniqueMessageID = (NSString*)key; - - NSString *peerID = (NSString*)[idsMessage objectForKey:(__bridge NSString*)kIDSMessageRecipientPeerID]; - NSString *ID = (NSString*)[idsMessage objectForKey:(__bridge NSString*)kIDSMessageRecipientDeviceID]; - - dispatch_sync(self.dataQueue, ^{ - [self.messagesInFlight removeObjectForKey:key]; - }); - - if (!peerID || !ID) { - return; - } - secnotice("IDS Transport", "sending this message: %@", idsMessage); - if([self sendIDSMessage:idsMessage name:ID peer:peerID]){ - NSString *useAckModel = [idsMessage objectForKey:kIDSMessageUseACKModel]; - if([useAckModel compare:@"YES"] == NSOrderedSame){ - secnotice("IDS Transport", "setting timer!"); - [self setMessageTimer:uniqueMessageID deviceID:ID message:idsMessage]; - } - } - }]; - } -} - -- (id)init -{ - if (self = [super init]) - { - secnotice("event", "%@ start", self); - - _isIDSInitDone = false; - _service = nil; - _calloutQueue = dispatch_queue_create("IDSCallout", DISPATCH_QUEUE_SERIAL); - _pingQueue = dispatch_queue_create("PingQueue", DISPATCH_QUEUE_SERIAL); - _dataQueue = dispatch_queue_create("DataQueue", DISPATCH_QUEUE_SERIAL); - _pingTimers = [[NSMutableDictionary alloc] init]; - deviceIDFromAuthToken = [[NSMutableDictionary alloc] init]; - _peerNextSendCache = [[NSMutableDictionary alloc] init]; - _counterValues = [[NSMutableDictionary alloc] init]; - _listOfDevices = [[NSMutableArray alloc] init]; - _outgoingMessages = 0; - _incomingMessages = 0; - _isSecDRunningAsRoot = false; - _doesSecDHavePeer = true; - secdebug(IDSPROXYSCOPE, "%@ done", self); - - [self doIDSInitialization]; - if(_isIDSInitDone) - [self doSetIDSDeviceID]; - - // Register for lock state changes - xpc_set_event_stream_handler(kStreamName, dispatch_get_main_queue(), - ^(xpc_object_t notification){ - [self streamEvent:notification]; - }); - - _retryTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); - dispatch_source_set_timer(_retryTimer, DISPATCH_TIME_FOREVER, DISPATCH_TIME_FOREVER, kRetryTimerLeeway); - dispatch_source_set_event_handler(_retryTimer, ^{ - [self timerFired]; - }); - dispatch_resume(_retryTimer); - NSMutableDictionary *state = [KeychainSyncingOverIDSProxyPersistentState idsState]; - - _unhandledMessageBuffer = state[kExportUnhandledMessages]; - if (!_unhandledMessageBuffer) { - _unhandledMessageBuffer = [NSMutableDictionary dictionary]; - } - _messagesInFlight = state[kMessagesInFlight]; - if(_messagesInFlight == nil) { - _messagesInFlight = [NSMutableDictionary dictionary]; - } - _monitor = state[kMonitorState]; - if(_monitor == nil) { - _monitor = [NSMutableDictionary dictionary]; - } - - if([_messagesInFlight count ] > 0) - _sendRestoredMessages = true; - int notificationToken; - notify_register_dispatch(kSecServerKeychainChangedNotification, ¬ificationToken, self.dataQueue, - ^ (int token __unused) - { - secinfo("backoff", "keychain changed, wiping backoff monitor state"); - self.monitor = [NSMutableDictionary dictionary]; - }); - int peerInfo; - notify_register_dispatch(kSecServerPeerInfoAvailable, &peerInfo, dispatch_get_main_queue(), - ^ (int token __unused) - { - secinfo("IDS Transport", "secd has a peer info"); - if(self.doesSecDHavePeer == false){ - self.doesSecDHavePeer = true; - [self doSetIDSDeviceID]; - } - }); - - [self updateUnlockedSinceBoot]; - [self updateIsLocked]; - if (!_isLocked) - [self keybagDidUnlock]; - - - } - return self; -} - -- (void)streamEvent:(xpc_object_t)notification -{ -#if (!TARGET_IPHONE_SIMULATOR) - const char *notificationName = xpc_dictionary_get_string(notification, "Notification"); - if (!notificationName) { - } else if (strcmp(notificationName, kUserKeybagStateChangeNotification)==0) { - return [self keybagStateChange]; - } - const char *eventName = xpc_dictionary_get_string(notification, "XPCEventName"); - char *desc = xpc_copy_description(notification); - secnotice("event", "%@ event: %s name: %s desc: %s", self, eventName, notificationName, desc); - if (desc) - free((void *)desc); -#endif -} - -- (void) keybagDidLock -{ - secnotice("IDS Transport", "%@ locking!", self); -} - -- (void) keybagDidUnlock -{ - secnotice("IDS Transport", "%@ unlocking!", self); - [self handleAllPendingMessage]; -} - -- (BOOL) updateUnlockedSinceBoot -{ - CFErrorRef aksError = NULL; - if (!SecAKSGetHasBeenUnlocked(&_unlockedSinceBoot, &aksError)) { - secerror("%@ Got error from SecAKSGetHasBeenUnlocked: %@", self, aksError); - CFReleaseSafe(aksError); - return NO; - } - return YES; -} - -- (BOOL) updateIsLocked -{ - CFErrorRef aksError = NULL; - if (!SecAKSGetIsLocked(&_isLocked, &aksError)) { - secerror("%@ Got error querying lock state: %@", self, aksError); - CFReleaseSafe(aksError); - return NO; - } - secerror("updateIsLocked: %d", _isLocked); - if (!_isLocked) - _unlockedSinceBoot = YES; - return YES; -} - -- (void) keybagStateChange -{ - os_activity_initiate("keybagStateChanged", OS_ACTIVITY_FLAG_DEFAULT, ^{ - secerror("keybagStateChange! was locked: %d", self->_isLocked); - BOOL wasLocked = self->_isLocked; - if ([self updateIsLocked]) { - if (wasLocked == self->_isLocked) - secdebug("IDS Transport", "%@ still %s ignoring", self, self->_isLocked ? "locked" : "unlocked"); - else if (self->_isLocked) - [self keybagDidLock]; - else - [self keybagDidUnlock]; - } - }); -} - - -- (void)timerFired -{ - NSUInteger __block messagecount = 0; - dispatch_sync(self.dataQueue, ^{ - if(self.unhandledMessageBuffer) { - secnotice("IDS Transport", "%@ attempting to hand unhandled messages to securityd, here is our message queue: %@", self, self.unhandledMessageBuffer); - messagecount = [self.unhandledMessageBuffer count]; - } - }); - - if(self.isLocked) { - self.retryTimerScheduled = NO; - } else if(messagecount == 0) { - self.retryTimerScheduled = NO; - } else if (self.retryTimerScheduled && !self.isLocked) { - [self handleAllPendingMessage]; - } else { - [[KeychainSyncingOverIDSProxy idsProxy] scheduleRetryRequestTimer]; - } -} - -- (void)scheduleRetryRequestTimer -{ - secnotice("IDS Transport", "scheduling unhandled messages timer"); - dispatch_source_set_timer(_retryTimer, dispatch_time(DISPATCH_TIME_NOW, kMinMessageRetryDelay), DISPATCH_TIME_FOREVER, kRetryTimerLeeway); - _retryTimerScheduled = YES; -} - -- (void)doIDSInitialization -{ - - dispatch_async(self.calloutQueue, ^{ - secnotice("IDS Transport", "doIDSInitialization!"); - - self->_service = [[IDSService alloc] initWithService: @IDSServiceNameKeychainSync]; - - if( self->_service == nil ){ - self->_isIDSInitDone = false; - secerror("Could not create ids service"); - } - else{ - secnotice("IDS Transport", "IDS Transport Successfully set up IDS!"); - [self->_service addDelegate:self queue: dispatch_get_main_queue()]; - - self->_isIDSInitDone = true; - if(self->_isSecDRunningAsRoot == false) - [self doSetIDSDeviceID]; - - NSArray *ListOfIDSDevices = [self->_service devices]; - self.listOfDevices = ListOfIDSDevices; - - for(NSUInteger i = 0; i < [ self.listOfDevices count ]; i++){ - IDSDevice *device = self.listOfDevices[i]; - NSString *authToken = IDSCopyIDForDevice(device); - [self.deviceIDFromAuthToken setObject:device.uniqueID forKey:authToken]; - } - } - }); -} - -- (void) doSetIDSDeviceID -{ - NSInteger code = 0; - NSString *errorMessage = nil; - - if(!_isIDSInitDone){ - [self doIDSInitialization]; - } - _setIDSDeviceID = YES; - - if(_isSecDRunningAsRoot != false) - { - errorMessage = @"cannot set IDS device ID, secd is running as root"; - code = SECD_RUN_AS_ROOT_ERROR; - secerror("Setting device ID error: %@, code: %ld", errorMessage, (long)code); - - } - else if(_doesSecDHavePeer != true) - { - errorMessage = @"cannot set IDS deviceID, secd does not have a full peer info for account"; - code = kSOSErrorPeerNotFound; - secerror("Setting device ID error: %@, code: %ld", errorMessage, (long)code); - - } - else if(!_isIDSInitDone){ - errorMessage = @"KeychainSyncingOverIDSProxy can't set up the IDS service"; - code = kSecIDSErrorNotRegistered; - secerror("Setting device ID error: %@, code: %ld", errorMessage, (long)code); - } - else if(_isLocked){ - errorMessage = @"KeychainSyncingOverIDSProxy can't set device ID, device is locked"; - code = kSecIDSErrorDeviceIsLocked; - secerror("Setting device ID error: %@, code: %ld", errorMessage, (long)code); - } - - else{ - [self calloutWith:^(NSMutableDictionary *pending, bool handlePendingMesssages, bool doSetDeviceID, dispatch_queue_t queue, void(^done)(NSMutableDictionary *, bool, bool)) { - CFErrorRef localError = NULL; - bool handledSettingID = false; - NSString *ID = IDSCopyLocalDeviceUniqueID(); - self->deviceID = ID; - - if(ID){ - handledSettingID = SOSCCSetDeviceID((__bridge CFStringRef) ID, &localError); - - if(!handledSettingID && localError != NULL){ - if(CFErrorGetCode(localError) == SECD_RUN_AS_ROOT_ERROR){ - secerror("SETTING RUN AS ROOT ERROR: %@", localError); - self->_isSecDRunningAsRoot = true; - } - else if (CFErrorIsMalfunctioningKeybagError(localError)) { - secnotice("IDS Transport", "system is unavailable, cannot set device ID, error: %@", localError); - self->_isLocked = true; - } - else if (CFErrorGetCode(localError) == kSOSErrorPeerNotFound && CFStringCompare(CFErrorGetDomain(localError), kSOSErrorDomain, 0) == 0){ - secnotice("IDS Transport","securityd does not have a peer yet , error: %@", localError); - self->_doesSecDHavePeer = false; - } - } - else - self->_setIDSDeviceID = NO; - - CFReleaseNull(localError); - dispatch_async(queue, ^{ - done(nil, NO, YES); - }); - } else { - dispatch_async(queue, ^{ - done(nil, NO, NO); - }); - } - if(errorMessage != nil){ - secerror("Setting device ID error: KeychainSyncingOverIDSProxy could not retrieve device ID from keychain, code: %ld", (long)kSecIDSErrorNoDeviceID); - } - }]; - } -} - -- (void) calloutWith: (void(^)(NSMutableDictionary *pending, bool handlePendingMesssages, bool doSetDeviceID, dispatch_queue_t queue, void(^done)(NSMutableDictionary *handledMessages, bool handledPendingMessage, bool handledSettingDeviceID))) callout -{ - // In KeychainSyncingOverIDSProxy serial queue - dispatch_queue_t idsproxy_queue = dispatch_get_main_queue(); - - // dispatch_get_global_queue - well-known global concurrent queue - // dispatch_get_main_queue - default queue that is bound to the main thread - xpc_transaction_begin(); - dispatch_async(_calloutQueue, ^{ - __block NSMutableDictionary *myPending; - __block bool myHandlePendingMessage; - __block bool myDoSetDeviceID; - __block bool wasLocked; - dispatch_sync(idsproxy_queue, ^{ - dispatch_sync(self.dataQueue, ^{ - myPending = [self.unhandledMessageBuffer copy]; - }); - myHandlePendingMessage = self.handleAllPendingMessages; - myDoSetDeviceID = self.setIDSDeviceID; - wasLocked = self.isLocked; - - self.inCallout = YES; - - self.shadowHandleAllPendingMessages = NO; - }); - - callout(myPending, myHandlePendingMessage, myDoSetDeviceID, idsproxy_queue, ^(NSMutableDictionary *handledMessages, bool handledPendingMessage, bool handledSetDeviceID) { - secdebug("event", "%@ %s%s before callout handled: %s%s", self, myHandlePendingMessage ? "P" : "p", myDoSetDeviceID ? "D" : "d", handledPendingMessage ? "H" : "h", handledSetDeviceID ? "I" : "i"); - - // In IDSKeychainSyncingProxy's serial queue - self->_inCallout = NO; - - // Update setting device id - self->_setIDSDeviceID = ((myDoSetDeviceID && !handledSetDeviceID)); - - self->_shadowDoSetIDSDeviceID = NO; - - xpc_transaction_end(); - }); - }); -} - -- (void) sendKeysCallout: (NSMutableDictionary*(^)(NSMutableDictionary* pending, NSError** error)) handleMessages { - [self calloutWith: ^(NSMutableDictionary *pending, bool handlePendingMesssages, bool doSetDeviceID, dispatch_queue_t queue, void(^done)(NSMutableDictionary *, bool, bool)) { - NSError* error = NULL; - - NSMutableDictionary* handled = handleMessages(pending, &error); - - dispatch_async(queue, ^{ - if (!handled && error) { - secerror("%@ did not handle message: %@", self, error); - } - - done(handled, NO, NO); - }); - }]; -} - -NSString* createErrorString(NSString* format, ...) -{ - va_list va; - va_start(va, format); - NSString* errorString = ([[NSString alloc] initWithFormat:format arguments:va]); - va_end(va); - return errorString; - -} - -- (NSDictionary*) collectStats{ - [_counterValues setObject:[NSNumber numberWithInteger:[KeychainSyncingOverIDSProxy idsProxy].outgoingMessages] forKey:kOutgoingMessages]; - [_counterValues setObject:[NSNumber numberWithInteger:[KeychainSyncingOverIDSProxy idsProxy].incomingMessages] forKey:kIncomingMessages]; - - return _counterValues; -} - - -@end diff --git a/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy+ReceiveMessage.h b/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy+ReceiveMessage.h deleted file mode 100644 index 297e4e47b..000000000 --- a/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy+ReceiveMessage.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2012-2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -#import "IDSProxy.h" - -@interface KeychainSyncingOverIDSProxy (ReceiveMessage) -//receive message routines --(BOOL) checkForFragmentation:(NSDictionary*)message id:(NSString*)fromID data:(NSData*)messageData; --(NSMutableDictionary*) combineMessage:(NSString*)deviceID peerID:(NSString*)peerID uuid:(NSString*)uuid; -- (void)service:(IDSService *)service account:(IDSAccount *)account incomingMessage:(NSDictionary *)message fromID:(NSString *)fromID context:(IDSMessageContext *)context; -- (void)sendMessageToSecurity:(NSMutableDictionary*)messageAndFromID fromID:(NSString*)fromID; -- (void) handleAllPendingMessage; - -@end diff --git a/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy+ReceiveMessage.m b/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy+ReceiveMessage.m deleted file mode 100644 index 05d2f6266..000000000 --- a/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy+ReceiveMessage.m +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Copyright (c) 2012-2017 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -#import -#import -#import - -#import -#import -#import -#import - -#include -#include -#include -#include -#include - -#import -#import - -#include -#include -#include - -#import "IDSPersistentState.h" -#import "KeychainSyncingOverIDSProxy+ReceiveMessage.h" -#import "KeychainSyncingOverIDSProxy+SendMessage.h" -#import "IDSProxy.h" - -static NSString *const kIDSNumberOfFragments = @"NumberOfIDSMessageFragments"; -static NSString *const kIDSFragmentIndex = @"kFragmentIndex"; -static NSString *const kIDSMessageRecipientID = @"RecipientPeerID"; -static NSString *const kIDSMessageUseACKModel = @"UsesAckModel"; - -@implementation KeychainSyncingOverIDSProxy (ReceiveMessage) - - --(int) countNumberOfValidObjects:(NSMutableArray*)fragmentsForDeviceID -{ - __block int count = 0; - [fragmentsForDeviceID enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL * _Nonnull stop) { - if(obj != [NSNull null]){ - count++; - } - }]; - return count; -} - --(BOOL) checkForFragmentation:(NSDictionary*)message id:(NSString*)fromID data:(NSData*)messageData -{ - BOOL handOffMessage = false; - - if([message valueForKey:kIDSNumberOfFragments] != nil){ - NSNumber *idsNumberOfFragments = [message objectForKey:kIDSNumberOfFragments]; - NSNumber *index = [message objectForKey:kIDSFragmentIndex]; - NSString *uuidString = [message objectForKey:(__bridge NSString*)kIDSMessageUniqueID]; - - if([KeychainSyncingOverIDSProxy idsProxy].allFragmentedMessages == nil) - [KeychainSyncingOverIDSProxy idsProxy].allFragmentedMessages = [NSMutableDictionary dictionary]; - - NSMutableDictionary *uniqueMessages = [[KeychainSyncingOverIDSProxy idsProxy].allFragmentedMessages objectForKey: fromID]; - if(uniqueMessages == nil) - uniqueMessages = [NSMutableDictionary dictionary]; - - NSMutableArray *fragmentsForDeviceID = [uniqueMessages objectForKey: uuidString]; - if(fragmentsForDeviceID == nil){ - fragmentsForDeviceID = [ [NSMutableArray alloc] initWithCapacity: [idsNumberOfFragments longValue]]; - for (int i = 0; i <[idsNumberOfFragments longValue] ; i++) { - [fragmentsForDeviceID addObject:[NSNull null]]; - } - } - - [fragmentsForDeviceID replaceObjectAtIndex: [index intValue] withObject:messageData ]; - [uniqueMessages setObject: fragmentsForDeviceID forKey:uuidString]; - [[KeychainSyncingOverIDSProxy idsProxy].allFragmentedMessages setObject:uniqueMessages forKey: fromID]; - - if([self countNumberOfValidObjects:fragmentsForDeviceID] == [idsNumberOfFragments longValue]) - handOffMessage = true; - else - handOffMessage = false; - - } - else //no fragmentation in the message, ready to hand off to securityd - handOffMessage = true; - - return handOffMessage; - -} - --(NSMutableDictionary*) combineMessage:(NSString*)ID peerID:(NSString*)peerID uuid:(NSString*)uuid -{ - NSString *dataKey = [ NSString stringWithUTF8String: kMessageKeyIDSDataMessage ]; - NSString *deviceIDKey = [ NSString stringWithUTF8String: kMessageKeyDeviceID ]; - NSString *peerIDKey = [ NSString stringWithUTF8String: kMessageKeyPeerID ]; - - NSMutableDictionary *arrayOfFragmentedMessagesByUUID = [[KeychainSyncingOverIDSProxy idsProxy].allFragmentedMessages objectForKey:ID]; - NSMutableArray *messagesForUUID = [arrayOfFragmentedMessagesByUUID objectForKey:uuid]; - NSMutableData* completeMessage = [NSMutableData data]; - - [messagesForUUID enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - NSData *messageFragment = (NSData*)obj; - - [completeMessage appendData: messageFragment]; - }]; - //we've combined the message, now remove it from the fragmented messages dictionary - [arrayOfFragmentedMessagesByUUID removeObjectForKey:uuid]; - - return [NSMutableDictionary dictionaryWithObjectsAndKeys: completeMessage, dataKey, deviceID, deviceIDKey, peerID, peerIDKey, nil]; -} - --(void) handleTestMessage:(NSString*)operation id:(NSString*)ID messageID:(NSString*)uniqueID senderPeerID:(NSString*)senderPeerID -{ - int operationType = [operation intValue]; - switch(operationType){ - case kIDSPeerAvailabilityDone: - { - //set current timestamp to indicate success! - [self.peerNextSendCache setObject:[NSDate date] forKey:ID]; - - secnotice("IDS Transport","!received availability response!: %@", ID); - notify_post(kSOSCCPeerAvailable); - break; - } - case kIDSEndPingTestMessage: - secnotice("IDS Transport","received pong message from other device: %@, ping test PASSED", ID); - break; - case kIDSSendOneMessage: - secnotice("IDS Transport","received ping test message, dropping on the floor now"); - break; - - case kIDSPeerAvailability: - case kIDSStartPingTestMessage: - { - char* messageCharS; - if(operationType == kIDSPeerAvailability){ - secnotice("IDS Transport","Received Availability Message from:%@!", ID); - asprintf(&messageCharS, "%d",kIDSPeerAvailabilityDone); - } - else{ - secnotice("IDS Transport","Received PingTest Message from: %@!", ID); - asprintf(&messageCharS, "%d", kIDSEndPingTestMessage); - } - - NSString *operationString = [[NSString alloc] initWithUTF8String:messageCharS]; - NSString* messageString = @"peer availability check finished"; - NSDictionary* messsageDictionary = @{(__bridge NSString*)kIDSOperationType:operationString, (__bridge NSString*)kIDSMessageToSendKey:messageString}; - - // We can always hold on to a message and our remote peers would bother everyone - [self sendIDSMessage:messsageDictionary name:ID peer:@"me"]; - - free(messageCharS); - - break; - } - case kIDSPeerReceivedACK: - { - //set current timestamp to indicate success! - [self.peerNextSendCache setObject:[[NSDate alloc] init] forKey:ID]; - - //cancel timer! - secnotice("IDS Transport", "received ack for: %@", uniqueID); - dispatch_async(self.pingQueue, ^{ - //remove timer for message id - dispatch_source_t timer = [[KeychainSyncingOverIDSProxy idsProxy].pingTimers objectForKey:uniqueID]; - if(timer != nil){ - dispatch_cancel(timer); - [[KeychainSyncingOverIDSProxy idsProxy].pingTimers removeObjectForKey:uniqueID]; - dispatch_sync(self.dataQueue, ^{ - [[KeychainSyncingOverIDSProxy idsProxy].messagesInFlight removeObjectForKey:uniqueID]; - }); - [[KeychainSyncingOverIDSProxy idsProxy] persistState]; - } - }); - //call out to securityd to set a NULL - [self sendKeysCallout:^NSMutableDictionary *(NSMutableDictionary *pending, NSError** error) { - - CFErrorRef localError = NULL; - SOSCCClearPeerMessageKeyInKVS((__bridge CFStringRef)senderPeerID, &localError); - return NULL; - }]; - break; - } - default: - break; - } -} - -- (void)sendACK:(NSString*)ID peerID:(NSString*)sendersPeerID uniqueID:(NSString*)uniqueID -{ - char* messageCharS; - NSString* messageString = @"ACK"; - - asprintf(&messageCharS, "%d",kIDSPeerReceivedACK); - NSString *operationString = [[NSString alloc] initWithUTF8String:messageCharS]; - - NSDictionary* messageDictionary = @{(__bridge NSString*)kIDSOperationType:operationString, (__bridge NSString*)kIDSMessageToSendKey:messageString, (__bridge NSString*)kIDSMessageUniqueID:uniqueID}; - - [self sendIDSMessage:messageDictionary name:ID peer:sendersPeerID]; - - free(messageCharS); - -} - -- (void)updateDeviceList -{ - self.deviceIDFromAuthToken = nil; - self.deviceIDFromAuthToken = [NSMutableDictionary dictionary]; - [self calloutWith:^(NSMutableDictionary *pending, bool handlePendingMesssages, bool doSetDeviceID, dispatch_queue_t queue, void(^done)(NSMutableDictionary *, bool, bool)) { - }]; -} -- (void)service:(IDSService *)service account:(IDSAccount *)account incomingMessage:(NSDictionary *)message fromID:(NSString *)fromID context:(IDSMessageContext *)context -{ - NSString *dataKey = [ NSString stringWithUTF8String: kMessageKeyIDSDataMessage ]; - NSString *deviceIDKey = [ NSString stringWithUTF8String: kMessageKeyDeviceID ]; - NSString *peerIDKey = [ NSString stringWithUTF8String: kMessageKeyPeerID ]; - NSString *sendersPeerIDKey = [NSString stringWithUTF8String: kMessageKeySendersPeerID]; - - [KeychainSyncingOverIDSProxy idsProxy].incomingMessages++; - - dispatch_async(self.calloutQueue, ^{ - NSString* messageID = nil; - uint32_t operationType; - bool hadError = false; - CFStringRef errorMessage = NULL; - __block NSString* myPeerID = @""; - __block NSData *messageData = nil; - NSString* operationTypeAsString = nil; - NSMutableDictionary *messageDictionary = nil; - NSString *useAck = nil; - NSString *ID = nil; - NSArray *devices = [self->_service devices]; - for(NSUInteger i = 0; i < [ devices count ]; i++){ - IDSDevice *device = devices[i]; - if( [(IDSCopyIDForDevice(device)) containsString: fromID] == YES){ - ID = device.uniqueID; - break; - } - } - secnotice("IDS Transport", "Received message from: %@: %@ ", ID, message); - NSString *sendersPeerID = [message objectForKey: sendersPeerIDKey]; - - if(sendersPeerID == nil) - sendersPeerID = [NSString string]; - - - require_action_quiet(ID, fail, hadError = true; errorMessage = CFSTR("require the sender's device ID")); - - operationTypeAsString = [message objectForKey: (__bridge NSString*)kIDSOperationType]; - messageDictionary = [message objectForKey: (__bridge NSString*)kIDSMessageToSendKey]; - - messageID = [message objectForKey:(__bridge NSString*)kIDSMessageUniqueID]; - useAck = [message objectForKey:kIDSMessageUseACKModel]; - - if(useAck != nil && [useAck compare:@"YES"] == NSOrderedSame) - require_quiet(messageID != nil, fail); - - secnotice("IDS Transport","from peer %@, operation type as string: %@, as integer: %d", ID, operationTypeAsString, [operationTypeAsString intValue]); - operationType = [operationTypeAsString intValue]; - - if(operationType != kIDSKeychainSyncIDSFragmentation) - { - [self handleTestMessage:operationTypeAsString id:ID messageID:messageID senderPeerID:sendersPeerID]; - } - else{ - - [messageDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { - myPeerID = (NSString*)key; - messageData = (NSData*)obj; - }]; - - if(useAck != nil && [useAck compare:@"YES"] == NSOrderedSame) - [self sendACK:ID peerID:myPeerID uniqueID:messageID]; - - BOOL readyToHandOffToSecD = [self checkForFragmentation:message id:ID data:messageData]; - - NSMutableDictionary *messageAndFromID = nil; - - if(readyToHandOffToSecD && ([message objectForKey:kIDSFragmentIndex])!= nil){ - NSString* uuid = [message objectForKey:(__bridge NSString*)kIDSMessageUniqueID]; - messageAndFromID = [self combineMessage:ID peerID:myPeerID uuid:uuid]; - } - else if(readyToHandOffToSecD){ - messageAndFromID = [NSMutableDictionary dictionaryWithObjectsAndKeys: messageData, dataKey, ID, deviceIDKey, myPeerID, peerIDKey, nil]; - } - else - return; - - //set the sender's peer id so we can check it in securityd - [messageAndFromID setObject:sendersPeerID forKey:sendersPeerIDKey]; - - if([KeychainSyncingOverIDSProxy idsProxy].isLocked){ - //hang on to the message and set the retry deadline - dispatch_sync(self.dataQueue, ^{ - [self.unhandledMessageBuffer setObject: messageAndFromID forKey: fromID]; - }); - } - else - [self sendMessageToSecurity:messageAndFromID fromID:fromID]; - } - - fail: - if(hadError) - secerror("error:%@", errorMessage); - }); -} - - -- (void) handleAllPendingMessage -{ - secnotice("IDS Transport", "Attempting to handle pending messsages"); - - NSMutableDictionary * __block copyOfUnhandled = nil; - dispatch_sync(self.dataQueue, ^{ - if ([self.unhandledMessageBuffer count] > 0) { - secnotice("IDS Transport", "handling messages: %@", self.unhandledMessageBuffer); - copyOfUnhandled = [NSMutableDictionary dictionaryWithDictionary:self.unhandledMessageBuffer]; - } - }); - - [copyOfUnhandled enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) - { - NSMutableDictionary *messageAndFromID = (NSMutableDictionary*)obj; - NSString *fromID = (NSString*)key; - //remove the message from the official message buffer (if it fails to get handled it'll be reset again in sendMessageToSecurity) - dispatch_sync(self.dataQueue, ^{ - [self.unhandledMessageBuffer removeObjectForKey: fromID]; - }); - [self sendMessageToSecurity:messageAndFromID fromID:fromID]; - }]; -} - -- (bool) shouldPersistMessage:(NSDictionary*) newMessageAndFromID id:(NSString*)fromID -{ - //get the dictionary of messages for a particular device id - NSDictionary* __block messagesFromBuffer; - dispatch_sync(self.dataQueue, ^{ - messagesFromBuffer = [self.unhandledMessageBuffer valueForKey:fromID]; - }); - - if([messagesFromBuffer isEqual:newMessageAndFromID]) - return false; - - return true; -} - --(void)sendMessageToSecurity:(NSMutableDictionary*)messageAndFromID fromID:(NSString*)fromID -{ - __block CFErrorRef cf_error = NULL; - __block HandleIDSMessageReason success = kHandleIDSMessageSuccess; - - [self sendKeysCallout:^NSMutableDictionary *(NSMutableDictionary *pending, NSError** error) { - - success = SOSCCHandleIDSMessage(((__bridge CFDictionaryRef)messageAndFromID), &cf_error); - //turns out the error needs to be evaluated as sync_and_do returns bools - if(cf_error != NULL) - { - if(CFErrorIsMalfunctioningKeybagError(cf_error)){ - success = kHandleIDSMessageLocked; - } - } - - if(success == kHandleIDSMessageLocked){ - secnotice("IDS Transport","cannot handle messages from: %@ when locked, error:%@", fromID, cf_error); - // I don't think this is ever nil but it was like this when I got here - dispatch_sync(self.dataQueue, ^{ - if(!self.unhandledMessageBuffer) { - self.unhandledMessageBuffer = [NSMutableDictionary dictionary]; - } - }); - - //write message to disk if message is new to the unhandled queue - if([self shouldPersistMessage:messageAndFromID id:fromID]) { - [self persistState]; - } - - dispatch_sync(self.dataQueue, ^{ - [self.unhandledMessageBuffer setObject: messageAndFromID forKey: fromID]; - secnotice("IDS Transport", "unhandledMessageBuffer: %@", self.unhandledMessageBuffer); - }); - - return NULL; - } - else if(success == kHandleIDSMessageNotReady){ - secnotice("IDS Transport","not ready to handle message from: %@, error:%@", fromID, cf_error); - dispatch_sync(self.dataQueue, ^{ - if(!self.unhandledMessageBuffer) { - self.unhandledMessageBuffer = [NSMutableDictionary dictionary]; - } - [self.unhandledMessageBuffer setObject: messageAndFromID forKey: fromID]; - secnotice("IDS Transport","unhandledMessageBuffer: %@", self.unhandledMessageBuffer); - }); - //write message to disk if message is new to the unhandled queue - if([self shouldPersistMessage:messageAndFromID id:fromID]) - [self persistState]; - - [[KeychainSyncingOverIDSProxy idsProxy] scheduleRetryRequestTimer]; - return NULL; - } - else if(success == kHandleIDSmessageDeviceIDMismatch){ - secnotice("IDS Transport","message for a ghost! dropping message. error:%@", cf_error); - return NULL; - } - else if(success == kHandleIDSMessageDontHandle){ - secnotice("IDS Transport","error in message, dropping message. error:%@", cf_error); - return NULL; - } - else{ - secnotice("IDS Transport","IDSProxy handled this message %@, from: %@", messageAndFromID, fromID); - return (NSMutableDictionary*)messageAndFromID; - } - - CFReleaseNull(cf_error); - }]; -} - -@end diff --git a/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy+SendMessage.h b/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy+SendMessage.h deleted file mode 100644 index 0de3f5b3b..000000000 --- a/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy+SendMessage.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2012-2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -#import "IDSProxy.h" - -@interface KeychainSyncingOverIDSProxy (SendMessage) --(BOOL) sendFragmentedIDSMessages:(NSDictionary*)data name:(NSString*) deviceName peer:(NSString*) ourPeerID error:(NSError**) error; --(BOOL) sendIDSMessage:(NSDictionary*)data name:(NSString*) deviceName peer:(NSString*) peerID; --(void) ackTimerFired:(NSString*)identifier deviceID:(NSString*)deviceID; --(void) setMessageTimer:(NSString*)identifier deviceID:(NSString*)deviceID message:(NSDictionary*)message; -- (void)pingTimerFired:(NSString*)deviceID peerID:(NSString*)peerID identifier:(NSString*)identifier; --(void) pingDevices:(NSArray*)list peerID:(NSString*)peerID; -@end diff --git a/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy+SendMessage.m b/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy+SendMessage.m deleted file mode 100644 index 3136a7e77..000000000 --- a/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy+SendMessage.m +++ /dev/null @@ -1,513 +0,0 @@ -/* - * Copyright (c) 2012-2017 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -#import -#import - -#import -#import -#import -#import - -#include -#include -#include -#include - -#import -#import - -#include -#include -#include - -#import "IDSProxy.h" -#import "IDSPersistentState.h" -#import "KeychainSyncingOverIDSProxy+SendMessage.h" -#include - - -static NSString *const IDSSendMessageOptionForceEncryptionOffKey = @"IDSSendMessageOptionForceEncryptionOff"; - -static NSString *const kIDSNumberOfFragments = @"NumberOfIDSMessageFragments"; -static NSString *const kIDSFragmentIndex = @"kFragmentIndex"; -static NSString *const kIDSMessageUseACKModel = @"UsesAckModel"; -static NSString *const kIDSDeviceID = @"deviceID"; - -static const int64_t kRetryTimerLeeway = (NSEC_PER_MSEC * 250); // 250ms leeway for handling unhandled messages. -static const int64_t timeout = 3ull; -static const int64_t KVS_BACKOFF = 5; - -static const NSUInteger kMaxIDSMessagePayloadSize = 64000; - - -@implementation KeychainSyncingOverIDSProxy (SendMessage) - - --(bool) chunkAndSendKeychainPayload:(NSData*)keychainData deviceID:(NSString*)deviceName ourPeerID:(NSString*)ourPeerID theirPeerID:(NSString*) theirPeerID operation:(NSString*)operationTypeAsString uuid:(NSString*)uuidString error:(NSError**) error -{ - __block BOOL result = true; - - NSUInteger keychainDataLength = [keychainData length]; - int fragmentIndex = 0; - int startingPosition = 0; - - NSUInteger totalNumberOfFragments = (keychainDataLength + kMaxIDSMessagePayloadSize - 1)/kMaxIDSMessagePayloadSize; - secnotice("IDS Transport", "sending %lu number of fragments to: %@", (unsigned long)totalNumberOfFragments, deviceName); - NSMutableDictionary* fragmentDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys: - deviceName, kIDSDeviceID, - [NSNumber numberWithUnsignedInteger:totalNumberOfFragments], kIDSNumberOfFragments, - [NSNumber numberWithInt:fragmentIndex], kIDSFragmentIndex, - deviceName, kIDSMessageRecipientDeviceID, theirPeerID, kIDSMessageRecipientPeerID, - operationTypeAsString, kIDSOperationType, - uuidString, kIDSMessageUniqueID, - nil]; - - NSUInteger remainingLength = keychainDataLength; - while(remainingLength > 0 && result == true){ - NSUInteger fragmentLength = MIN(remainingLength, kMaxIDSMessagePayloadSize); - NSData *fragment = [keychainData subdataWithRange:NSMakeRange(startingPosition, fragmentLength)]; - - // Insert the current fragment data in dictionary with key peerID and message key. - [fragmentDictionary setObject:@{theirPeerID:fragment} - forKey:(__bridge NSString*)kIDSMessageToSendKey]; - // Insert the fragment number in the dictionary - [fragmentDictionary setObject:[NSNumber numberWithInt:fragmentIndex] - forKey:kIDSFragmentIndex]; - - result = [self sendIDSMessage:fragmentDictionary name:deviceName peer:ourPeerID]; - if(!result) - secerror("Could not send fragmented message"); - - startingPosition+=fragmentLength; - remainingLength-=fragmentLength; - fragmentIndex++; - } - - return result; -} - -- (void)sendToKVS: (NSString*) theirPeerID message: (NSData*) message -{ - [self sendKeysCallout:^NSMutableDictionary *(NSMutableDictionary *pending, NSError** error) { - CFErrorRef cf_error = NULL; - - bool success = SOSCCRequestSyncWithPeerOverKVS(((__bridge CFStringRef)theirPeerID), (__bridge CFDataRef)message, &cf_error); - - if(success){ - secnotice("IDSPing", "sent peerID: %@ to securityd to sync over KVS", theirPeerID); - } - else{ - secerror("Could not hand peerID: %@ to securityd, error: %@", theirPeerID, cf_error); - } - - CFReleaseNull(cf_error); - return NULL; - }]; -} - -- (void) sendMessageToKVS: (NSDictionary*) encapsulatedKeychainMessage -{ - [encapsulatedKeychainMessage enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { - if ([key isKindOfClass: [NSString class]] && [obj isKindOfClass:[NSData class]]) { - [self sendToKVS:key message:obj]; - } else { - secerror("Couldn't send to KVS key: %@ obj: %@", key, obj); - } - }]; -} - - -- (void)pingTimerFired:(NSString*)IDSid peerID:(NSString*)peerID identifier:(NSString*)identifier -{ - //setting next time to send - [self updateNextTimeToSendFor5Minutes:IDSid]; - - secnotice("IDS Transport", "device ID: %@ !!!!!!!!!!!!!!!!Ping timeout is up!!!!!!!!!!!!", IDSid); - //call securityd to sync with device over KVS - __block CFErrorRef cf_error = NULL; - __block bool success = kHandleIDSMessageSuccess; - - //cleanup timers - dispatch_async(self.pingQueue, ^{ - dispatch_source_t timer = [[KeychainSyncingOverIDSProxy idsProxy].pingTimers objectForKey:IDSid]; //remove timer - dispatch_cancel(timer); //cancel timer - [[KeychainSyncingOverIDSProxy idsProxy].pingTimers removeObjectForKey:IDSid]; - }); - - [self sendKeysCallout:^NSMutableDictionary *(NSMutableDictionary *pending, NSError** error) { - - success = SOSCCRequestSyncWithPeerOverKVSUsingIDOnly(((__bridge CFStringRef)IDSid), &cf_error); - - if(success){ - secnotice("IDSPing", "sent peerID: %@ to securityd to sync over KVS", IDSid); - } - else{ - secerror("Could not hand peerID: %@ to securityd, error: %@", IDSid, cf_error); - } - - return NULL; - }]; - CFReleaseSafe(cf_error); -} - --(void) pingDevices:(NSArray*)list peerID:(NSString*)peerID -{ - NSDictionary *messageDictionary = @{(__bridge NSString*)kIDSOperationType : [NSString stringWithFormat:@"%d", kIDSPeerAvailability], (__bridge NSString*)kIDSMessageToSendKey : @"checking peers"}; - - [list enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL * top) { - NSString* IDSid = (NSString*)obj; - NSString* identifier = [NSString string]; - bool result = false; - secnotice("IDS Transport", "sending to id: %@", IDSid); - - result = [self sendIDSMessage:messageDictionary name:IDSid peer:peerID]; - - if(!result){ - secerror("Could not send message over IDS"); - [self sendKeysCallout:^NSMutableDictionary *(NSMutableDictionary *pending, NSError** error) { - CFErrorRef kvsError = nil; - bool success = SOSCCRequestSyncWithPeerOverKVSUsingIDOnly(((__bridge CFStringRef)IDSid), &kvsError); - - if(success){ - secnotice("IDSPing", "sent peerID: %@ to securityd to sync over KVS", IDSid); - } - else{ - secerror("Could not hand peerID: %@ to securityd, error: %@", IDSid, kvsError); - } - CFReleaseNull(kvsError); - return NULL; - }]; - } - else{ - dispatch_async(self.pingQueue, ^{ - //create a timer! - if( [self.pingTimers objectForKey:IDSid] == nil){ - dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); - dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, timeout * NSEC_PER_SEC), DISPATCH_TIME_FOREVER, kRetryTimerLeeway); - dispatch_source_set_event_handler(timer, ^{ - [self pingTimerFired:IDSid peerID:peerID identifier:identifier]; - }); - dispatch_resume(timer); - - [self.pingTimers setObject:timer forKey:IDSid]; - } - }); - } - }]; -} - --(BOOL) shouldProxySendMessage:(NSString*)deviceName -{ - BOOL result = false; - - //checking peer cache to see if the message should be sent over IDS or back to KVS - if(self.peerNextSendCache == nil) - { - self.peerNextSendCache = [[NSMutableDictionary alloc]initWithCapacity:0]; - } - NSDate *nextTimeToSend = [self.peerNextSendCache objectForKey:deviceName]; - if(nextTimeToSend != nil) - { - //check if the timestamp is stale or set sometime in the future - NSDate *currentTime = [[NSDate alloc] init]; - //if the current time is greater than the next time to send -> time to send! - if([[nextTimeToSend laterDate:currentTime] isEqual:currentTime]){ - result = true; - } - } - else{ //next time to send is not set yet - result = true; - } - return result; -} - --(BOOL) isMessageAPing:(NSDictionary*)data -{ - NSDictionary *messageDictionary = [data objectForKey: (__bridge NSString*)kIDSMessageToSendKey]; - BOOL isPingMessage = false; - - if(messageDictionary && ![messageDictionary isKindOfClass:[NSDictionary class]]) - { - NSString* messageString = [data objectForKey: (__bridge NSString*)kIDSMessageToSendKey]; - if(messageString && [messageString isKindOfClass:[NSString class]]) - isPingMessage = true; - } - else if(!messageDictionary){ - secerror("IDS Transport: message is null?"); - } - - return isPingMessage; -} - --(BOOL) sendFragmentedIDSMessages:(NSDictionary*)data name:(NSString*) deviceName peer:(NSString*) ourPeerID error:(NSError**) error -{ - BOOL result = false; - BOOL isPingMessage = false; - - NSError* localError = nil; - - NSString* operationTypeAsString = [data objectForKey: (__bridge NSString*)kIDSOperationType]; - NSMutableDictionary *messageDictionary = [data objectForKey: (__bridge NSString*)kIDSMessageToSendKey]; - - isPingMessage = [self isMessageAPing:data]; - - //check the peer cache for the next time to send timestamp - //if the timestamp is set in the future, reroute the message to KVS - //otherwise send the message over IDS - if(![self shouldProxySendMessage:deviceName]) - { - if(isPingMessage){ - secnotice("IDS Transport", "peer negative cache check: peer cannot send yet. not sending ping message"); - return true; - } - else{ - secnotice("IDS Transport", "peer negative cache check: peer cannot send yet. rerouting message to be sent over KVS: %@", messageDictionary); - [self sendMessageToKVS:messageDictionary]; - return true; - } - } - - if(isPingMessage){ //foward the ping message, no processing - result = [self sendIDSMessage:data - name:deviceName - peer:ourPeerID]; - if(!result){ - secerror("Could not send ping message"); - } - return result; - } - - NSString *localMessageIdentifier = [[NSUUID UUID] UUIDString]; - - bool fragment = [operationTypeAsString intValue] == kIDSKeychainSyncIDSFragmentation; - bool useAckModel = fragment && [[data objectForKey:kIDSMessageUseACKModel] compare: @"YES"] == NSOrderedSame; - - __block NSData *keychainData = nil; - __block NSString *theirPeerID = nil; - - [messageDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { - if ([key isKindOfClass:[NSString class]] && [obj isKindOfClass:[NSData class]]) { - theirPeerID = (NSString*)key; - keychainData = (NSData*)obj; - } - *stop = YES; - }]; - - if(fragment && keychainData && [keychainData length] >= kMaxIDSMessagePayloadSize){ - secnotice("IDS Transport","sending chunked keychain messages"); - result = [self chunkAndSendKeychainPayload:keychainData - deviceID:deviceName - ourPeerID:ourPeerID - theirPeerID:theirPeerID - operation:operationTypeAsString - uuid:localMessageIdentifier - error:&localError]; - } - else{ - NSMutableDictionary* dataCopy = [NSMutableDictionary dictionaryWithDictionary:data]; - [dataCopy setObject:localMessageIdentifier forKey:(__bridge NSString*)kIDSMessageUniqueID]; - result = [self sendIDSMessage:dataCopy - name:deviceName - peer:ourPeerID]; - } - - if(result && useAckModel){ - secnotice("IDS Transport", "setting ack timer"); - [self setMessageTimer:localMessageIdentifier deviceID:deviceName message:data]; - } - - secnotice("IDS Transport","returning result: %d, error: %@", result, error ? *error : nil); - return result; -} - --(void) updateNextTimeToSendFor5Minutes:(NSString*)ID -{ - secnotice("IDS Transport", "Setting next time to send in 5 minutes for device: %@", ID); - - NSTimeInterval backOffInterval = (KVS_BACKOFF * 60); - NSDate *nextTimeToTransmit = [NSDate dateWithTimeInterval:backOffInterval sinceDate:[NSDate date]]; - - [self.peerNextSendCache setObject:nextTimeToTransmit forKey:ID]; -} - -- (void)ackTimerFired:(NSString*)identifier deviceID:(NSString*)ID -{ - secnotice("IDS Transport", "IDS device id: %@, Ping timeout is up for message identifier: %@", ID, identifier); - - //call securityd to sync with device over KVS - NSMutableDictionary * __block message; - dispatch_sync(self.dataQueue, ^{ - message = [[KeychainSyncingOverIDSProxy idsProxy].messagesInFlight objectForKey:identifier]; - [[KeychainSyncingOverIDSProxy idsProxy].messagesInFlight removeObjectForKey:identifier]; - }); - if(!message){ - return; - } - NSDictionary *encapsulatedKeychainMessage = [message objectForKey:(__bridge NSString*)kIDSMessageToSendKey]; - - secnotice("IDS Transport", "Encapsulated message: %@", encapsulatedKeychainMessage); - //cleanup timers - dispatch_async(self.pingQueue, ^{ - dispatch_source_t timer = [[KeychainSyncingOverIDSProxy idsProxy].pingTimers objectForKey:identifier]; //remove timer - if(timer != nil) - dispatch_cancel(timer); //cancel timer - [[KeychainSyncingOverIDSProxy idsProxy].pingTimers removeObjectForKey:identifier]; - }); - - [self sendMessageToKVS:encapsulatedKeychainMessage]; - - //setting next time to send - [self updateNextTimeToSendFor5Minutes:ID]; - - [[KeychainSyncingOverIDSProxy idsProxy] persistState]; -} - --(void) setMessageTimer:(NSString*)identifier deviceID:(NSString*)ID message:(NSDictionary*)message -{ - dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); - dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, timeout * NSEC_PER_SEC), DISPATCH_TIME_FOREVER, kRetryTimerLeeway); - - dispatch_source_set_event_handler(timer, ^{ - [self ackTimerFired:identifier deviceID:ID]; - }); - dispatch_resume(timer); - //restructure message in flight - - - - //set the timer for message id - dispatch_async(self.pingQueue, ^{ - [self.pingTimers setObject:timer forKey:identifier]; - }); - - dispatch_sync(self.dataQueue, ^{ - [[KeychainSyncingOverIDSProxy idsProxy].messagesInFlight setObject:message forKey:identifier]; - }); - [[KeychainSyncingOverIDSProxy idsProxy] persistState]; -} - -//had an immediate error, remove it from messages in flight, and immediately send it over KVS --(void) cleanupAfterHardIDSError:(NSDictionary*)data -{ - NSString *messageIdentifier = [data objectForKey:(__bridge NSString*)kIDSMessageUniqueID]; - NSMutableDictionary * __block messageToSendToKVS = nil; - - if(messageIdentifier != nil){ - secerror("removing message id: %@ from message timers", messageIdentifier); - dispatch_sync(self.dataQueue, ^{ - messageToSendToKVS = [[KeychainSyncingOverIDSProxy idsProxy].messagesInFlight objectForKey:messageIdentifier]; - [[KeychainSyncingOverIDSProxy idsProxy].messagesInFlight removeObjectForKey:messageIdentifier]; - }); - if(!messageToSendToKVS){ - secnotice("IDS Transport", "no message for identifier: %@", messageIdentifier); - return; - } - secnotice("IDS Transport", "sending over KVS: %@", messageToSendToKVS); - - - - //cleanup timer for message - dispatch_async(self.pingQueue, ^{ - dispatch_source_t timer = [[KeychainSyncingOverIDSProxy idsProxy].pingTimers objectForKey:messageIdentifier]; //remove timer - if(timer) - dispatch_cancel(timer); //cancel timer - [[KeychainSyncingOverIDSProxy idsProxy].pingTimers removeObjectForKey:messageIdentifier]; - }); - } - - NSDictionary *encapsulatedKeychainMessage = [messageToSendToKVS objectForKey:(__bridge NSString*)kIDSMessageToSendKey]; - - if([encapsulatedKeychainMessage isKindOfClass:[NSDictionary class]]){ - secnotice("IDS Transport", "Encapsulated message: %@", encapsulatedKeychainMessage); - [self sendMessageToKVS:encapsulatedKeychainMessage]; - } -} - --(BOOL) sendIDSMessage:(NSDictionary*)data name:(NSString*) deviceName peer:(NSString*) peerID -{ - - if(!self->_service){ - secerror("Could not send message to peer: %@: IDS delegate uninitialized, can't use IDS to send this message", deviceName); - return NO; - } - - dispatch_async(self.calloutQueue, ^{ - - IDSMessagePriority priority = IDSMessagePriorityHigh; - BOOL encryptionOff = YES; - NSString *sendersPeerIDKey = [ NSString stringWithUTF8String: kMessageKeySendersPeerID]; - - secnotice("backoff","!!writing these keys to IDS!!: %@", data); - - NSDictionary *options = @{IDSSendMessageOptionForceEncryptionOffKey : [NSNumber numberWithBool:encryptionOff] }; - - NSMutableDictionary *dataCopy = [NSMutableDictionary dictionaryWithDictionary: data]; - - //set our peer id and a unique id for this message - [dataCopy setObject:peerID forKey:sendersPeerIDKey]; - secnotice("IDS Transport", "%@ sending message %@ to: %@", peerID, data, deviceName); - - NSDictionary *info; - NSInteger errorCode = 0; - NSInteger numberOfDevices = 0; - NSString *errMessage = nil; - NSMutableSet *destinations = nil; - NSError *localError = nil; - NSString *identifier = nil; - IDSDevice *device = nil; - numberOfDevices = [self.listOfDevices count]; - - require_action_quiet(numberOfDevices > 0, fail, errorCode = kSecIDSErrorNotRegistered; errMessage=createErrorString(@"Could not send message to peer: %@: IDS devices are not registered yet", deviceName)); - secnotice("IDS Transport","List of devices: %@", [self->_service devices]); - - destinations = [NSMutableSet set]; - for(NSUInteger i = 0; i < [ self.listOfDevices count ]; i++){ - device = self.listOfDevices[i]; - if( [ deviceName compare:device.uniqueID ] == 0){ - [destinations addObject: IDSCopyIDForDevice(device)]; - } - } - require_action_quiet([destinations count] != 0, fail, errorCode = kSecIDSErrorCouldNotFindMatchingAuthToken; errMessage = createErrorString(@"Could not send message to peer: %@: IDS device ID for peer does not match any devices within an IDS Account", deviceName)); - - bool result = [self->_service sendMessage:dataCopy toDestinations:destinations priority:priority options:options identifier:&identifier error:&localError ] ; - - [KeychainSyncingOverIDSProxy idsProxy].outgoingMessages++; - require_action_quiet(localError == nil && result, fail, errorCode = kSecIDSErrorFailedToSend; errMessage = createErrorString(@"Had an error sending IDS message to peer: %@", deviceName)); - - secnotice("IDS Transport","successfully sent to peer:%@, message: %@", deviceName, dataCopy); - fail: - - if(errMessage != nil){ - info = [ NSDictionary dictionaryWithObjectsAndKeys:errMessage, NSLocalizedDescriptionKey, nil ]; - localError = [[NSError alloc] initWithDomain:@"com.apple.security.ids.error" code:errorCode userInfo:info ]; - secerror("%@", localError); - [self cleanupAfterHardIDSError: data]; - } - }); - - return YES; -} - -@end diff --git a/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy+Throttle.h b/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy+Throttle.h deleted file mode 100644 index 65a2c596b..000000000 --- a/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy+Throttle.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2012-2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -#import "IDSProxy.h" - -@interface KeychainSyncingOverIDSProxy (Throttle) - -- (dispatch_source_t)setNewTimer:(int)timeout key:(NSString*)key deviceName:(NSString*)deviceName peerID:(NSString*)peerID; -- (NSDictionary*)filterForWritableValues:(NSDictionary *)values; -- (void)recordTimestampForAppropriateInterval:(NSMutableDictionary**)timeTable key:(NSString*)key consecutiveWrites:(NSNumber**)consecutiveWrites; -- (void)recordTimestampOfWriteToIDS:(NSDictionary *)values deviceName:(NSString*)name peerID:(NSString*)peerid; - - -@end diff --git a/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy+Throttle.m b/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy+Throttle.m deleted file mode 100644 index 769adc8e2..000000000 --- a/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy+Throttle.m +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Copyright (c) 2012-2016 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -#import -#import - -#import -#import -#import -#import - -#include -#include -#include -#include - -#import -#import - -#include -#include -#include - -#import "IDSPersistentState.h" -#import "KeychainSyncingOverIDSProxy+SendMessage.h" -#import "KeychainSyncingOverIDSProxy+Throttle.h" -#import - - -static NSString *kExportUnhandledMessages = @"UnhandledMessages"; -static NSString *kMonitorState = @"MonitorState"; - -static NSString *kMonitorPenaltyBoxKey = @"Penalty"; -static NSString *kMonitorMessageKey = @"Message"; -static NSString *kMonitorConsecutiveWrites = @"ConsecutiveWrites"; -static NSString *kMonitorLastWriteTimestamp = @"LastWriteTimestamp"; -static NSString *kMonitorMessageQueue = @"MessageQueue"; -static NSString *kMonitorPenaltyTimer = @"PenaltyTimer"; -static NSString *kMonitorDidWriteDuringPenalty = @"DidWriteDuringPenalty"; - -static NSString *kMonitorTimeTable = @"TimeTable"; -static NSString *kMonitorFirstMinute = @"AFirstMinute"; -static NSString *kMonitorSecondMinute = @"BSecondMinute"; -static NSString *kMonitorThirdMinute = @"CThirdMinute"; -static NSString *kMonitorFourthMinute = @"DFourthMinute"; -static NSString *kMonitorFifthMinute = @"EFifthMinute"; -static NSString *kMonitorWroteInTimeSlice = @"TimeSlice"; - -static int max_penalty_timeout = 32; -static int seconds_per_minute = 60; -static int queue_depth = 1; - -CFStringRef const IDSPAggdIncreaseThrottlingKey = CFSTR("com.apple.security.idsproxy.increasethrottle"); -CFStringRef const IDSPAggdDecreaseThrottlingKey = CFSTR("com.apple.security.idsproxy.decreasethrottle"); - -static const int64_t kRetryTimerLeeway = (NSEC_PER_MSEC * 250); // 250ms leeway for handling unhandled messages. - -@implementation KeychainSyncingOverIDSProxy (Throttle) - --(dispatch_source_t)setNewTimer:(int)timeout key:(NSString*)key deviceName:(NSString*)deviceName peerID:(NSString*)peerID -{ - - __block dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); - dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, timeout * NSEC_PER_SEC * seconds_per_minute), DISPATCH_TIME_FOREVER, kRetryTimerLeeway); - dispatch_source_set_event_handler(timer, ^{ - [self penaltyTimerFired:key deviceName:deviceName peerID:peerID]; - }); - dispatch_resume(timer); - return timer; -} - --(void) increasePenalty:(NSNumber*)currentPenalty key:(NSString*)key keyEntry:(NSMutableDictionary**)keyEntry deviceName:(NSString*)deviceName peerID:(NSString*)peerID -{ - SecADAddValueForScalarKey((IDSPAggdIncreaseThrottlingKey), 1); - - secnotice("backoff", "increasing penalty!"); - int newPenalty = 0; - - if ([currentPenalty intValue] <= 0) - newPenalty = 1; - else - newPenalty = fmin([currentPenalty intValue]*2, max_penalty_timeout); - - secnotice("backoff", "key %@, waiting %d minutes long to send next messages", key, newPenalty); - - NSNumber* penalty_timeout = [[NSNumber alloc]initWithInt:newPenalty]; - dispatch_source_t existingTimer = [*keyEntry objectForKey:kMonitorPenaltyTimer]; - - if(existingTimer != nil){ - [*keyEntry removeObjectForKey:kMonitorPenaltyTimer]; - dispatch_suspend(existingTimer); - dispatch_source_set_timer(existingTimer,dispatch_time(DISPATCH_TIME_NOW, newPenalty * NSEC_PER_SEC * seconds_per_minute), DISPATCH_TIME_FOREVER, kRetryTimerLeeway); - dispatch_resume(existingTimer); - [*keyEntry setObject:existingTimer forKey:kMonitorPenaltyTimer]; - } - else{ - dispatch_source_t timer = [self setNewTimer:newPenalty key:key deviceName:deviceName peerID:peerID]; - [*keyEntry setObject:timer forKey:kMonitorPenaltyTimer]; - } - - [*keyEntry setObject:penalty_timeout forKey:kMonitorPenaltyBoxKey]; - [[KeychainSyncingOverIDSProxy idsProxy].monitor setObject:*keyEntry forKey:key]; -} - --(void) decreasePenalty:(NSNumber*)currentPenalty key:(NSString*)key keyEntry:(NSMutableDictionary**)keyEntry deviceName:(NSString*)deviceName peerID:(NSString*)peerID -{ - SecADAddValueForScalarKey((IDSPAggdDecreaseThrottlingKey), 1); - - int newPenalty = 0; - secnotice("backoff","decreasing penalty!"); - if([currentPenalty intValue] == 0 || [currentPenalty intValue] == 1) - newPenalty = 0; - else - newPenalty = [currentPenalty intValue]/2; - - secnotice("backoff","key %@, waiting %d minutes long to send next messages", key, newPenalty); - - NSNumber* penalty_timeout = [[NSNumber alloc]initWithInt:newPenalty]; - - dispatch_source_t existingTimer = [*keyEntry objectForKey:kMonitorPenaltyTimer]; - if(existingTimer != nil){ - [*keyEntry removeObjectForKey:kMonitorPenaltyTimer]; - dispatch_suspend(existingTimer); - if(newPenalty != 0){ - dispatch_source_set_timer(existingTimer,dispatch_time(DISPATCH_TIME_NOW, newPenalty * NSEC_PER_SEC * seconds_per_minute), DISPATCH_TIME_FOREVER, kRetryTimerLeeway); - dispatch_resume(existingTimer); - [*keyEntry setObject:existingTimer forKey:kMonitorPenaltyTimer]; - } - else{ - dispatch_resume(existingTimer); - dispatch_source_cancel(existingTimer); - } - } - else{ - if(newPenalty != 0){ - dispatch_source_t timer = [self setNewTimer:newPenalty key:key deviceName:deviceName peerID:peerID]; - [*keyEntry setObject:timer forKey:kMonitorPenaltyTimer]; - } - } - - [*keyEntry setObject:penalty_timeout forKey:kMonitorPenaltyBoxKey]; - [[KeychainSyncingOverIDSProxy idsProxy].monitor setObject:*keyEntry forKey:key]; - -} - -- (void)penaltyTimerFired:(NSString*)key deviceName:(NSString*)deviceName peerID:(NSString*)peerID -{ - secnotice("backoff", "key: %@, !!!!!!!!!!!!!!!!penalty timeout is up!!!!!!!!!!!!", key); - NSMutableDictionary *keyEntry = [[KeychainSyncingOverIDSProxy idsProxy].monitor objectForKey:key]; - if(!keyEntry){ - [self initializeKeyEntry:key]; - keyEntry = [[KeychainSyncingOverIDSProxy idsProxy].monitor objectForKey:key]; - } - NSMutableArray *queuedMessages = [[KeychainSyncingOverIDSProxy idsProxy].monitor objectForKey:kMonitorMessageQueue]; - secnotice("backoff","key: %@, queuedMessages: %@", key, queuedMessages); - if(queuedMessages && [queuedMessages count] != 0){ - secnotice("backoff","key: %@, message queue not empty, writing to IDS!", key); - [queuedMessages enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { - NSError* error = nil; - NSDictionary* message = (NSDictionary*) obj; - [self sendFragmentedIDSMessages:message name:deviceName peer:peerID error:&error]; - }]; - - [[KeychainSyncingOverIDSProxy idsProxy].monitor setObject:[NSMutableArray array] forKey:kMonitorMessageQueue]; - } - //decrease timeout since we successfully wrote messages out - NSNumber *penalty_timeout = [keyEntry objectForKey:kMonitorPenaltyBoxKey]; - secnotice("backoff", "key: %@, current penalty timeout: %@", key, penalty_timeout); - - NSString* didWriteDuringTimeout = [keyEntry objectForKey:kMonitorDidWriteDuringPenalty]; - if( didWriteDuringTimeout && [didWriteDuringTimeout isEqualToString:@"YES"] ) - { - //increase timeout since we wrote during out penalty timeout - [self increasePenalty:penalty_timeout key:key keyEntry:&keyEntry deviceName:deviceName peerID:peerID]; - } - else{ - //decrease timeout since we successfully wrote messages out - [self decreasePenalty:penalty_timeout key:key keyEntry:&keyEntry deviceName:deviceName peerID:peerID]; - } - - //resetting the check - [keyEntry setObject: @"NO" forKey:kMonitorDidWriteDuringPenalty]; - - //recompute the timetable and number of consecutive writes to IDS - NSMutableDictionary *timetableForKey = [keyEntry objectForKey:kMonitorTimeTable]; - if(timetableForKey == nil){ - timetableForKey = [self initializeTimeTable:key]; - } - NSNumber *consecutiveWrites = [keyEntry objectForKey:kMonitorConsecutiveWrites]; - if(consecutiveWrites == nil){ - consecutiveWrites = [[NSNumber alloc] initWithInt:0]; - } - [self recordTimestampForAppropriateInterval:&timetableForKey key:key consecutiveWrites:&consecutiveWrites]; - - [keyEntry setObject:consecutiveWrites forKey:kMonitorConsecutiveWrites]; - [keyEntry setObject:timetableForKey forKey:kMonitorTimeTable]; - [[KeychainSyncingOverIDSProxy idsProxy].monitor setObject:keyEntry forKey:key]; - -} - --(NSMutableDictionary*)initializeTimeTable:(NSString*)key -{ - NSDate *currentTime = [NSDate date]; - NSMutableDictionary *firstMinute = [NSMutableDictionary dictionaryWithObjectsAndKeys:[currentTime dateByAddingTimeInterval: seconds_per_minute], kMonitorFirstMinute, @"YES", kMonitorWroteInTimeSlice, nil]; - NSMutableDictionary *secondMinute = [NSMutableDictionary dictionaryWithObjectsAndKeys:[currentTime dateByAddingTimeInterval: seconds_per_minute * 2],kMonitorSecondMinute, @"NO", kMonitorWroteInTimeSlice, nil]; - NSMutableDictionary *thirdMinute = [NSMutableDictionary dictionaryWithObjectsAndKeys:[currentTime dateByAddingTimeInterval: seconds_per_minute * 3], kMonitorThirdMinute, @"NO",kMonitorWroteInTimeSlice, nil]; - NSMutableDictionary *fourthMinute = [NSMutableDictionary dictionaryWithObjectsAndKeys:[currentTime dateByAddingTimeInterval: seconds_per_minute * 4],kMonitorFourthMinute, @"NO", kMonitorWroteInTimeSlice, nil]; - NSMutableDictionary *fifthMinute = [NSMutableDictionary dictionaryWithObjectsAndKeys:[currentTime dateByAddingTimeInterval: seconds_per_minute * 5], kMonitorFifthMinute, @"NO", kMonitorWroteInTimeSlice, nil]; - - NSMutableDictionary *timeTable = [NSMutableDictionary dictionaryWithObjectsAndKeys: firstMinute, kMonitorFirstMinute, - secondMinute, kMonitorSecondMinute, - thirdMinute, kMonitorThirdMinute, - fourthMinute, kMonitorFourthMinute, - fifthMinute, kMonitorFifthMinute, nil]; - return timeTable; -} - -- (void)initializeKeyEntry:(NSString*)key -{ - NSMutableDictionary *timeTable = [[KeychainSyncingOverIDSProxy idsProxy] initializeTimeTable:key]; - NSDate *currentTime = [NSDate date]; - - NSMutableDictionary *keyEntry = [NSMutableDictionary dictionaryWithObjectsAndKeys: key, kMonitorMessageKey, @0, kMonitorConsecutiveWrites, currentTime, kMonitorLastWriteTimestamp, @0, kMonitorPenaltyBoxKey, timeTable, kMonitorTimeTable,[NSMutableArray array], kMonitorMessageQueue, nil]; - - [[KeychainSyncingOverIDSProxy idsProxy].monitor setObject:keyEntry forKey:key]; - -} - -- (void)recordTimestampForAppropriateInterval:(NSMutableDictionary**)timeTable key:(NSString*)key consecutiveWrites:(NSNumber**)consecutiveWrites -{ - NSDate *currentTime = [NSDate date]; - __block int cWrites = [*consecutiveWrites intValue]; - __block BOOL foundTimeSlot = NO; - __block NSMutableDictionary *previousTable = nil; - - NSArray *sortedTimestampKeys = [[*timeTable allKeys] sortedArrayUsingSelector:@selector(compare:)]; - NSMutableDictionary* timeTableStrong = *timeTable; - - [sortedTimestampKeys enumerateObjectsUsingBlock:^(id arrayObject, NSUInteger idx, BOOL *stop) - { - if(foundTimeSlot == YES) - return; - - NSString *sortedKey = (NSString*)arrayObject; - - //grab the dictionary containing write information - //(date, boolean to check if a write occured in the timeslice, - NSMutableDictionary *minutesTable = [timeTableStrong objectForKey: sortedKey]; - if(minutesTable == nil) - minutesTable = [[KeychainSyncingOverIDSProxy idsProxy] initializeTimeTable:key]; - - NSString *minuteKey = (NSString*)sortedKey; - NSDate *timeStampForSlice = [minutesTable objectForKey:minuteKey]; - - if(timeStampForSlice && [timeStampForSlice compare:currentTime] == NSOrderedDescending){ - foundTimeSlot = YES; - NSString* written = [minutesTable objectForKey:kMonitorWroteInTimeSlice]; - //figure out if we have previously recorded a write in this time slice - if([written isEqualToString:@"NO"]){ - [minutesTable setObject:@"YES" forKey:kMonitorWroteInTimeSlice]; - if(previousTable != nil){ - //if we wrote in the previous time slice count the current time as in the consecutive write count - written = [previousTable objectForKey:kMonitorWroteInTimeSlice]; - if([written isEqualToString:@"YES"]){ - cWrites++; - } - else if ([written isEqualToString:@"NO"]){ - cWrites = 0; - } - } - } - return; - } - previousTable = minutesTable; - }]; - - if(foundTimeSlot == NO){ - //reset the time table - secnotice("backoff","didn't find a time slot, resetting the table"); - - //record if a write occured between the last time slice of - //the time table entries and now. - NSMutableDictionary *lastTable = [*timeTable objectForKey:kMonitorFifthMinute]; - NSDate *lastDate = [lastTable objectForKey:kMonitorFifthMinute]; - - if(lastDate && ((double)[currentTime timeIntervalSinceDate: lastDate] >= seconds_per_minute)){ - *consecutiveWrites = [[NSNumber alloc]initWithInt:0]; - } - else{ - NSString* written = [lastTable objectForKey:kMonitorWroteInTimeSlice]; - if(written && [written isEqualToString:@"YES"]){ - cWrites++; - *consecutiveWrites = [[NSNumber alloc]initWithInt:cWrites]; - } - else{ - *consecutiveWrites = [[NSNumber alloc]initWithInt:0]; - } - } - - *timeTable = [[KeychainSyncingOverIDSProxy idsProxy] initializeTimeTable:key]; - return; - } - *consecutiveWrites = [[NSNumber alloc]initWithInt:cWrites]; -} -- (void)recordTimestampOfWriteToIDS:(NSDictionary *)values deviceName:(NSString*)name peerID:(NSString*)peerid -{ - if([[KeychainSyncingOverIDSProxy idsProxy].monitor count] == 0){ - [values enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) - { - [self initializeKeyEntry: key]; - }]; - } - else{ - [values enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) - { - NSMutableDictionary *keyEntry = [[KeychainSyncingOverIDSProxy idsProxy].monitor objectForKey:key]; - if(keyEntry == nil){ - [self initializeKeyEntry: key]; - } - else{ - NSNumber *penalty_timeout = [keyEntry objectForKey:kMonitorPenaltyBoxKey]; - NSDate *lastWriteTimestamp = [keyEntry objectForKey:kMonitorLastWriteTimestamp]; - NSMutableDictionary *timeTable = [keyEntry objectForKey: kMonitorTimeTable]; - NSNumber *existingWrites = [keyEntry objectForKey: kMonitorConsecutiveWrites]; - NSDate *currentTime = [NSDate date]; - - //record the write happened in our timetable structure - [self recordTimestampForAppropriateInterval:&timeTable key:key consecutiveWrites:&existingWrites]; - - int consecutiveWrites = [existingWrites intValue]; - secnotice("backoff","consecutive writes: %d", consecutiveWrites); - [keyEntry setObject:existingWrites forKey:kMonitorConsecutiveWrites]; - [keyEntry setObject:timeTable forKey:kMonitorTimeTable]; - [keyEntry setObject:currentTime forKey:kMonitorLastWriteTimestamp]; - [[KeychainSyncingOverIDSProxy idsProxy].monitor setObject:keyEntry forKey:key]; - - if( (penalty_timeout && [penalty_timeout intValue] != 0 ) || ((double)[currentTime timeIntervalSinceDate: lastWriteTimestamp] <= 60 && consecutiveWrites >= 5)){ - - if( (penalty_timeout == nil || [penalty_timeout intValue] == 0) && consecutiveWrites == 5){ - secnotice("backoff","written for 5 consecutive minutes, time to start throttling"); - [self increasePenalty:penalty_timeout key:key keyEntry:&keyEntry deviceName:name peerID:peerid]; - } - else - secnotice("backoff","monitor: keys have been written for 5 or more minutes, recording we wrote during timeout"); - - //record we wrote during a timeout - [keyEntry setObject: @"YES" forKey:kMonitorDidWriteDuringPenalty]; - } - else if((double)[currentTime timeIntervalSinceDate: lastWriteTimestamp] <= 60 && consecutiveWrites < 5){ - //for debugging purposes - secnotice("backoff","monitor: still writing freely"); - [keyEntry setObject: @"NO" forKey:kMonitorDidWriteDuringPenalty]; - } - else if([penalty_timeout intValue] != 0 && ((double)[currentTime timeIntervalSinceDate: lastWriteTimestamp] > 60 && consecutiveWrites > 5) ){ - - //encountered a write even though we're in throttle mode - [keyEntry setObject: @"YES" forKey:kMonitorDidWriteDuringPenalty]; - } - } - }]; - } -} - -- (NSDictionary*)filterForWritableValues:(NSDictionary *)values -{ - secnotice("backoff", "filterForWritableValues: %@", values); - NSMutableDictionary *keyEntry_operationType = [[KeychainSyncingOverIDSProxy idsProxy].monitor objectForKey:@"IDSMessageOperation"]; - - secnotice("backoff", "keyEntry_operationType: %@", keyEntry_operationType); - - NSNumber *penalty = [keyEntry_operationType objectForKey:kMonitorPenaltyBoxKey]; - - if(penalty && [penalty intValue] != 0){ - - NSMutableArray *queuedMessage = [[KeychainSyncingOverIDSProxy idsProxy].monitor objectForKey:kMonitorMessageQueue]; - if(queuedMessage == nil) - queuedMessage = [[NSMutableArray alloc] initWithCapacity:queue_depth]; - - secnotice("backoff", "writing to queuedMessages: %@", queuedMessage); - - if([queuedMessage count] == 0) - [queuedMessage addObject:values]; - else - [queuedMessage replaceObjectAtIndex:(queue_depth-1) withObject: values]; - - [[KeychainSyncingOverIDSProxy idsProxy].monitor setObject:queuedMessage forKey:kMonitorMessageQueue]; - return NULL; - } - - return values; -} - -@end diff --git a/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy-Info.plist b/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy-Info.plist deleted file mode 100644 index 325edc2d5..000000000 --- a/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy-Info.plist +++ /dev/null @@ -1,34 +0,0 @@ - - - - - Application-Group - - InternetAccounts - - CFBundleDevelopmentRegion - English - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIconFile - - CFBundleIdentifier - com.apple.security.keychainsyncingoveridsproxy - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - ${CURRENT_PROJECT_VERSION} - LSBackgroundOnly - - NSHumanReadableCopyright - Copyright © 2013 Apple, Inc. All rights reserved. - - diff --git a/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy.8 b/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy.8 deleted file mode 100644 index 1dec96838..000000000 --- a/KeychainSyncingOverIDSProxy/KeychainSyncingOverIDSProxy.8 +++ /dev/null @@ -1,9 +0,0 @@ -.Dd November 02, 2016 -.Dt KeychainSyncingOverIDSProxy 8 -.Os -.Sh NAME -.Nm KeychainSyncingOverIDSProxy -.Nd part of iCloud Keychain syncing. -.Sh DESCRIPTION -.Nm -part of iCloud Keychain syncing. diff --git a/KeychainSyncingOverIDSProxy/com.apple.private.alloy.keychainsync.plist b/KeychainSyncingOverIDSProxy/com.apple.private.alloy.keychainsync.plist deleted file mode 100644 index f08f2617b..000000000 Binary files a/KeychainSyncingOverIDSProxy/com.apple.private.alloy.keychainsync.plist and /dev/null differ diff --git a/KeychainSyncingOverIDSProxy/com.apple.security.keychainsyncingoveridsproxy.ios.plist b/KeychainSyncingOverIDSProxy/com.apple.security.keychainsyncingoveridsproxy.ios.plist deleted file mode 100644 index a3acb004c..000000000 --- a/KeychainSyncingOverIDSProxy/com.apple.security.keychainsyncingoveridsproxy.ios.plist +++ /dev/null @@ -1,53 +0,0 @@ - - - - - EnablePressuredExit - - EnvironmentVariables - - DEBUGSCOPE - all - WAIT4DEBUGGER - NO - - Label - com.apple.security.keychainsyncingoveridsproxy - LaunchEvents - - com.apple.notifyd.matching - - com.apple.mobile.keybagd.first_unlock - - Notification - com.apple.mobile.keybagd.first_unlock - - com.apple.mobile.keybagd.lock_status - - Notification - com.apple.mobile.keybagd.lock_status - - com.apple.keystore.lockstatus - - Notification - com.apple.keystore.lockstatus - - - - MachServices - - com.apple.private.alloy.keychainsync-idswake - - com.apple.security.keychainsyncingoveridsproxy - - - Program - /System/Library/Frameworks/Security.framework/KeychainSyncingOverIDSProxy.bundle/KeychainSyncingOverIDSProxy - ProgramArguments - - /System/Library/Frameworks/Security.framework/KeychainSyncingOverIDSProxy.bundle/KeychainSyncingOverIDSProxy - - enabletransactions - - - diff --git a/KeychainSyncingOverIDSProxy/com.apple.security.keychainsyncingoveridsproxy.osx.plist b/KeychainSyncingOverIDSProxy/com.apple.security.keychainsyncingoveridsproxy.osx.plist deleted file mode 100644 index dbdcaca52..000000000 --- a/KeychainSyncingOverIDSProxy/com.apple.security.keychainsyncingoveridsproxy.osx.plist +++ /dev/null @@ -1,43 +0,0 @@ - - - - - LaunchEvents - - com.apple.notifyd.matching - - com.apple.keystore.lockstatus - - Notification - com.apple.keystore.lockstatus - - - - Program - /System/Library/Frameworks/Security.framework/Versions/A/Resources/KeychainSyncingOverIDSProxy.bundle/Contents/MacOS/KeychainSyncingOverIDSProxy - Label - com.apple.security.keychainsyncingoveridsproxy - EnvironmentVariables - - DEBUGSCOPE - all - WAIT4DEBUGGER - NO - - ProcessType - Adaptive - MachServices - - com.apple.private.alloy.keychainsync-idswake - - com.apple.security.keychainsyncingoveridsproxy - - - ProgramArguments - - /System/Library/Frameworks/Security.framework/Versions/A/Resources/KeychainSyncingOverIDSProxy.bundle/Contents/MacOS/KeychainSyncingOverIDSProxy - - EnablePressuredExit - - - diff --git a/KeychainSyncingOverIDSProxy/en.lproj/InfoPlist.strings b/KeychainSyncingOverIDSProxy/en.lproj/InfoPlist.strings deleted file mode 100644 index 477b28ff8..000000000 --- a/KeychainSyncingOverIDSProxy/en.lproj/InfoPlist.strings +++ /dev/null @@ -1,2 +0,0 @@ -/* Localized versions of Info.plist keys */ - diff --git a/KeychainSyncingOverIDSProxy/keychainsyncingoveridsproxy.entitlements.plist b/KeychainSyncingOverIDSProxy/keychainsyncingoveridsproxy.entitlements.plist deleted file mode 100644 index 14070f34f..000000000 --- a/KeychainSyncingOverIDSProxy/keychainsyncingoveridsproxy.entitlements.plist +++ /dev/null @@ -1,32 +0,0 @@ - - - - - keychain-cloud-circle - - com.apple.wifi.manager-access - - com.apple.private.ids.remoteurlconnection - - com.apple.private.ids.force-encryption-off - - com.apple.private.alloy.keychainsync - - com.apple.private.ids.messaging.high-priority - - com.apple.private.alloy.keychainsync - - com.apple.private.ids.messaging - - com.apple.private.alloy.keychainsync - - keychain-access-groups - - apple - IMCore - InternetAccounts - - application-identifier - com.apple.security.keychainsyncingoveridsproxy - - diff --git a/KeychainSyncingOverIDSProxy/keychainsyncingoveridsproxy.m b/KeychainSyncingOverIDSProxy/keychainsyncingoveridsproxy.m deleted file mode 100644 index 810d4b8fa..000000000 --- a/KeychainSyncingOverIDSProxy/keychainsyncingoveridsproxy.m +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#include -#include -#include "SOSCloudKeychainConstants.h" -#import -#import "KeychainSyncingOverIDSProxy+SendMessage.h" - -int idsproxymain(int argc, const char *argv[]); - -#define PROXYXPCSCOPE "idsproxy" - -static void describeXPCObject(char *prefix, xpc_object_t object) -{ - // This is useful for debugging. - if (object) - { - char *desc = xpc_copy_description(object); - secdebug(PROXYXPCSCOPE, "%s%s\n", prefix, desc); - free(desc); - } - else - secdebug(PROXYXPCSCOPE, "%s\n", prefix); - -} - -static void idskeychainsyncingproxy_peer_dictionary_handler(const xpc_connection_t peer, 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"); - - const char *operation = xpc_dictionary_get_string(event, kMessageKeyOperation); - require_action(operation, xit, result = false); - - // 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); - - // Operations - secdebug(PROXYXPCSCOPE, "Handling %s operation", operation); - - - if(operation && !strcmp(operation, kOperationGetDeviceID)){ - [[KeychainSyncingOverIDSProxy idsProxy] doSetIDSDeviceID]; - xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - xpc_dictionary_set_bool(replyMessage, kMessageKeyValue, true); - xpc_connection_send_message(peer, replyMessage); - secdebug(PROXYXPCSCOPE, "Set our IDS Device ID message sent"); - - } - else if(operation && !strcmp(operation, kOperationGetIDSPerfCounters)){ - NSDictionary *counters = [[KeychainSyncingOverIDSProxy idsProxy] collectStats]; - xpc_object_t xMessages = _CFXPCCreateXPCObjectFromCFObject((__bridge CFDictionaryRef)(counters)); - - xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - xpc_dictionary_set_value(replyMessage, kMessageKeyValue, xMessages); - xpc_connection_send_message(peer, replyMessage); - secdebug(PROXYXPCSCOPE, "Retrieved counters"); - } - else if (operation && !strcmp(operation, kOperationGetPendingMesages)) - { - NSDictionary* messages = [[KeychainSyncingOverIDSProxy idsProxy] retrievePendingMessages]; - xpc_object_t xMessages = _CFXPCCreateXPCObjectFromCFObject((__bridge CFDictionaryRef)(messages)); - - xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - xpc_dictionary_set_value(replyMessage, kMessageKeyValue, xMessages); - - xpc_connection_send_message(peer, replyMessage); - secdebug(PROXYXPCSCOPE, "retrieved pending messages"); - - } - else if(operation && !strcmp(operation, kOperationSendDeviceList)) //IDS device availability check - { - xpc_object_t xidsDeviceList = xpc_dictionary_get_value(event, kMessageKeyValue); - xpc_object_t xPeerID = xpc_dictionary_get_value(event, kMessageKeyPeerID); - - NSArray *idsList = (__bridge_transfer NSArray*)(_CFXPCCreateCFObjectFromXPCObject(xidsDeviceList)); - NSString *peerID = (__bridge_transfer NSString*)(_CFXPCCreateCFObjectFromXPCObject(xPeerID)); - - bool isMessageArray = (CFGetTypeID((__bridge CFTypeRef)(idsList)) == CFArrayGetTypeID()); - bool isPeerIDString = (CFGetTypeID((__bridge CFTypeRef)(peerID)) == CFStringGetTypeID()); - - require_quiet(isMessageArray, xit); - require_quiet(isPeerIDString, xit); - - [[KeychainSyncingOverIDSProxy idsProxy] pingDevices:idsList peerID:peerID]; - - xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - xpc_dictionary_set_bool(replyMessage, kMessageKeyValue, true); - - xpc_connection_send_message(peer, replyMessage); - secdebug(PROXYXPCSCOPE, "IDS device list sent"); - } - else if (operation && !strcmp(operation, kOperationSendFragmentedIDSMessage)) - { - xpc_object_t xidsMessageData = xpc_dictionary_get_value(event, kMessageKeyValue); - xpc_object_t xDeviceName = xpc_dictionary_get_value(event, kMessageKeyDeviceName); - xpc_object_t xPeerID = xpc_dictionary_get_value(event, kMessageKeyPeerID); - BOOL object = false; - - NSString *deviceName = (__bridge_transfer NSString*)(_CFXPCCreateCFObjectFromXPCObject(xDeviceName)); - NSString *peerID = (__bridge_transfer NSString*)(_CFXPCCreateCFObjectFromXPCObject(xPeerID)); - NSDictionary *messageDictionary = (__bridge_transfer NSDictionary*)(_CFXPCCreateCFObjectFromXPCObject(xidsMessageData)); - NSError *error = NULL; - bool isNameString = (CFGetTypeID((__bridge CFTypeRef)(deviceName)) == CFStringGetTypeID()); - bool isPeerIDString = (CFGetTypeID((__bridge CFTypeRef)(peerID)) == CFStringGetTypeID()); - bool isMessageDictionary = (CFGetTypeID((__bridge CFTypeRef)(messageDictionary)) == CFDictionaryGetTypeID()); - - require_quiet(isNameString, xit); - require_quiet(isPeerIDString, xit); - require_quiet(isMessageDictionary, xit); - - object = [[KeychainSyncingOverIDSProxy idsProxy] sendFragmentedIDSMessages:messageDictionary name:deviceName peer:peerID error:&error]; - - xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - xpc_dictionary_set_bool(replyMessage, kMessageKeyValue, object); - - if(error){ - xpc_object_t xerrobj = SecCreateXPCObjectWithCFError((__bridge CFErrorRef)(error)); - xpc_dictionary_set_value(replyMessage, kMessageKeyError, xerrobj); - } - xpc_connection_send_message(peer, replyMessage); - secdebug(PROXYXPCSCOPE, "IDS message sent"); - } - else if (operation && !strcmp(operation, kOperationSendIDSMessage)) //for IDS tests - { - xpc_object_t xidsMessageData = xpc_dictionary_get_value(event, kMessageKeyValue); - xpc_object_t xDeviceName = xpc_dictionary_get_value(event, kMessageKeyDeviceName); - xpc_object_t xPeerID = xpc_dictionary_get_value(event, kMessageKeyPeerID); - BOOL object = false; - - NSString *deviceName = (__bridge_transfer NSString*)(_CFXPCCreateCFObjectFromXPCObject(xDeviceName)); - NSString *peerID = (__bridge_transfer NSString*)(_CFXPCCreateCFObjectFromXPCObject(xPeerID)); - NSDictionary *messageDictionary = (__bridge_transfer NSDictionary*)(_CFXPCCreateCFObjectFromXPCObject(xidsMessageData)); - CFErrorRef error = NULL; - bool isNameString = (CFGetTypeID((__bridge CFTypeRef)(deviceName)) == CFStringGetTypeID()); - bool isPeerIDString = (CFGetTypeID((__bridge CFTypeRef)(peerID)) == CFStringGetTypeID()); - bool isMessageDictionary = (CFGetTypeID((__bridge CFTypeRef)(messageDictionary)) == CFDictionaryGetTypeID()); - - require_quiet(isNameString, xit); - require_quiet(isPeerIDString, xit); - require_quiet(isMessageDictionary, xit); - - NSString *localMessageIdentifier = [[NSUUID UUID] UUIDString]; - NSMutableDictionary* messageDictionaryCopy = [NSMutableDictionary dictionaryWithDictionary:messageDictionary]; - - [messageDictionaryCopy setObject:localMessageIdentifier forKey:(__bridge NSString*)(kIDSMessageUniqueID)]; - - if([[KeychainSyncingOverIDSProxy idsProxy] sendIDSMessage:messageDictionaryCopy name:deviceName peer:peerID]) - { - object = true; - NSString *useAckModel = [messageDictionaryCopy objectForKey:(__bridge NSString*)(kIDSMessageUsesAckModel)]; - if(object && [useAckModel compare:@"YES"] == NSOrderedSame){ - secnotice("IDS Transport", "setting timer!"); - [[KeychainSyncingOverIDSProxy idsProxy] setMessageTimer:localMessageIdentifier deviceID:deviceName message:messageDictionaryCopy]; - } - } - else{ - SOSErrorCreate(kSecIDSErrorFailedToSend, &error, NULL, CFSTR("Failed to send keychain data message over IDS")); - secerror("Could not send message"); - } - - xpc_object_t replyMessage = xpc_dictionary_create_reply(event); - xpc_dictionary_set_bool(replyMessage, kMessageKeyValue, object); - - if(error){ - xpc_object_t xerrobj = SecCreateXPCObjectWithCFError(error); - xpc_dictionary_set_value(replyMessage, kMessageKeyError, xerrobj); - } - CFReleaseNull(error); - xpc_connection_send_message(peer, replyMessage); - secdebug(PROXYXPCSCOPE, "IDS message sent"); - } - - 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; -xit: - if (!result) - describeXPCObject("handle_operation fail: ", event); -} - -static void idskeychainsyncingproxy_peer_event_handler(xpc_connection_t peer, xpc_object_t event) -{ - describeXPCObject("peer: ", peer); - xpc_type_t type = xpc_get_type(event); - if (type == XPC_TYPE_ERROR) { - if (event == XPC_ERROR_CONNECTION_INVALID) { - // The client process on the other end of the connection has either - // crashed or canceled the connection. After receiving this error, - // the connection is in an invalid state, and you do not need to - // call xpc_connection_cancel(). Just tear down any associated state - // here. - } else if (event == XPC_ERROR_TERMINATION_IMMINENT) { - // Handle per-connection termination cleanup. - } - } else { - assert(type == XPC_TYPE_DICTIONARY); - // Handle the message. - // describeXPCObject("dictionary:", event); - dispatch_async(dispatch_get_main_queue(), ^{ - idskeychainsyncingproxy_peer_dictionary_handler(peer, event); - }); - } -} - -static void idskeychainsyncingproxy_event_handler(xpc_connection_t peer) -{ - // By defaults, new connections will target the default dispatch - // concurrent queue. - - if (xpc_get_type(peer) != XPC_TYPE_CONNECTION) - { - secdebug(PROXYXPCSCOPE, "expected XPC_TYPE_CONNECTION"); - return; - } - - xpc_connection_set_event_handler(peer, ^(xpc_object_t event) - { - idskeychainsyncingproxy_peer_event_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); -} - -int idsproxymain(int argc, const char *argv[]) -{ - secdebug(PROXYXPCSCOPE, "Starting IDSProxy"); - char *wait4debugger = getenv("WAIT4DEBUGGER"); - - if (wait4debugger && !strcasecmp("YES", wait4debugger)) - { - syslog(LOG_ERR, "Waiting for debugger"); - kill(getpid(), SIGTSTP); - } - - // DISPATCH_TARGET_QUEUE_DEFAULT - xpc_connection_t listener = xpc_connection_create_mach_service(xpcIDSServiceName, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER); - xpc_connection_set_event_handler(listener, ^(xpc_object_t object){ idskeychainsyncingproxy_event_handler(object); }); - - [KeychainSyncingOverIDSProxy idsProxy]; - - if([[KeychainSyncingOverIDSProxy idsProxy] haveMessagesInFlight] && - [KeychainSyncingOverIDSProxy idsProxy].isIDSInitDone && - [KeychainSyncingOverIDSProxy idsProxy].sendRestoredMessages) { - [[KeychainSyncingOverIDSProxy idsProxy] sendPersistedMessagesAgain]; - [KeychainSyncingOverIDSProxy idsProxy].sendRestoredMessages = false; - } - - // 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]; - } - - secdebug(PROXYXPCSCOPE, "Exiting KeychainSyncingOverIDSProxy"); - - return EXIT_FAILURE; -} - -int main(int argc, const char *argv[]) -{ - return idsproxymain(argc, argv); -} diff --git a/Modules/Security.macOS.private.modulemap b/Modules/Security.macOS.private.modulemap new file mode 100644 index 000000000..9645c117f --- /dev/null +++ b/Modules/Security.macOS.private.modulemap @@ -0,0 +1,4 @@ +module Security.SecTask [extern_c] { + header "SecTask.h" + export * +} diff --git a/OCMockUmbrella/Info.plist b/OCMockUmbrella/Info.plist new file mode 100644 index 000000000..e1fe4cfb7 --- /dev/null +++ b/OCMockUmbrella/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + + diff --git a/OCMockUmbrella/OCMockUmbrella.h b/OCMockUmbrella/OCMockUmbrella.h new file mode 100644 index 000000000..50625776f --- /dev/null +++ b/OCMockUmbrella/OCMockUmbrella.h @@ -0,0 +1,8 @@ + +#import + +//! Project version number for OCMockUmbrella. +FOUNDATION_EXPORT double OCMockUmbrellaVersionNumber; + +//! Project version string for OCMockUmbrella. +FOUNDATION_EXPORT const unsigned char OCMockUmbrellaVersionString[]; diff --git a/OSX/Breadcrumb/SecBreadcrumb.c b/OSX/Breadcrumb/SecBreadcrumb.c index 13caa20f1..067c93c56 100644 --- a/OSX/Breadcrumb/SecBreadcrumb.c +++ b/OSX/Breadcrumb/SecBreadcrumb.c @@ -37,15 +37,15 @@ #define CFReleaseNull(CF) ({ __typeof__(CF) *const _pcf = &(CF), _cf = *_pcf; (_cf ? (*_pcf) = ((__typeof__(CF))0), (CFRelease(_cf), ((__typeof__(CF))0)) : _cf); }) -static const int kKeySize = CCAES_KEY_SIZE_128; -static const int kSaltSize = 20; -static const int kIterations = 5000; -static const CFIndex tagLen = 16; -static const CFIndex ivLen = 16; -static const uint8_t BCversion1 = 1; -static const uint8_t BCversion2 = 2; -static const ssize_t paddingSize = 256; -static const ssize_t maxSize = 1024; +#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, @@ -55,8 +55,7 @@ SecBreadcrumbCreateFromPassword(CFStringRef inPassword, { const struct ccmode_ecb *ecb = ccaes_ecb_encrypt_mode(); const struct ccmode_gcm *gcm = ccaes_gcm_encrypt_mode(); - const struct ccdigest_info *di = ccsha256_di(); - uint8_t iv[ivLen]; + uint8_t iv[BCIVLen]; CFMutableDataRef key, npw; CFDataRef pw; @@ -69,18 +68,18 @@ SecBreadcrumbCreateFromPassword(CFStringRef inPassword, if (key == NULL) return false; - CFDataSetLength(key, kKeySize + kSaltSize + 4); + CFDataSetLength(key, kBCKeySize + kBCSaltSize + 4); if (SecRandomCopyBytes(kSecRandomDefault, CFDataGetLength(key) - 4, CFDataGetMutableBytePtr(key)) != 0) { CFReleaseNull(key); return false; } - if (SecRandomCopyBytes(kSecRandomDefault, ivLen, iv) != 0) { + if (SecRandomCopyBytes(kSecRandomDefault, BCIVLen, iv) != 0) { CFReleaseNull(key); return false; } - uint32_t size = htonl(kIterations); - memcpy(CFDataGetMutableBytePtr(key) + kKeySize + kSaltSize, &size, sizeof(size)); + uint32_t size = htonl(kBCIterations); + memcpy(CFDataGetMutableBytePtr(key) + kBCKeySize + kBCSaltSize, &size, sizeof(size)); /* * Create data for password @@ -94,14 +93,14 @@ SecBreadcrumbCreateFromPassword(CFStringRef inPassword, const CFIndex passwordLength = CFDataGetLength(pw); - if (passwordLength > maxSize) { + if (passwordLength > BCMaxSize) { CFReleaseNull(pw); CFReleaseNull(key); return false; } - CFIndex paddedSize = passwordLength + paddingSize - (passwordLength % paddingSize); - const CFIndex outLength = 1 + ivLen + 4 + paddedSize + tagLen; + CFIndex paddedSize = passwordLength + BCPaddingSize - (passwordLength % BCPaddingSize); + const CFIndex outLength = 1 + BCIVLen + 4 + paddedSize + BCTagLen; npw = CFDataCreateMutable(NULL, outLength); if (npw == NULL) { @@ -111,36 +110,37 @@ SecBreadcrumbCreateFromPassword(CFStringRef inPassword, } CFDataSetLength(npw, outLength); - memset(CFDataGetMutableBytePtr(npw), 0, outLength); + cc_clear(outLength, CFDataGetMutableBytePtr(npw)); CFDataGetMutableBytePtr(npw)[0] = BCversion2; - memcpy(CFDataGetMutableBytePtr(npw) + 1, iv, ivLen); + memcpy(CFDataGetMutableBytePtr(npw) + 1, iv, BCIVLen); size = htonl(passwordLength); - memcpy(CFDataGetMutableBytePtr(npw) + 1 + ivLen, &size, sizeof(size)); - memcpy(CFDataGetMutableBytePtr(npw) + 1 + ivLen + 4, CFDataGetBytePtr(pw), 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, kKeySize, CFDataGetMutableBytePtr(key)); - ccgcm_set_iv(gcm, ctx, ivLen, iv); + 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 - tagLen - ivLen - 1, CFDataGetMutableBytePtr(npw) + 1 + ivLen, CFDataGetMutableBytePtr(npw) + 1 + ivLen); - ccgcm_finalize(gcm, ctx, tagLen, CFDataGetMutableBytePtr(npw) + outLength - tagLen); + 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 */ - if (di->output_size < kKeySize) abort(); - - uint8_t rawkey[di->output_size]; - + 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), - kSaltSize, CFDataGetMutableBytePtr(key) + kKeySize, - kIterations, + kBCSaltSize, CFDataGetMutableBytePtr(key) + kBCKeySize, + kBCIterations, sizeof(rawkey), rawkey) != 0) abort(); @@ -149,7 +149,7 @@ SecBreadcrumbCreateFromPassword(CFStringRef inPassword, */ ccecb_ctx_decl(ccecb_context_size(ecb), ecbkey); - ccecb_init(ecb, ecbkey, kKeySize, rawkey); + ccecb_init(ecb, ecbkey, kBCKeySize, rawkey); ccecb_update(ecb, ecbkey, 1, CFDataGetMutableBytePtr(key), CFDataGetMutableBytePtr(key)); ccecb_ctx_clear(ccecb_context_size(ecb), ecbkey); @@ -157,7 +157,7 @@ SecBreadcrumbCreateFromPassword(CFStringRef inPassword, * */ - memset(rawkey, 0, sizeof(rawkey)); + cc_clear(sizeof(rawkey), rawkey); CFReleaseNull(pw); *outBreadcrumb = npw; @@ -175,7 +175,6 @@ SecBreadcrumbCopyPassword(CFStringRef inPassword, CFErrorRef *outError) { const struct ccmode_ecb *ecb = ccaes_ecb_decrypt_mode(); - const struct ccdigest_info *di = ccsha256_di(); CFMutableDataRef gcmkey, oldpw; CFIndex outLength; CFDataRef pw; @@ -185,19 +184,19 @@ SecBreadcrumbCopyPassword(CFStringRef inPassword, if (outError) *outError = NULL; - if (CFDataGetLength(inEncryptedKey) < kKeySize + kSaltSize + 4) { + if (CFDataGetLength(inEncryptedKey) < kBCKeySize + kBCSaltSize + 4) { return false; } if (CFDataGetBytePtr(inBreadcrumb)[0] == BCversion1) { - if (CFDataGetLength(inBreadcrumb) < 1 + 4 + paddingSize + tagLen) + if (CFDataGetLength(inBreadcrumb) < 1 + 4 + BCPaddingSize + BCTagLen) return false; - outLength = CFDataGetLength(inBreadcrumb) - 1 - tagLen; + outLength = CFDataGetLength(inBreadcrumb) - 1 - BCTagLen; } else if (CFDataGetBytePtr(inBreadcrumb)[0] == BCversion2) { - if (CFDataGetLength(inBreadcrumb) < 1 + ivLen + 4 + paddingSize + tagLen) + if (CFDataGetLength(inBreadcrumb) < 1 + BCIVLen + 4 + BCPaddingSize + BCTagLen) return false; - outLength = CFDataGetLength(inBreadcrumb) - 1 - ivLen - tagLen; + outLength = CFDataGetLength(inBreadcrumb) - 1 - BCIVLen - BCTagLen; } else { return false; } @@ -234,15 +233,16 @@ SecBreadcrumbCopyPassword(CFStringRef inPassword, * Wrapping key is HMAC(sha256) over password */ - if (di->output_size < kKeySize) abort(); - - uint8_t rawkey[di->output_size]; - - memcpy(&size, CFDataGetMutableBytePtr(gcmkey) + kKeySize + kSaltSize, sizeof(size)); + 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), - kSaltSize, CFDataGetMutableBytePtr(gcmkey) + kKeySize, + kBCSaltSize, CFDataGetMutableBytePtr(gcmkey) + kBCKeySize, size, sizeof(rawkey), rawkey) != 0) abort(); @@ -254,21 +254,21 @@ SecBreadcrumbCopyPassword(CFStringRef inPassword, */ ccecb_ctx_decl(ccecb_context_size(ecb), ecbkey); - ccecb_init(ecb, ecbkey, kKeySize, rawkey); + 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[tagLen]; + uint8_t tag[BCTagLen]; if (CFDataGetBytePtr(inBreadcrumb)[0] == BCversion1) { - memcpy(tag, CFDataGetBytePtr(inBreadcrumb) + 1 + outLength, tagLen); + memcpy(tag, CFDataGetBytePtr(inBreadcrumb) + 1 + outLength, BCTagLen); - ccgcm_one_shot_legacy(ccaes_gcm_decrypt_mode(), kKeySize, CFDataGetMutableBytePtr(gcmkey), 0, NULL, 1, CFDataGetBytePtr(inBreadcrumb), - outLength, CFDataGetBytePtr(inBreadcrumb) + 1, CFDataGetMutableBytePtr(oldpw), tagLen, tag); - if (memcmp(tag, CFDataGetBytePtr(inBreadcrumb) + 1 + outLength, tagLen) != 0) { + 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; @@ -277,13 +277,13 @@ SecBreadcrumbCopyPassword(CFStringRef inPassword, } else { const uint8_t *iv = CFDataGetBytePtr(inBreadcrumb) + 1; int res; - memcpy(tag, CFDataGetBytePtr(inBreadcrumb) + 1 + ivLen + outLength, tagLen); + memcpy(tag, CFDataGetBytePtr(inBreadcrumb) + 1 + BCIVLen + outLength, BCTagLen); - res = ccgcm_one_shot(ccaes_gcm_decrypt_mode(), kKeySize, CFDataGetMutableBytePtr(gcmkey), - ivLen, iv, + res = ccgcm_one_shot(ccaes_gcm_decrypt_mode(), kBCKeySize, CFDataGetMutableBytePtr(gcmkey), + BCIVLen, iv, 1, CFDataGetBytePtr(inBreadcrumb), - outLength, CFDataGetBytePtr(inBreadcrumb) + 1 + ivLen, CFDataGetMutableBytePtr(oldpw), - tagLen, tag); + outLength, CFDataGetBytePtr(inBreadcrumb) + 1 + BCIVLen, CFDataGetMutableBytePtr(oldpw), + BCTagLen, tag); if (res) { CFReleaseNull(gcmkey); CFReleaseNull(oldpw); @@ -319,11 +319,14 @@ SecBreadcrumbCreateNewEncryptedKey(CFStringRef oldPassword, 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(); - CFMutableDataRef newEncryptedKey; + uint8_t rawkey[CCSHA256_OUTPUT_SIZE]; CFDataRef newpw = NULL, oldpw = NULL; - uint8_t rawkey[di->output_size]; - - if (CFDataGetLength(encryptedKey) < kKeySize + kSaltSize + 4) { + 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; } @@ -345,19 +348,17 @@ SecBreadcrumbCreateNewEncryptedKey(CFStringRef oldPassword, return false; } - if (di->output_size < kKeySize) abort(); - /* * Unwrap with new key */ uint32_t iter; - memcpy(&iter, CFDataGetMutableBytePtr(newEncryptedKey) + kKeySize + kSaltSize, sizeof(iter)); + memcpy(&iter, CFDataGetMutableBytePtr(newEncryptedKey) + kBCKeySize + kBCSaltSize, sizeof(iter)); iter = ntohl(iter); if (ccpbkdf2_hmac(di, CFDataGetLength(oldpw), CFDataGetBytePtr(oldpw), - kSaltSize, CFDataGetMutableBytePtr(newEncryptedKey) + kKeySize, + kBCSaltSize, CFDataGetMutableBytePtr(newEncryptedKey) + kBCKeySize, iter, sizeof(rawkey), rawkey) != 0) abort(); @@ -366,18 +367,18 @@ SecBreadcrumbCreateNewEncryptedKey(CFStringRef oldPassword, ccecb_ctx_decl(dec->size, deckey); - ccecb_init(dec, deckey, kKeySize, rawkey); + ccecb_init(dec, deckey, kBCKeySize, rawkey); ccecb_update(dec, deckey, 1, CFDataGetMutableBytePtr(newEncryptedKey), CFDataGetMutableBytePtr(newEncryptedKey)); ccecb_ctx_clear(ccecb_context_size(dec), deckey); - memset(rawkey, 0, sizeof(rawkey)); - + cc_clear(sizeof(rawkey), rawkey); + /* * Re-wrap with new key */ if (ccpbkdf2_hmac(di, CFDataGetLength(newpw), CFDataGetBytePtr(newpw), - kSaltSize, CFDataGetMutableBytePtr(newEncryptedKey) + kKeySize, + kBCSaltSize, CFDataGetMutableBytePtr(newEncryptedKey) + kBCKeySize, iter, sizeof(rawkey), rawkey) != 0) abort(); @@ -386,11 +387,11 @@ SecBreadcrumbCreateNewEncryptedKey(CFStringRef oldPassword, ccecb_ctx_decl(enc->size, enckey); - ccecb_init(enc, enckey, kKeySize, rawkey); + ccecb_init(enc, enckey, kBCKeySize, rawkey); ccecb_update(enc, enckey, 1, CFDataGetMutableBytePtr(newEncryptedKey), CFDataGetMutableBytePtr(newEncryptedKey)); ccecb_ctx_clear(ccecb_context_size(enc), enckey); - memset(rawkey, 0, sizeof(rawkey)); + cc_clear(sizeof(rawkey), rawkey); return newEncryptedKey; } diff --git a/OSX/Keychain Circle Notification/KNAppDelegate.m b/OSX/Keychain Circle Notification/KNAppDelegate.m index c8995b949..2c9138260 100644 --- a/OSX/Keychain Circle Notification/KNAppDelegate.m +++ b/OSX/Keychain Circle Notification/KNAppDelegate.m @@ -31,6 +31,8 @@ #import #import "notify.h" #import +#import +#import #import #import @@ -67,6 +69,15 @@ @implementation KNAppDelegate type: _NSUserNotificationCenterTypeSystem]; } +static BOOL isErrorFromXPC(CFErrorRef error) +{ + // Error due to XPC failure does not provide information about the circle. + if (error && (CFEqual(sSecXPCErrorDomain, CFErrorGetDomain(error)))) { + return YES; + } + return NO; +} + static void PSKeychainSyncIsUsingICDP(void) { ACAccountStore *accountStore = [[ACAccountStore alloc] init]; @@ -215,10 +226,227 @@ - (NSTimeInterval) getPendingApplicationReminderInterval return 24*60*60; } +- (NSMutableSet *) makeApplicantSet { + KNAppDelegate *me = self; + NSMutableSet *applicantIds = [NSMutableSet new]; + for (KDCirclePeer *applicant in me.circle.applicants) { + [me postForApplicant:applicant]; + [applicantIds addObject:applicant.idString]; + } + return applicantIds; +} + +- (bool) removeAllNotificationsOfType: (NSString *) typeString { + bool didRemove = false; + NSUserNotificationCenter *noteCenter = appropriateNotificationCenter(); + for (NSUserNotification *note in noteCenter.deliveredNotifications) { + if (note.userInfo[typeString]) { + [appropriateNotificationCenter() removeDeliveredNotification: note]; + didRemove = true; + } + } + return didRemove; +} + +static const char *sosCCStatusCString(SOSCCStatus status) { + switch(status) { + case kSOSCCError: return "kSOSCCError"; + case kSOSCCInCircle: return "kSOSCCInCircle"; + case kSOSCCNotInCircle: return "kSOSCCNotInCircle"; + case kSOSCCCircleAbsent: return "kSOSCCCircleAbsent"; + case kSOSCCRequestPending: return "kSOSCCRequestPending"; + default: return "unknown"; + } +} + +static const char *sosDepartureReasonCString(enum DepartureReason departureReason){ + switch(departureReason) { + case kSOSDepartureReasonError: return "kSOSDepartureReasonError"; + case kSOSNeverLeftCircle: return "kSOSNeverLeftCircle"; + case kSOSWithdrewMembership: return "kSOSWithdrewMembership"; + case kSOSMembershipRevoked: return "kSOSMembershipRevoked"; + case kSOSLeftUntrustedCircle: return "kSOSLeftUntrustedCircle"; + case kSOSNeverAppliedToCircle: return "kSOSNeverAppliedToCircle"; + case kSOSDiscoveredRetirement: return "kSOSDiscoveredRetirement"; + case kSOSLostPrivateKey: return "kSOSLostPrivateKey"; + default: return "unknown reason"; + } +} + -#define ICKC_EVENT_DISABLED "com.apple.security.secureobjectsync.disabled" -#define ICKC_EVENT_DEPARTURE_REASON "com.apple.security.secureobjectsync.departurereason" -#define ICKC_EVENT_NUM_PEERS "com.apple.security.secureobjectsync.numcircledevices" +- (void) processCircleState { + CFErrorRef err = NULL; + KNAppDelegate *me = self; + + enum DepartureReason departureReason = SOSCCGetLastDepartureReason(&err); + if (isErrorFromXPC(err)) { + secnotice("kcn", "SOSCCGetLastDepartureReason failed with xpc error: %@", err); + CFReleaseNull(err); + return; + } else if (err) { + secnotice("kcn", "SOSCCGetLastDepartureReason failed with: %@", err); + } + CFReleaseNull(err); + + SOSCCStatus circleStatus = SOSCCThisDeviceIsInCircle(&err); + if (isErrorFromXPC(err)) { + secnotice("kcn", "SOSCCThisDeviceIsInCircle failed with xpc error: %@", err); + CFReleaseNull(err); + return; + } else if (err) { + secnotice("kcn", "SOSCCThisDeviceIsInCircle failed with: %@", err); + } + CFReleaseNull(err); + + NSDate *nowish = [NSDate date]; + me.state = [KNPersistentState loadFromStorage]; + SOSCCStatus lastCircleStatus = me.state.lastCircleStatus; + + PSKeychainSyncIsUsingICDP(); + + secnotice("kcn", "processCircleState starting ICDP: %s SOSCCStatus: %s DepartureReason: %s", + (_isAccountICDP) ? "Enabled": "Disabled", + sosCCStatusCString(circleStatus), + sosDepartureReasonCString(departureReason)); + + if(_isAccountICDP){ + me.state.lastCircleStatus = circleStatus; + [me.state writeToStorage]; + + switch(circleStatus) { + case kSOSCCInCircle: + secnotice("kcn", "iCDP: device is in circle!"); + _hasPostedAndStillInError = false; + break; + case kSOSCCRequestPending: + [me scheduleActivityAt:me.state.pendingApplicationReminder]; + break; + case kSOSCCCircleAbsent: + case kSOSCCNotInCircle: + [me outOfCircleAlert: departureReason]; + secnotice("kcn", "{ChangeCallback} Pending request START"); + me.state.applicationDate = nowish; + me.state.pendingApplicationReminder = [me.state.applicationDate dateByAddingTimeInterval:[me getPendingApplicationReminderInterval]]; + [me.state writeToStorage]; // FIXME: move below? might be needed for scheduleActivityAt... + [me scheduleActivityAt:me.state.pendingApplicationReminder]; + break; + case kSOSCCError: + /* + You would think we could count on not being iCDP if the account was signed out. Evidently that's wrong. + So we'll go based on the artifact that when the account object is reset (like by signing out) the + departureReason will be set to kSOSDepartureReasonError. So we won't push to get back into a circle if that's + the current reason. I've checked code for other ways we could be out. If we boot and can't load the account + we'll end up with kSOSDepartureReasonError. Then too if we end up in kSOSDepartureReasonError and reboot we end up + in the same place. Leave it to cdpd to decide whether the user needs to sign in to an account. + */ + if(departureReason != kSOSDepartureReasonError) { + secnotice("kcn", "ICDP: We need the password to initiate trust"); + [me postRequirePassword]; + _hasPostedAndStillInError = true; + } else { + secnotice("kcn", "iCDP: We appear to not be associated with an iCloud account"); + } + break; + default: + secnotice("kcn", "Bad SOSCCStatus return %d", circleStatus); + break; + } + } else { // SA version + switch(circleStatus) { + case kSOSCCInCircle: + secnotice("kcn", "SA: device is in circle!"); + _hasPostedAndStillInError = false; + break; + case kSOSCCRequestPending: + [me scheduleActivityAt:me.state.pendingApplicationReminder]; + secnotice("kcn", "{ChangeCallback} scheduleActivity %@", me.state.pendingApplicationReminder); + break; + case kSOSCCCircleAbsent: + case kSOSCCNotInCircle: + switch (departureReason) { + case kSOSDiscoveredRetirement: + case kSOSLostPrivateKey: + case kSOSWithdrewMembership: + case kSOSNeverAppliedToCircle: + case kSOSDepartureReasonError: + case kSOSMembershipRevoked: + default: + if(me.state.lastCircleStatus == kSOSCCInCircle) { + secnotice("kcn", "SA: circle status went from in circle to %s: reason: %s", sosCCStatusCString(circleStatus), sosDepartureReasonCString(departureReason)); + } + break; + + case kSOSNeverLeftCircle: + case kSOSLeftUntrustedCircle: + [me outOfCircleAlert: departureReason]; + secnotice("kcn", "{ChangeCallback} Pending request START"); + me.state.applicationDate = nowish; + me.state.pendingApplicationReminder = [me.state.applicationDate dateByAddingTimeInterval:[me getPendingApplicationReminderInterval]]; + [me.state writeToStorage]; // FIXME: move below? might be needed for scheduleActivityAt... + [me scheduleActivityAt:me.state.pendingApplicationReminder]; + break; + } + break; + case kSOSCCError: + if(me.state.lastCircleStatus == kSOSCCInCircle && (departureReason == kSOSNeverLeftCircle)) { + secnotice("kcn", "SA: circle status went from in circle to error - we need the password"); + [me postRequirePassword]; + _hasPostedAndStillInError = true; + } + break; + default: + secnotice("kcn", "Bad SOSCCStatus return %d", circleStatus); + break; + } + } + + + // Circle applications: pending request(s) started / completed + if (lastCircleStatus == kSOSCCRequestPending && circleStatus != kSOSCCRequestPending) { + secnotice("kcn", "Pending request completed"); + me.state.applicationDate = [NSDate distantPast]; + me.state.pendingApplicationReminder = [NSDate distantFuture]; + [me.state writeToStorage]; + + // Remove reminders + if([me removeAllNotificationsOfType: @"ApplicationReminder"]) { + secnotice("kcn", "{ChangeCallback} removed application remoinders"); + } + } + + // Clear out (old) reset notifications + if (circleStatus == kSOSCCInCircle) { + secnotice("kcn", "{ChangeCallback} kSOSCCInCircle"); + if([me removeAllNotificationsOfType: (NSString*) kValidOnlyOutOfCircleKey]) { + secnotice("kcn", "Removed existing notifications now that we're in circle"); + } + if([me removeAllNotificationsOfType: (NSString*) kPasswordChangedOrTrustedDeviceChanged]) { + secnotice("kcn", "Removed existing password notifications now that we're in circle"); + } + + // Applicants + secnotice("kcn", "{ChangeCallback} Applicants"); + NSMutableSet *applicantIds = [me makeApplicantSet]; + // Clear applicant notifications that aren't pending any more + NSUserNotificationCenter *notificationCenter = appropriateNotificationCenter(); + secnotice("kcn", "Checking validity of %lu notes", (unsigned long)notificationCenter.deliveredNotifications.count); + for (NSUserNotification *note in notificationCenter.deliveredNotifications) { + if (note.userInfo[@"applicantId"] && ![applicantIds containsObject:note.userInfo[@"applicantId"]]) { + secnotice("kcn", "No longer an applicant (%@) for %@ (I=%@)", note.userInfo[@"applicantId"], note, [note.userInfo compactDescription]); + [notificationCenter removeDeliveredNotification:note]; + } else { + secnotice("kcn", "Still an applicant (%@) for %@ (I=%@)", note.userInfo[@"applicantId"], note, [note.userInfo compactDescription]); + } + } + } else { // Clear any pending applicant notifications since we aren't in circle or invalid + if([me removeAllNotificationsOfType: (NSString*) @"applicantId"]) { + secnotice("kcn", "Not in circle or invalid - removed applicant notes"); + } + } + + me.state.lastCircleStatus = circleStatus; + [me.state writeToStorage]; +} - (void) applicationDidFinishLaunching: (NSNotification *) aNotification { @@ -231,46 +459,26 @@ - (void) applicationDidFinishLaunching: (NSNotification *) aNotification CFErrorRef err = NULL; KNAppDelegate *me = self; SOSCCStatus currentCircleStatus = SOSCCThisDeviceIsInCircle(&err); + + if (isErrorFromXPC(err)) { + secnotice("kcn", "SOSCCThisDeviceIsInCircle failed with: %@", err); + CFReleaseNull(err); + return; + } + CFReleaseNull(err); + me.state = [KNPersistentState loadFromStorage]; secnotice("kcn", "got public key available notification"); - me.state.lastCircleStatus = currentCircleStatus; - [me.state writeToStorage]; }); //register for public key not available notification, if occurs KCN can react notify_register_dispatch(kPublicKeyNotAvailable, &out_taken, dispatch_get_main_queue(), ^(int token) { - CFErrorRef err = NULL; + secnotice("kcn", "got public key not available notification"); KNAppDelegate *me = self; - enum DepartureReason departureReason = SOSCCGetLastDepartureReason(&err); - SOSCCStatus currentCircleStatus = SOSCCThisDeviceIsInCircle(&err); - me.state = [KNPersistentState loadFromStorage]; - - secnotice("kcn", "got public key not available notification, but won't send notification unless circle transition matches"); - secnotice("kcn", "current circle status: %d, current departure reason: %d, last circle status: %d", currentCircleStatus, departureReason, me.state.lastCircleStatus); - - PSKeychainSyncIsUsingICDP(); - - if(_isAccountICDP){ - if((currentCircleStatus == kSOSCCError || currentCircleStatus == kSOSCCCircleAbsent || currentCircleStatus == kSOSCCNotInCircle) && _hasPostedAndStillInError == false) { - secnotice("kcn", "iCDP: device not in circle, posting follow up"); - [self postRequirePassword]; - _hasPostedAndStillInError = true; - } - else if(currentCircleStatus == kSOSCCInCircle){ - secnotice("kcn", "iCDP: device is in circle!"); - _hasPostedAndStillInError = false; - } - } - else if(!_isAccountICDP && currentCircleStatus == kSOSCCError && me.state.lastCircleStatus == kSOSCCInCircle && (departureReason == kSOSNeverLeftCircle)) { - secnotice("kcn", "circle status went from in circle to not in circle"); - [self postRequirePassword]; - } - me.state.lastCircleStatus = currentCircleStatus; - - [me.state writeToStorage]; + [me processCircleState]; }); self.viewedIds = [NSMutableSet new]; @@ -279,206 +487,8 @@ - (void) applicationDidFinishLaunching: (NSNotification *) aNotification [self.circle addChangeCallback:^{ secnotice("kcn", "{ChangeCallback}"); - - CFErrorRef err = NULL; - - NSDate *nowish = [NSDate date]; - enum DepartureReason departureReason = SOSCCGetLastDepartureReason(&err); - SOSCCStatus circleStatus = SOSCCThisDeviceIsInCircle(&err); - me.state = [KNPersistentState loadFromStorage]; - secnotice("kcn", "applicationDidFinishLaunching"); - - PSKeychainSyncIsUsingICDP(); - - if(_isAccountICDP){ - if((circleStatus == kSOSCCError || circleStatus == kSOSCCCircleAbsent || circleStatus == kSOSCCNotInCircle) && _hasPostedAndStillInError == false) { - - secnotice("kcn", "ICDP: We need the password to re-validate ourselves - it's changed on another device"); - me.state.lastCircleStatus = circleStatus; - [me.state writeToStorage]; - [me postRequirePassword]; - _hasPostedAndStillInError = true; - } - else if(circleStatus == kSOSCCInCircle){ - secnotice("kcn", "iCDP: device is in circle!"); - _hasPostedAndStillInError = false; - } - } - else if(!_isAccountICDP && circleStatus == kSOSCCError && me.state.lastCircleStatus == kSOSCCInCircle && (departureReason == kSOSNeverLeftCircle)) { - secnotice("kcn", "SA: circle status went from in circle to not in circle"); - [me postRequirePassword]; - } - // Pending application reminder - secnotice("kcn", "{ChangeCallback} scheduleActivity %@", me.state.pendingApplicationReminder); - if (circleStatus == kSOSCCRequestPending) - [me scheduleActivityAt:me.state.pendingApplicationReminder]; - - - // No longer in circle? - if ((me.state.lastCircleStatus == kSOSCCInCircle && (circleStatus == kSOSCCNotInCircle || circleStatus == kSOSCCCircleAbsent)) || - (me.state.lastCircleStatus == kSOSCCCircleAbsent && circleStatus == kSOSCCNotInCircle && me.state.absentCircleWithNoReason) || - me.state.debugLeftReason) { - enum DepartureReason reason = kSOSNeverLeftCircle; - if (me.state.debugLeftReason) { - reason = [me.state.debugLeftReason intValue]; - me.state.debugLeftReason = nil; - [me.state writeToStorage]; - } else { - reason = SOSCCGetLastDepartureReason(&err); - if (reason == kSOSDepartureReasonError) { - secnotice("kcn", "SOSCCGetLastDepartureReason err: %@", err); - } - if (err) CFRelease(err); - } - - if (reason != kSOSDepartureReasonError) { - // Post kick-out alert - - // MessageTracer data to find out how many users were dropped & reset - msgtracer_domain_t domain = msgtracer_domain_new(ICKC_EVENT_DISABLED); - msgtracer_msg_t mt_msg = NULL; - - if (domain != NULL) - mt_msg = msgtracer_msg_new(domain); - - if (mt_msg) { - char s[16]; - - msgtracer_set(mt_msg, kMsgTracerKeySignature, ICKC_EVENT_DEPARTURE_REASON); - snprintf(s, sizeof(s), "%u", reason); - msgtracer_set(mt_msg, kMsgTracerKeyValue, s); - - int64_t num_peers = 0; - CFArrayRef peerList = SOSCCCopyPeerPeerInfo(NULL); - if (peerList) { - num_peers = CFArrayGetCount(peerList); - if (num_peers > 99) { - // Round down # peers to 2 significant digits - int factor; - for (factor = 10; num_peers >= 100*factor; factor *= 10) ; - num_peers = (num_peers / factor) * factor; - } - CFRelease(peerList); - } - msgtracer_set(mt_msg, kMsgTracerKeySignature2, ICKC_EVENT_NUM_PEERS); - snprintf(s, sizeof(s), "%lld", num_peers); - msgtracer_set(mt_msg, kMsgTracerKeyValue2, s); - - msgtracer_set(mt_msg, kMsgTracerKeySummarize, "NO"); - msgtracer_log(mt_msg, ASL_LEVEL_DEBUG, ""); - } - - // FIXME: - // 1. Write here due to [me timerCheck] => [KNPersistentState loadFromStorage] below?!? - // 2. Or change call order of timerCheck, pendingApplication reminder below??? - me.state.absentCircleWithNoReason = (circleStatus == kSOSCCCircleAbsent && reason == kSOSNeverLeftCircle); - [me.state writeToStorage]; - secnotice("kcn", "{ChangeCallback} departure reason %d", reason); - - switch (reason) { - case kSOSDiscoveredRetirement: - case kSOSLostPrivateKey: - case kSOSWithdrewMembership: - case kSOSNeverAppliedToCircle: - break; - - case kSOSNeverLeftCircle: - case kSOSMembershipRevoked: - case kSOSLeftUntrustedCircle: - default: - [me postKickedOutAlert: reason]; - break; - } - } - } - - - // Circle applications: pending request(s) started / completed - if (me.circle.rawStatus != me.state.lastCircleStatus) { - SOSCCStatus lastCircleStatus = me.state.lastCircleStatus; - me.state.lastCircleStatus = circleStatus; - - if (lastCircleStatus != kSOSCCRequestPending && circleStatus == kSOSCCRequestPending) { - secnotice("kcn", "{ChangeCallback} Pending request START"); - me.state.applicationDate = nowish; - me.state.pendingApplicationReminder = [me.state.applicationDate dateByAddingTimeInterval:[me getPendingApplicationReminderInterval]]; - [me.state writeToStorage]; // FIXME: move below? might be needed for scheduleActivityAt... - [me scheduleActivityAt:me.state.pendingApplicationReminder]; - } - - if (lastCircleStatus == kSOSCCRequestPending && circleStatus != kSOSCCRequestPending) { - secnotice("kcn", "Pending request completed"); - me.state.applicationDate = [NSDate distantPast]; - me.state.pendingApplicationReminder = [NSDate distantFuture]; - [me.state writeToStorage]; - - // Remove reminders - NSUserNotificationCenter *noteCenter = appropriateNotificationCenter(); - for (NSUserNotification *note in noteCenter.deliveredNotifications) { - if (note.userInfo[(NSString*) kValidOnlyOutOfCircleKey] && note.userInfo[@"ApplicationReminder"]) { - secnotice("kcn", "{ChangeCallback} Removing notification %@", note); - [appropriateNotificationCenter() removeDeliveredNotification: note]; - } - } - } - } - - - // Clear out (old) reset notifications - if (me.circle.isInCircle) { - secnotice("kcn", "{ChangeCallback} me.circle.isInCircle"); - NSUserNotificationCenter *noteCenter = appropriateNotificationCenter(); - for (NSUserNotification *note in noteCenter.deliveredNotifications) { - if (note.userInfo[(NSString*) kValidOnlyOutOfCircleKey]) { - secnotice("kcn", "Removing existing notification (%@) now that we are in circle", note); - [appropriateNotificationCenter() removeDeliveredNotification: note]; - } - } - } - - //Clear out (old) password changed notifications - if(me.circle.isInCircle){ - secnotice("kcn", "{ChangeCallback} me.circle.isInCircle"); - NSUserNotificationCenter *noteCenter = appropriateNotificationCenter(); - for (NSUserNotification *note in noteCenter.deliveredNotifications) { - if (note.userInfo[(NSString*) kPasswordChangedOrTrustedDeviceChanged]) { - secnotice("kcn", "Removing existing notification (%@) now that we are valid again", note); - [appropriateNotificationCenter() removeDeliveredNotification: note]; - } - } - - } - - // Applicants - secnotice("kcn", "{ChangeCallback} Applicants"); - NSMutableSet *applicantIds = [NSMutableSet new]; - for (KDCirclePeer *applicant in me.circle.applicants) { - if (!me.circle.isInCircle) { - // Don't yammer on about circles we aren't in, and don't announce our own - // join requests as if the user could approve them locally! - break; - } - [me postForApplicant:applicant]; - [applicantIds addObject:applicant.idString]; - } - - - // Update notifications - NSUserNotificationCenter *notificationCenter = appropriateNotificationCenter(); - secnotice("kcn", "Checking validity of %lu notes", (unsigned long)notificationCenter.deliveredNotifications.count); - for (NSUserNotification *note in notificationCenter.deliveredNotifications) { - if (note.userInfo[@"applicantId"] && ![applicantIds containsObject:note.userInfo[@"applicantId"]]) { - secnotice("kcn", "No longer an applicant (%@) for %@ (I=%@)", note.userInfo[@"applicantId"], note, [note.userInfo compactDescription]); - [notificationCenter removeDeliveredNotification:note]; - } else { - secnotice("kcn", "Still an applicant (%@) for %@ (I=%@)", note.userInfo[@"applicantId"], note, [note.userInfo compactDescription]); - } - } - - me.state.lastCircleStatus = circleStatus; - - [me.state writeToStorage]; - }]; + [me processCircleState]; + }]; } @@ -537,7 +547,7 @@ - (void) postForApplicant: (KDCirclePeer *) applicant note.title = [NSString stringWithFormat: (__bridge_transfer NSString *) SecCopyCKString(SEC_CK_APPROVAL_TITLE), applicant.name]; note.informativeText = [KNAppDelegate localisedApprovalBodyWithDeviceTypeFromPeerInfo:applicant.peerObject]; note._displayStyle = _NSUserNotificationDisplayStyleAlert; - note._identityImage = [NSImage bundleImage]; + note._identityImage = [NSImage bundleImageNamed:kAOSUISpyglassAppleID]; note._identityImageStyle = _NSUserNotificationIdentityImageStyleRectangleNoBorder; note.otherButtonTitle = (__bridge_transfer NSString *) SecCopyCKString(SEC_CK_DECLINE); note.actionButtonTitle = (__bridge_transfer NSString *) SecCopyCKString(SEC_CK_APPROVE); @@ -550,6 +560,7 @@ - (void) postForApplicant: (KDCirclePeer *) applicant secnotice("kcn", "About to post #%d/%lu (%@): %@", postCount, noteCenter.deliveredNotifications.count, applicant.idString, note); [appropriateNotificationCenter() deliverNotification:note]; + [self.viewedIds addObject:applicant.idString]; postCount++; } @@ -572,7 +583,18 @@ + (NSString *)localisedApprovalBodyWithDeviceTypeFromPeerInfo:(id)peerInfo { - (void) postRequirePassword { - if(!_isAccountICDP){ + SOSCCStatus currentCircleStatus = SOSCCThisDeviceIsInCircle(NULL); + if(currentCircleStatus != kSOSCCError) { + secnotice("kcn", "postRequirePassword when not needed"); + return; + } + + enum DepartureReason departureReason = SOSCCGetLastDepartureReason(NULL); + + if(_isAccountICDP){ + secnotice("kcn","would have posted needs password and then followed up"); + [self startFollowupKitRepair]; + } else if(departureReason == kSOSNeverLeftCircle) { // The only SA case for prompting NSUserNotificationCenter *noteCenter = appropriateNotificationCenter(); for (NSUserNotification *note in noteCenter.deliveredNotifications) { if (note.userInfo[(NSString*) kPasswordChangedOrTrustedDeviceChanged]) { @@ -587,14 +609,14 @@ - (void) postRequirePassword NSString *message = CFBridgingRelease(SecCopyCKString(SEC_CK_PWD_REQUIRED_BODY_OSX)); if (os_variant_has_internal_ui("iCloudKeychain")) { - NSString *reason_str = [NSString stringWithFormat:(__bridge_transfer NSString *) SecCopyCKString(SEC_CK_CR_REASON_INTERNAL), @"Device became untrusted or password changed"]; + NSString *reason_str = [NSString stringWithFormat:(__bridge_transfer NSString *) SecCopyCKString(SEC_CK_CR_REASON_INTERNAL), "Device became untrusted or password changed"]; message = [message stringByAppendingString: reason_str]; } NSUserNotification *note = [NSUserNotification new]; note.title = (__bridge_transfer NSString *) SecCopyCKString(SEC_CK_PWD_REQUIRED_TITLE); note.informativeText = message; - note._identityImage = [NSImage bundleImage]; + note._identityImage = [NSImage bundleImageNamed:kAOSUISpyglassAppleID]; note._identityImageStyle = _NSUserNotificationIdentityImageStyleRectangleNoBorder; note.otherButtonTitle = (__bridge_transfer NSString *) SecCopyCKString(SEC_CK_NOT_NOW); note.actionButtonTitle = (__bridge_transfer NSString *) SecCopyCKString(SEC_CK_CONTINUE); @@ -608,14 +630,12 @@ - (void) postRequirePassword secnotice("kcn", "body=%@", note.informativeText); secnotice("kcn", "About to post #-/%lu (PASSWORD/TRUSTED DEVICE): %@", noteCenter.deliveredNotifications.count, note); [appropriateNotificationCenter() deliverNotification:note]; - } - else{ - secnotice("kcn","would have posted needs password and then followed up"); - [self startFollowupKitRepair]; + } else { + secnotice("kcn", "postRequirePassword when not needed for SA"); } } -- (void) postKickedOutAlert: (int) reason +- (void) outOfCircleAlert: (int) reason { if(!_isAccountICDP){ @@ -633,19 +653,7 @@ - (void) postKickedOutAlert: (int) reason NSString *message = CFBridgingRelease(SecCopyCKString(SEC_CK_PWD_REQUIRED_BODY_OSX)); if (os_variant_has_internal_ui("iCloudKeychain")) { - static const char *departureReasonStrings[] = { - "kSOSDepartureReasonError", - "kSOSNeverLeftCircle", - "kSOSWithdrewMembership", - "kSOSMembershipRevoked", - "kSOSLeftUntrustedCircle", - "kSOSNeverAppliedToCircle", - "kSOSDiscoveredRetirement", - "kSOSLostPrivateKey", - "unknown reason" - }; - int idx = (kSOSDepartureReasonError <= reason && reason <= kSOSLostPrivateKey) ? reason : (kSOSLostPrivateKey + 1); - NSString *reason_str = [NSString stringWithFormat:(__bridge_transfer NSString *) SecCopyCKString(SEC_CK_CR_REASON_INTERNAL), departureReasonStrings[idx]]; + NSString *reason_str = [NSString stringWithFormat:(__bridge_transfer NSString *) SecCopyCKString(SEC_CK_CR_REASON_INTERNAL), sosDepartureReasonCString(reason)]; message = [message stringByAppendingString: reason_str]; } @@ -657,7 +665,7 @@ - (void) postKickedOutAlert: (int) reason NSUserNotification *note = [NSUserNotification new]; note.title = (__bridge_transfer NSString *) SecCopyCKString(SEC_CK_PWD_REQUIRED_TITLE); note.informativeText = message; - note._identityImage = [NSImage bundleImage]; + note._identityImage = [NSImage bundleImageNamed:kAOSUISpyglassAppleID]; note._identityImageStyle = _NSUserNotificationIdentityImageStyleRectangleNoBorder; note.otherButtonTitle = (__bridge_transfer NSString *) SecCopyCKString(SEC_CK_NOT_NOW); note.actionButtonTitle = (__bridge_transfer NSString *) SecCopyCKString(SEC_CK_CONTINUE); @@ -675,7 +683,7 @@ - (void) postKickedOutAlert: (int) reason } else{ - secnotice("kcn","postKickedOutAlert starting followup repair"); + secnotice("kcn","outOfCircleAlert starting followup repair"); [self startFollowupKitRepair]; } } @@ -702,7 +710,7 @@ - (void) postApplicationReminder NSUserNotification *note = [NSUserNotification new]; note.title = (__bridge_transfer NSString *) SecCopyCKString(SEC_CK_REMINDER_TITLE_OSX); note.informativeText = (__bridge_transfer NSString *) SecCopyCKString(SEC_CK_REMINDER_BODY_OSX); - note._identityImage = [NSImage bundleImage]; + note._identityImage = [NSImage bundleImageNamed:kAOSUISpyglassAppleID]; note._identityImageStyle = _NSUserNotificationIdentityImageStyleRectangleNoBorder; note.otherButtonTitle = (__bridge_transfer NSString *) SecCopyCKString(SEC_CK_NOT_NOW); note.actionButtonTitle = (__bridge_transfer NSString *) SecCopyCKString(SEC_CK_CONTINUE); diff --git a/OSX/Keychain/KDAppDelegate.m b/OSX/Keychain/KDAppDelegate.m index 58a2ff4d7..710d5fd64 100644 --- a/OSX/Keychain/KDAppDelegate.m +++ b/OSX/Keychain/KDAppDelegate.m @@ -85,11 +85,11 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification -(void)setCheckbox { if (self.circle.isInCircle) { - [self.enableKeychainSyncing setState:NSOnState]; + [self.enableKeychainSyncing setState:NSControlStateValueOn]; } else if (self.circle.isOutOfCircle) { - [self.enableKeychainSyncing setState:NSOffState]; + [self.enableKeychainSyncing setState:NSControlStateValueOff]; } else { - [self.enableKeychainSyncing setState:NSMixedState]; + [self.enableKeychainSyncing setState:NSControlStateValueMixed]; } } diff --git a/OSX/Keychain/KDSecCircle.m b/OSX/Keychain/KDSecCircle.m index f5b8d448f..66e36e7c1 100644 --- a/OSX/Keychain/KDSecCircle.m +++ b/OSX/Keychain/KDSecCircle.m @@ -57,6 +57,8 @@ -(void)updateCheck { // XXX: assert not on main_queue CFErrorRef err = NULL; + + SOSCCValidateUserPublic(NULL); // requires the account queue - makes the rest of this wait for fresh info. This used to happen in SOSCCThisDeviceIsInCircle(below) before we made it use cached info. SOSCCStatus newRawStatus = SOSCCThisDeviceIsInCircle(&err); NSArray *peerInfos = (__bridge NSArray *) SOSCCCopyApplicantPeerInfo(&err); NSMutableArray *newApplicants = [[NSMutableArray alloc] initWithCapacity:peerInfos.count]; diff --git a/OSX/SecurityTestsOSX/SecurityTests-Entitlements.plist b/OSX/SecurityTestsOSX/SecurityTests-Entitlements.plist index 442596962..c1dd8e6c4 100644 --- a/OSX/SecurityTestsOSX/SecurityTests-Entitlements.plist +++ b/OSX/SecurityTestsOSX/SecurityTests-Entitlements.plist @@ -10,8 +10,12 @@ com.apple.keystore.access-keychain-keys + com.apple.keystore.sik.access + com.apple.keystore.device + com.apple.private.applecredentialmanager.allow + restore-keychain migrate-keychain @@ -24,8 +28,12 @@ application-identifier com.apple.security.regressions + com.apple.application-identifier + com.apple.security.regressions com.apple.private.uninstall.deletion + com.apple.private.security.delete.all + keychain-access-groups com.apple.security.regressions @@ -36,17 +44,5 @@ 123456.test.group2 com.apple.bluetooth - com.apple.private.ubiquity-kvstore-access - - com.apple.securityd - - com.apple.developer.ubiquity-kvstore-identifier - com.apple.security.cloudkeychainproxy3 - com.apple.developer.ubiquity-container-identifiers - - com.apple.security.cloudkeychainproxy3 - com.apple.security.cloudkeychain - CloudKeychainProxy.xpc - diff --git a/OSX/SecurityTestsOSX/testlist.h b/OSX/SecurityTestsOSX/testlist.h index ea6b65792..5c3ef633c 100644 --- a/OSX/SecurityTestsOSX/testlist.h +++ b/OSX/SecurityTestsOSX/testlist.h @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include diff --git a/OSX/authd/agent.c b/OSX/authd/agent.c index 730835336..f6cf1f33d 100644 --- a/OSX/authd/agent.c +++ b/OSX/authd/agent.c @@ -139,7 +139,8 @@ agent_create(engine_t engine, mechanism_t mech, auth_token_t auth, process_t pro os_log_debug(AUTHD_LOG, "agent: creating a standard security agent"); } else { // Root session => loginwindow SecurityAgent - agent->agentConnection = xpc_connection_create_mach_service(SECURITYAGENT_LOGINWINDOW_BOOTSTRAP_NAME_BASE, NULL, 0); + agent->agentConnection = xpc_connection_create_mach_service(SECURITYAGENT_LOGINWINDOW_BOOTSTRAP_NAME_BASE, NULL, + XPC_CONNECTION_MACH_SERVICE_PRIVILEGED); xpc_connection_set_instance(agent->agentConnection, sessionUUID); os_log_debug(AUTHD_LOG, "agent: creating a loginwindow security agent"); doSwitchAudit = true; diff --git a/OSX/authd/authd-Entitlements.plist b/OSX/authd/authd-Entitlements.plist index 126b1f639..7ef4f57c7 100644 --- a/OSX/authd/authd-Entitlements.plist +++ b/OSX/authd/authd-Entitlements.plist @@ -4,5 +4,7 @@ com.apple.private.LocalAuthentication.ExtractCredential + com.apple.keystore.console + diff --git a/OSX/authd/authdb.c b/OSX/authd/authdb.c index df25c5694..c10ce840b 100644 --- a/OSX/authd/authdb.c +++ b/OSX/authd/authdb.c @@ -23,7 +23,7 @@ AUTHD_DEFINE_LOG #define AUTH_STR(x) #x #define AUTH_STRINGIFY(x) AUTH_STR(x) -#define AUTHDB_VERSION 1 +#define AUTHDB_VERSION 2 #define AUTHDB_VERSION_STRING AUTH_STRINGIFY(AUTHDB_VERSION) #define AUTHDB_BUSY_DELAY 1 @@ -105,7 +105,16 @@ static const char * const authdb_upgrade_sql[] = { "value TEXT NOT NULL" ");" "CREATE INDEX b_r_id ON buttons(r_id);" - "INSERT INTO config VALUES('version', "AUTHDB_VERSION_STRING");" + "INSERT INTO config VALUES('version', '1');" , + + // version 2 of the database + "CREATE TABLE rules_history (" + "timestamp DATETIME DEFAULT CURRENT_TIMESTAMP," + "rule TEXT NOT NULL," + "version INTEGER NOT NULL," + "source TEXT NOT NULL," + "operation INTEGER NOT NULL" + ");" }; static sqlite3 * _create_handle(authdb_t db); @@ -134,7 +143,8 @@ struct _db_upgrade_stages { }; static struct _db_upgrade_stages auth_upgrade_script[] = { - { .pre = -1, .main = 0, .post = -1 } // Create version AUTHDB_VERSION databse. + { .pre = -1, .main = 0, .post = -1 }, // Create version AUTHDB_VERSION databse. + { .pre = -1, .main = 1, .post = -1} }; static int32_t _db_run_script(authdb_connection_t dbconn, int number) @@ -174,7 +184,7 @@ static int32_t _db_upgrade_from_version(authdb_connection_t dbconn, int32_t vers return s3e; } -static void _db_load_data(authdb_connection_t dbconn, auth_items_t config) +static CFDictionaryRef _copy_plist(auth_items_t config, CFAbsoluteTime *outTs) { CFURLRef authURL = NULL; CFPropertyListRef plist = NULL; @@ -184,34 +194,96 @@ static void _db_load_data(authdb_connection_t dbconn, auth_items_t config) CFTypeRef value = NULL; CFAbsoluteTime ts = 0; CFAbsoluteTime old_ts = 0; - Boolean ok; - + Boolean ok; authURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR(AUTHDB_DATA), kCFURLPOSIXPathStyle, false); require_action(authURL != NULL, done, os_log_error(AUTHD_LOG, "authdb: file not found %{public}s", AUTHDB_DATA)); - - ok = CFURLCopyResourcePropertyForKey(authURL, kCFURLContentModificationDateKey, &value, &err); + + ok = CFURLCopyResourcePropertyForKey(authURL, kCFURLContentModificationDateKey, &value, &err); require_action(ok && value != NULL, done, os_log_error(AUTHD_LOG, "authdb: failed to get modification date: %{public}@", err)); if (CFGetTypeID(value) == CFDateGetTypeID()) { ts = CFDateGetAbsoluteTime(value); + if (outTs) { + *outTs = ts; + } } - old_ts = auth_items_get_double(config, "data_ts"); - - // SEED: BUG: Fast User Switching Not Working - // After Mavericks => Yosemite upgrade install, the new Yosemite rule "system.login.fus" was missing. - // Somehow (probably during install) ts < old_ts, even though that should never happen. - // Solution: always import plist and update db when time stamps don't match. - // After a successful import, old_ts = ts below. - if (ts != old_ts) { + if (config) { + old_ts = auth_items_get_double(config, "data_ts"); + } + + // SEED: BUG: Fast User Switching Not Working + // After Mavericks => Yosemite upgrade install, the new Yosemite rule "system.login.fus" was missing. + // Somehow (probably during install) ts < old_ts, even though that should never happen. + // Solution: always import plist and update db when time stamps don't match. + // After a successful import, old_ts = ts below. + if (!config || (ts != old_ts)) { os_log_debug(AUTHD_LOG, "authdb: %{public}s modified old=%f, new=%f", AUTHDB_DATA, old_ts, ts); CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, authURL, &data, NULL, NULL, (SInt32*)&rc); require_noerr_action(rc, done, os_log_error(AUTHD_LOG, "authdb: failed to load %{public}s", AUTHDB_DATA)); - + plist = CFPropertyListCreateWithData(kCFAllocatorDefault, data, kCFPropertyListImmutable, NULL, &err); require_action(err == NULL, done, os_log_error(AUTHD_LOG, "authdb: failed to read plist: %{public}@", err)); - - if (authdb_import_plist(dbconn, plist, true)) { + } + +done: + CFReleaseSafe(authURL); + CFReleaseSafe(value); + CFReleaseSafe(err); + CFReleaseSafe(data); + + return plist; +} + +static void _repair_broken_kofn_right(authdb_connection_t dbconn, const char *right, CFDictionaryRef plist) +{ + if (!right || !dbconn) { + return; + } + + CFDictionaryRef localPlist = plist; + if (!localPlist) { + localPlist = _copy_plist(NULL, NULL); + } + + // import the broken right + os_log(AUTHD_LOG, "Repairing broken right %{public}s", right); + authdb_import_plist(dbconn, localPlist, FALSE, right); + + if (!plist && localPlist) { + CFRelease(localPlist); + } +} + +static void _repair_all_kofns(authdb_connection_t dbconn, auth_items_t config) +{ + // we want plist to be returned always and not only when never + CFDictionaryRef plist = _copy_plist(NULL, NULL); + + if (!plist) { + os_log_error(AUTHD_LOG, "authdb: unable to repair kofns"); + return; + } + + authdb_step(dbconn, "SELECT name FROM rules WHERE (rules.kofn > 0) AND (id NOT IN (SELECT r_id FROM delegates_map WHERE r_id = id))", + NULL, ^bool(auth_items_t data) { + const char *name = auth_items_get_string(data, "name"); + if (name) { + _repair_broken_kofn_right(dbconn, name, plist); + } + return false; + }); + + CFRelease(plist); +} + +static void _db_load_data(authdb_connection_t dbconn, auth_items_t config) +{ + CFAbsoluteTime ts = 0; + CFDictionaryRef plist = _copy_plist(config, &ts); + + if (plist) { + if (authdb_import_plist(dbconn, plist, true, NULL)) { os_log_debug(AUTHD_LOG, "authdb: updating data_ts"); auth_items_t update = auth_items_create(); auth_items_set_double(update, "data_ts", ts); @@ -219,13 +291,7 @@ static void _db_load_data(authdb_connection_t dbconn, auth_items_t config) CFReleaseSafe(update); } } - -done: - CFReleaseSafe(value); - CFReleaseSafe(authURL); CFReleaseSafe(plist); - CFReleaseSafe(err); - CFReleaseSafe(data); } static bool _truncate_db(authdb_connection_t dbconn) @@ -445,7 +511,7 @@ authdb_connection_t authdb_connection_acquire(authdb_t db) dbconn = authdb_connection_create(db); #if DEBUG total++; - os_log_debug(AUTHD_LOG, "authdb: no handles available total: %i", total); + os_log_debug(AUTHD_LOG, "authdb: handles count: %i", total); #endif } }); @@ -531,6 +597,7 @@ bool authdb_maintenance(authdb_connection_t dbconn) _db_load_data(dbconn, config); + _repair_all_kofns(dbconn, config); done: CFReleaseSafe(config); os_log_debug(AUTHD_LOG, "authdb: finished maintenance"); @@ -806,7 +873,7 @@ bool authdb_step(authdb_connection_t dbconn, const char * sql, void (^bind_stmt) break; default: if (_is_busy(rc)) { - os_log_debug(AUTHD_LOG, "authdb: %{public}s", sqlite3_errmsg(dbconn->handle)); + os_log(AUTHD_LOG, "authdb: %{public}s (will try to recover)", sqlite3_errmsg(dbconn->handle)); sleep(AUTHDB_BUSY_DELAY); sqlite3_reset(stmt); } else { @@ -859,7 +926,7 @@ _copy_rules_dict(RuleType type, CFDictionaryRef plist, authdb_connection_t dbcon } static void -_import_rules(authdb_connection_t dbconn, CFMutableArrayRef rules, bool version_check, CFAbsoluteTime now) +_import_rules(authdb_connection_t dbconn, CFMutableArrayRef rules, bool version_check, CFAbsoluteTime now, const char *nameFilter) { CFMutableArrayRef notcommited = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); CFIndex count = CFArrayGetCount(rules); @@ -867,6 +934,11 @@ _import_rules(authdb_connection_t dbconn, CFMutableArrayRef rules, bool version_ for (CFIndex i = 0; i < count; i++) { rule_t rule = (rule_t)CFArrayGetValueAtIndex(rules, i); + if (nameFilter && (strcmp(nameFilter, rule_get_name(rule)) != 0)) { + // current rule name does not match the requested filter + continue; + } + bool update = false; if (version_check) { if (rule_get_id(rule) != 0) { // rule already exists see if we need to update @@ -922,7 +994,7 @@ _import_rules(authdb_connection_t dbconn, CFMutableArrayRef rules, bool version_ } bool -authdb_import_plist(authdb_connection_t dbconn, CFDictionaryRef plist, bool version_check) +authdb_import_plist(authdb_connection_t dbconn, CFDictionaryRef plist, bool version_check, const char *name) { bool result = false; @@ -955,10 +1027,10 @@ authdb_import_plist(authdb_connection_t dbconn, CFDictionaryRef plist, bool vers if (!count) break; - _import_rules(dbconn, rules, version_check, now); + _import_rules(dbconn, rules, version_check, now, name); } - _import_rules(dbconn, rights, version_check, now); + _import_rules(dbconn, rights, version_check, now, name); if (CFArrayGetCount(rights) == 0) { result = true; @@ -1051,6 +1123,8 @@ static sqlite3 * _create_handle(authdb_t db) chmod(db->db_path, S_IRUSR | S_IWUSR); } + // Let SQLite handle timeouts. + sqlite3_busy_timeout(handle, 5*1000); done: return handle; } diff --git a/OSX/authd/authdb.h b/OSX/authd/authdb.h index 6e5f6b64b..5c31c62ad 100644 --- a/OSX/authd/authdb.h +++ b/OSX/authd/authdb.h @@ -44,7 +44,7 @@ int32_t authdb_exec(authdb_connection_t, const char *); AUTH_NONNULL_ALL bool authdb_transaction(authdb_connection_t, AuthDBTransactionType, bool (^t)(void)); -AUTH_NONNULL1 AUTH_NONNULL2 AUTH_NONNULL3 +AUTH_NONNULL1 AUTH_NONNULL2 bool authdb_step(authdb_connection_t, const char * sql, void (^bind_stmt)(sqlite3_stmt* stmt), authdb_iterator_t iter); AUTH_NONNULL_ALL @@ -56,9 +56,9 @@ int32_t authdb_set_key_value(authdb_connection_t, const char * table, auth_items AUTH_NONNULL_ALL void authdb_checkpoint(authdb_connection_t); -AUTH_NONNULL_ALL -bool authdb_import_plist(authdb_connection_t,CFDictionaryRef,bool); - +AUTH_NONNULL1 AUTH_NONNULL2 +bool authdb_import_plist(authdb_connection_t, CFDictionaryRef, bool, const char * name); + #pragma mark - #pragma mark authdb_connection_t diff --git a/OSX/authd/authitems.c b/OSX/authd/authitems.c index 50dc0a45c..ea49287ad 100644 --- a/OSX/authd/authitems.c +++ b/OSX/authd/authitems.c @@ -23,8 +23,6 @@ struct _auth_item_s { AuthorizationItem data; uint32_t type; size_t bufLen; - - CFStringRef cfKey; }; static const char * @@ -43,21 +41,6 @@ auth_item_get_string(auth_item_t item) return item->data.value; } -static CFStringRef -auth_item_get_cf_key(auth_item_t item) -{ - if (!item->cfKey) { - item->cfKey = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, item->data.name, kCFStringEncodingUTF8, kCFAllocatorNull); - } - return item->cfKey; -} - -static AuthorizationItem * -auth_item_get_auth_item(auth_item_t item) -{ - return &item->data; -} - static xpc_object_t auth_item_copy_auth_item_xpc(auth_item_t item) { @@ -90,9 +73,7 @@ static void _auth_item_finalize(CFTypeRef value) { auth_item_t item = (auth_item_t)value; - - CFReleaseNull(item->cfKey); - + if (item->data.name) { free((void*)item->data.name); /* cannot set item->data.name to NULL because item->data.name is non-nullable public API (rdar://problem/32235322) @@ -274,6 +255,10 @@ auth_item_create_with_xpc(xpc_object_t data) bool sensitive = xpc_dictionary_get_value(data, AUTH_XPC_ITEM_SENSITIVE_VALUE_LENGTH); if (sensitive) { size_t sensitiveLength = (size_t)xpc_dictionary_get_uint64(data, AUTH_XPC_ITEM_SENSITIVE_VALUE_LENGTH); + if (sensitiveLength > len) { + os_log_error(AUTHD_LOG, "Sensitive data len %zu is not valid", sensitiveLength); + goto done; + } item->bufLen = sensitiveLength; item->data.valueLength = sensitiveLength; item->data.value = calloc(1u, sensitiveLength); @@ -362,6 +347,16 @@ _auth_items_equal(CFTypeRef value1, CFTypeRef value2) return CFEqual(items1->dictionary, items2->dictionary); } +static void +auth_items_add_item(auth_items_t items, auth_item_t item) +{ + CFStringRef cfName = CFStringCreateWithCString(kCFAllocatorDefault, item->data.name, kCFStringEncodingUTF8); + if (cfName) { + CFDictionarySetValue(items->dictionary, cfName, item); + CFRelease(cfName); + } +} + static CFStringRef _auth_items_copy_description(CFTypeRef value) { @@ -430,8 +425,8 @@ _auth_items_parse_xpc(auth_items_t items, const xpc_object_t data) auth_item_t item = auth_item_create_with_xpc(value); if (item) { - CFDictionarySetValue(items->dictionary, auth_item_get_cf_key(item), item); - CFReleaseSafe(item); + auth_items_add_item(items, item); + CFRelease(item); } return true; @@ -474,36 +469,6 @@ auth_items_get_count(auth_items_t items) return (size_t)CFDictionaryGetCount(items->dictionary); } -AuthorizationItemSet * -auth_items_get_item_set(auth_items_t items) -{ - uint32_t count = (uint32_t)CFDictionaryGetCount(items->dictionary); - if (count) { - size_t size = count * sizeof(AuthorizationItem); - if (items->set.items == NULL) { - items->set.items = calloc(1u, size); - require(items->set.items != NULL, done); - } else { - if (count > items->set.count) { - items->set.items = realloc(items->set.items, size); - require_action(items->set.items != NULL, done, items->set.count = 0); - } - } - items->set.count = count; - CFTypeRef keys[count], values[count]; - CFDictionaryGetKeysAndValues(items->dictionary, keys, values); - for (uint32_t i = 0; i < count; i++) { - auth_item_t item = (auth_item_t)values[i]; - items->set.items[i] = *auth_item_get_auth_item(item); - } - } else { - items->set.count = 0; - } - -done: - return &items->set; -} - xpc_object_t auth_items_export_xpc(auth_items_t items) { @@ -584,8 +549,8 @@ auth_items_set_key(auth_items_t items, const char *key) if (!item) { item = auth_item_create(AI_TYPE_RIGHT, key, NULL, 0, 0); if (item) { - CFDictionarySetValue(items->dictionary, auth_item_get_cf_key(item), item); - CFReleaseSafe(item); + auth_items_add_item(items, item); + CFRelease(item); } } } @@ -649,9 +614,12 @@ void auth_items_copy(auth_items_t items, auth_items_t src) { auth_items_iterate(src, ^bool(const char *key) { + if (!key) { + return true; + } CFStringRef lookup = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, key, kCFStringEncodingUTF8, kCFAllocatorNull); auth_item_t item = (auth_item_t)CFDictionaryGetValue(src->dictionary, lookup); - CFDictionarySetValue(items->dictionary, auth_item_get_cf_key(item), item); + if (item) auth_items_add_item(items, item); CFReleaseSafe(lookup); return true; }); @@ -664,8 +632,7 @@ auth_items_content_copy(auth_items_t items, auth_items_t src) CFStringRef lookup = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, key, kCFStringEncodingUTF8, kCFAllocatorNull); auth_item_t item = (auth_item_t)CFDictionaryGetValue(src->dictionary, lookup); auth_item_t new_item = auth_item_create(item->type, item->data.name, item->data.value, item->data.valueLength, item->data.flags); - if (new_item) - CFDictionarySetValue(items->dictionary, auth_item_get_cf_key(new_item), new_item); + if (new_item) auth_items_add_item(items, new_item); CFReleaseSafe(lookup); CFReleaseSafe(new_item); return true; @@ -684,8 +651,11 @@ auth_items_copy_with_flags(auth_items_t items, auth_items_t src, uint32_t flags) auth_items_iterate(src, ^bool(const char *key) { if (auth_items_check_flags(src, key, flags)) { CFStringRef lookup = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, key, kCFStringEncodingUTF8, kCFAllocatorNull); + if (CFDictionaryContainsKey(items->dictionary, lookup)) { + CFDictionaryRemoveValue(items->dictionary, lookup); // we do not want to have preserved unretained key + } auth_item_t item = (auth_item_t)CFDictionaryGetValue(src->dictionary, lookup); - CFDictionarySetValue(items->dictionary, auth_item_get_cf_key(item), item); + if (item) auth_items_add_item(items, item); CFReleaseSafe(lookup); } return true; @@ -701,10 +671,11 @@ auth_items_content_copy_with_flags(auth_items_t items, auth_items_t src, uint32_ CFStringRef lookup = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, key, kCFStringEncodingUTF8, kCFAllocatorNull); auth_item_t item = (auth_item_t)CFDictionaryGetValue(src->dictionary, lookup); auth_item_t new_item = auth_item_create(item->type, item->data.name, item->data.value, item->data.valueLength, item->data.flags); - if (new_item) - CFDictionarySetValue(items->dictionary, auth_item_get_cf_key(new_item), new_item); + if (new_item) { + auth_items_add_item(items, new_item); + CFRelease(new_item); + } CFReleaseSafe(lookup); - CFReleaseSafe(new_item); } return true; }); @@ -752,8 +723,8 @@ auth_items_set_string(auth_items_t items, const char *key, const char *value) } else { item = auth_item_create(AI_TYPE_STRING, key, value, valLen, 0); if (item) { - CFDictionarySetValue(items->dictionary, auth_item_get_cf_key(item), item); - CFReleaseSafe(item); + auth_items_add_item(items, item); + CFRelease(item); } } } @@ -788,8 +759,8 @@ auth_items_set_data(auth_items_t items, const char *key, const void *value, size } else { item = auth_item_create(AI_TYPE_DATA, key, value, len, 0); if (item) { - CFDictionarySetValue(items->dictionary, auth_item_get_cf_key(item), item); - CFReleaseSafe(item); + auth_items_add_item(items, item); + CFRelease(item); } } } @@ -845,8 +816,8 @@ auth_items_set_bool(auth_items_t items, const char *key, bool value) } else { item = auth_item_create(AI_TYPE_BOOL, key, &value, sizeof(bool), 0); if (item) { - CFDictionarySetValue(items->dictionary, auth_item_get_cf_key(item), item); - CFReleaseSafe(item); + auth_items_add_item(items, item); + CFRelease(item); } } } @@ -885,8 +856,8 @@ auth_items_set_int(auth_items_t items, const char *key, int32_t value) } else { item = auth_item_create(AI_TYPE_INT, key, &value, sizeof(int32_t), 0); if (item) { - CFDictionarySetValue(items->dictionary, auth_item_get_cf_key(item), item); - CFReleaseSafe(item); + auth_items_add_item(items, item); + CFRelease(item); } } } @@ -925,8 +896,8 @@ auth_items_set_uint(auth_items_t items, const char *key, uint32_t value) } else { item = auth_item_create(AI_TYPE_UINT, key, &value, sizeof(uint32_t), 0); if (item) { - CFDictionarySetValue(items->dictionary, auth_item_get_cf_key(item), item); - CFReleaseSafe(item); + auth_items_add_item(items, item); + CFRelease(item); } } } @@ -965,8 +936,8 @@ auth_items_set_int64(auth_items_t items, const char *key, int64_t value) } else { item = auth_item_create(AI_TYPE_INT64, key, &value, sizeof(int64_t), 0); if (item) { - CFDictionarySetValue(items->dictionary, auth_item_get_cf_key(item), item); - CFReleaseSafe(item); + auth_items_add_item(items, item); + CFRelease(item); } } } @@ -1005,8 +976,8 @@ auth_items_set_uint64(auth_items_t items, const char *key, uint64_t value) } else { item = auth_item_create(AI_TYPE_UINT64, key, &value, sizeof(uint64_t), 0); if (item) { - CFDictionarySetValue(items->dictionary, auth_item_get_cf_key(item), item); - CFReleaseSafe(item); + auth_items_add_item(items, item); + CFRelease(item); } } } @@ -1044,8 +1015,8 @@ void auth_items_set_double(auth_items_t items, const char *key, double value) } else { item = auth_item_create(AI_TYPE_DOUBLE, key, &value, sizeof(double), 0); if (item) { - CFDictionarySetValue(items->dictionary, auth_item_get_cf_key(item), item); - CFReleaseSafe(item); + auth_items_add_item(items, item); + CFRelease(item); } } } @@ -1098,8 +1069,8 @@ void auth_items_set_value(auth_items_t items, const char *key, uint32_t type, ui { auth_item_t item = auth_item_create(type, key, value, len, flags); if (item) { - CFDictionarySetValue(items->dictionary, auth_item_get_cf_key(item), item); - CFReleaseSafe(item); + auth_items_add_item(items, item); + CFRelease(item); } } @@ -1223,23 +1194,18 @@ static auth_item_t _find_right_item(auth_rights_t rights, const char * key) { auth_item_t item = NULL; - CFStringRef lookup = NULL; require(key != NULL, done); - - lookup = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, key, kCFStringEncodingUTF8, kCFAllocatorNull); - require(lookup != NULL, done); - + CFIndex count = CFArrayGetCount(rights->array); for (CFIndex i = 0; i < count; i++) { auth_item_t tmp = (auth_item_t)CFArrayGetValueAtIndex(rights->array, i); - if (tmp && CFEqual(auth_item_get_cf_key(tmp), lookup)) { + if (tmp && strcmp(tmp->data.name, key) == 0) { item = tmp; break; } } done: - CFReleaseSafe(lookup); return item; } @@ -1296,17 +1262,15 @@ bool auth_rights_exist(auth_rights_t rights, const char *key) void auth_rights_remove(auth_rights_t rights, const char *key) { - CFStringRef lookup = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, key, kCFStringEncodingUTF8, kCFAllocatorNull); CFIndex count = CFArrayGetCount(rights->array); for (CFIndex i = 0; i < count; i++) { auth_item_t item = (auth_item_t)CFArrayGetValueAtIndex(rights->array, i); - if (CFEqual(auth_item_get_cf_key(item), lookup)) { + if (item && strcmp(item->data.name, key) == 0) { CFArrayRemoveValueAtIndex(rights->array, i); i--; count--; } } - CFReleaseSafe(lookup); } void auth_rights_clear(auth_rights_t rights) diff --git a/OSX/authd/authitems.h b/OSX/authd/authitems.h index 48bd82dff..57319a5af 100644 --- a/OSX/authd/authitems.h +++ b/OSX/authd/authitems.h @@ -46,9 +46,6 @@ auth_items_t auth_items_create_copy(auth_items_t); AUTH_WARN_RESULT AUTH_NONNULL_ALL size_t auth_items_get_count(auth_items_t); -AUTH_WARN_RESULT AUTH_NONNULL_ALL -AuthorizationItemSet * auth_items_get_item_set(auth_items_t); - AUTH_WARN_RESULT AUTH_NONNULL_ALL xpc_object_t auth_items_export_xpc(auth_items_t); diff --git a/OSX/authd/authorization.plist b/OSX/authd/authorization.plist index f4f68f3bf..2b135078b 100644 --- a/OSX/authd/authorization.plist +++ b/OSX/authd/authorization.plist @@ -58,10 +58,22 @@ See remaining rules for examples. allow-root + authenticate-user + class - user - group - admin + rule + k-of-n + 1 + rule + + is-root + is-admin + default + + shared + + version + 1 com.apple.DiskManagement. @@ -663,6 +675,17 @@ See remaining rules for examples. comment For burning media. + system.csfde.requestpassword.weak + + class + rule + comment + Used by CoreStorage Full Disk Encryption to request the user's password, allowing alternative authentication methods. + rule + + authenticate-admin-or-staff-extract-weak + + system.csfde.requestpassword class @@ -892,13 +915,13 @@ See remaining rules for examples. loginwindow:login builtin:login-begin builtin:reset-password,privileged + loginwindow:FDESupport,privileged builtin:forward-login,privileged builtin:auto-login,privileged builtin:authenticate,privileged PKINITMechanism:auth,privileged builtin:login-success loginwindow:success - loginwindow:FDESupport,privileged HomeDirMechanism:login,privileged HomeDirMechanism:status MCXMechanism:login @@ -906,7 +929,7 @@ See remaining rules for examples. loginwindow:done version - 6 + 7 system.login.fus @@ -1219,7 +1242,7 @@ See remaining rules for examples. class user comment - Used by AuthorizationExecuteWithPrivileges(...). + Used by AuthorizationExecuteWithPrivileges(...). AuthorizationExecuteWithPrivileges() is used by programs requesting to run a tool as root (e.g., some installers). group @@ -1286,22 +1309,20 @@ See remaining rules for examples. system.services.directory.configure - allow-root - - authenticate-user - class - user + rule + k-of-n + 1 + rule + + is-root + entitled + authenticate-admin-nonshared + comment For making Directory Services changes. - group - admin - session-owner - - shared - version - 2 + 3 system.services.networkextension.filtering @@ -1335,18 +1356,23 @@ See remaining rules for examples. system.services.systemconfiguration.network - allow-root - class - user + rule comment For making change to network configuration via System Configuration. + k-of-n + 1 + rule + + is-root + entitled + _mbsetupuser-nonshared + authenticate-admin-nonshared + entitled-group - group - admin version - 1 + 2 vpn-entitled-group @@ -1500,13 +1526,28 @@ See remaining rules for examples. authenticate-admin-30 + com.apple.installassistant.macos + + allow-root + + class + user + comment + Used by Install Assistant + group + admin + shared + + timeout + 300 + com.apple.security.syntheticinput class rule rule authenticate-session-owner - + com.apple.security.sudo class @@ -1518,7 +1559,7 @@ See remaining rules for examples. entitled authenticate-session-owner - + system.preferences.continuity class @@ -1541,6 +1582,23 @@ See remaining rules for examples. authenticate-session-owner-or-admin + com.apple.configurationprofiles.userenrollment.install + + class + user + comment + This right is used by UserManagement to ask user to acquire password from users. + session-owner + + extract-password + + password-only + + shared + + version + 1 + com.apple.safaridriver.allow comment @@ -1558,6 +1616,69 @@ See remaining rules for examples. version 1 + com.apple.app-sandbox.create-symlink + + comment + Authorize an app-sandboxed application to install a symlink into /usr/local/bin. + class + rule + rule + authenticate-admin-nonshared + shared + + timeout + 60 + + com.apple.app-sandbox.set-attributes + + comment + Authorize an app-sandboxed application to change permissions on a privileged file. + class + rule + rule + authenticate-admin-nonshared + shared + + timeout + 60 + + com.apple.app-sandbox.replace-file + + comment + Authorize an app-sandboxed application to save (overwrite) a file in a privileged location. + class + rule + rule + authenticate-admin-nonshared + shared + + timeout + 60 + + com.apple.applepay.reset + + class + user + comment + Used by nfcd. + group + admin + shared + + timeout + 300 + + com.apple.system-extensions.admin + + comment + Authorize a 3rd party application which wants to manipulate system extensions. + class + rule + rule + authenticate-admin-nonshared + shared + + rules @@ -1623,7 +1744,7 @@ See remaining rules for examples. version 1 - + authenticate-admin class @@ -1650,13 +1771,26 @@ See remaining rules for examples. version 1 + _mbsetupuser-nonshared + + class + user + authenticate-user + + comment + Succeeds if user is from _mbsetupuser group. + group + _mbsetupuser + timeout + 30 + authenticate-admin-30 class user comment - Like the default rule, but - credentials remain valid for only 30 seconds after they've + Like the default rule, but + credentials remain valid for only 30 seconds after they've been obtained. An acquired credential is shared by all clients. group @@ -1666,6 +1800,36 @@ See remaining rules for examples. timeout 30 + authenticate-admin-extract-weak + + class + user + comment + Authenticate as an administrator + allow password extraction. + extract-password + + group + admin + require-apple-signed + + timeout + 0 + + authenticate-staff-extract-weak + + class + user + comment + Authenticate as group staff + allow password to be extracted. + extract-password + + group + staff + require-apple-signed + + timeout + 0 + authenticate-admin-extract class @@ -1716,6 +1880,18 @@ See remaining rules for examples. localauthentication-context + authenticate-admin-or-staff-extract-weak + + class + rule + k-of-n + 1 + rule + + authenticate-admin-extract-weak + authenticate-staff-extract-weak + + authenticate-admin-or-staff-extract class @@ -1790,8 +1966,8 @@ See remaining rules for examples. class user comment - Default rule. - Credentials remain valid for 5 minutes after they've been obtained. + Default rule. + Credentials remain valid for 5 minutes after they've been obtained. An acquired credential is shared by all clients. group @@ -2131,7 +2307,7 @@ See remaining rules for examples. timeout 36000 - + diff --git a/OSX/authd/authtoken.c b/OSX/authd/authtoken.c index 995be9d4c..6b0568aab 100644 --- a/OSX/authd/authtoken.c +++ b/OSX/authd/authtoken.c @@ -169,7 +169,7 @@ _auth_token_create(const audit_info_s * auditInfo, bool operateAsLeastPrivileged auth->processes = CFSetCreateMutable(kCFAllocatorDefault, 0, NULL); auth->creator_bootstrap_port = MACH_PORT_NULL; - if (sandbox_check(auth->auditInfo.pid, "authorization-right-obtain", SANDBOX_CHECK_NO_REPORT) != 0) + if (sandbox_check_by_audit_token(auth->auditInfo.opaqueToken, "authorization-right-obtain", SANDBOX_CHECK_NO_REPORT) != 0) auth->sandboxed = true; else auth->sandboxed = false; @@ -228,54 +228,6 @@ auth_token_create(process_t proc, bool operateAsLeastPrivileged) return auth; } -auth_token_t -auth_token_create_with_audit_info(const audit_info_s* info, bool operateAsLeastPrivileged) -{ - OSStatus status = errSecSuccess; - SecCodeRef code_Ref = NULL; - CFURLRef code_url = NULL; - - auth_token_t auth = NULL; - require(info != NULL, done); - - auth = _auth_token_create(info, operateAsLeastPrivileged); - require(auth != NULL, done); - - auth->session = server_find_copy_session(info->asid, true); - if (auth->session == NULL) { - os_log_debug(AUTHD_LOG, "authtoken: failed to create session (PID %d)", auth->auditInfo.pid); - CFReleaseNull(auth); - goto done; - } - - CFMutableDictionaryRef codeDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFNumberRef codePid = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &auth->auditInfo.pid); - CFDictionarySetValue(codeDict, kSecGuestAttributePid, codePid); - status = SecCodeCopyGuestWithAttributes(NULL, codeDict, kSecCSDefaultFlags, &code_Ref); - CFReleaseSafe(codeDict); - CFReleaseSafe(codePid); - - if (status) { - os_log_debug(AUTHD_LOG, "authtoken: failed to create code ref (%d)", (int)status); - CFReleaseNull(auth); - goto done; - } - - if (SecCodeCopyPath(code_Ref, kSecCSDefaultFlags, &code_url) == errSecSuccess) { - auth->code_url = calloc(1u, PATH_MAX+1); - if (auth->code_url) { - CFURLGetFileSystemRepresentation(code_url, true, (UInt8*)auth->code_url, PATH_MAX); - } - } - - os_log_debug(AUTHD_LOG, "authtoken: created for %{public}s", auth->code_url); - -done: - CFReleaseSafe(code_Ref); - CFReleaseSafe(code_url); - return auth; -} - bool auth_token_get_sandboxed(auth_token_t auth) { @@ -394,6 +346,10 @@ auth_token_credentials_iterate(auth_token_t auth, credential_iterator_t iter) dispatch_sync(auth->dispatch_queue, ^{ CFIndex count = CFSetGetCount(auth->credentials); + if (count > 128) { // Variable Length Arrays; AuthD + // auth_token usually contains 0 or 1 credential + count = 128; + } CFTypeRef values[count]; CFSetGetValues(auth->credentials, values); for (CFIndex i = 0; i < count; i++) { @@ -416,27 +372,6 @@ auth_token_set_right(auth_token_t auth, credential_t right) }); } -bool -auth_token_rights_iterate(auth_token_t auth, credential_iterator_t iter) -{ - __block bool result = false; - - dispatch_sync(auth->dispatch_queue, ^{ - CFIndex count = CFSetGetCount(auth->authorized_rights); - CFTypeRef values[count]; - CFSetGetValues(auth->authorized_rights, values); - for (CFIndex i = 0; i < count; i++) { - credential_t right = (credential_t)values[i]; - result = iter(right); - if (!result) { - break; - } - } - }); - - return result; -} - CFTypeRef auth_token_copy_entitlement_value(auth_token_t auth, const char * entitlement) { diff --git a/OSX/authd/authtoken.h b/OSX/authd/authtoken.h index d4b9db589..3236e4da1 100644 --- a/OSX/authd/authtoken.h +++ b/OSX/authd/authtoken.h @@ -20,9 +20,6 @@ extern const CFDictionaryKeyCallBacks kAuthTokenKeyCallBacks; AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED auth_token_t auth_token_create(process_t,bool operateAsLeastPrivileged); - -AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED -auth_token_t auth_token_create_with_audit_info(const audit_info_s*,bool operateAsLeastPrivileged); AUTH_NONNULL_ALL bool auth_token_get_sandboxed(auth_token_t); @@ -75,9 +72,6 @@ bool auth_token_credentials_iterate(auth_token_t, credential_iterator_t iter); AUTH_NONNULL_ALL void auth_token_set_right(auth_token_t,credential_t); -AUTH_NONNULL_ALL -bool auth_token_rights_iterate(auth_token_t, credential_iterator_t iter); - AUTH_NONNULL_ALL CFTypeRef auth_token_copy_entitlement_value(auth_token_t, const char * entitlement); diff --git a/OSX/authd/authutilities.c b/OSX/authd/authutilities.c index d769467b3..60b6b2fdf 100644 --- a/OSX/authd/authutilities.c +++ b/OSX/authd/authutilities.c @@ -7,6 +7,8 @@ #include #include +AUTHD_DEFINE_LOG + xpc_object_t SerializeItemSet(const AuthorizationItemSet * itemSet) { @@ -67,6 +69,10 @@ DeserializeItemSet(const xpc_object_t data) // authd is holding on to multiple copies of my password in the clear if (xpc_dictionary_get_value(value, AUTH_XPC_ITEM_SENSITIVE_VALUE_LENGTH) != NULL) { size_t sensitiveLength = (size_t)xpc_dictionary_get_uint64(value, AUTH_XPC_ITEM_SENSITIVE_VALUE_LENGTH); + if (sensitiveLength > len) { + os_log_error(AUTHD_LOG, "Sensitive data len %zu is not valid", sensitiveLength); + goto done; + } dataCopy = malloc(sensitiveLength); require(dataCopy != NULL, done); memcpy(dataCopy, valueData, sensitiveLength); diff --git a/OSX/authd/ccaudit.c b/OSX/authd/ccaudit.c index 2c696ebb0..4d53229bf 100644 --- a/OSX/authd/ccaudit.c +++ b/OSX/authd/ccaudit.c @@ -11,7 +11,6 @@ AUTHD_DEFINE_LOG - struct _ccaudit_s { __AUTH_BASE_STRUCT_HEADER__; @@ -149,7 +148,6 @@ static bool _subject(ccaudit_t ccaudit) void ccaudit_log_authorization(ccaudit_t ccaudit, const char * right, OSStatus err) { - if (!_open(ccaudit)) { return; } @@ -177,7 +175,6 @@ void ccaudit_log_authorization(ccaudit_t ccaudit, const char * right, OSStatus e void ccaudit_log_success(ccaudit_t ccaudit, credential_t cred, const char * right) { - if (!_open(ccaudit)) { return; } @@ -198,7 +195,6 @@ void ccaudit_log_success(ccaudit_t ccaudit, credential_t cred, const char * righ void ccaudit_log_failure(ccaudit_t ccaudit, const char * credName, const char * right) { - if (!_open(ccaudit)) { return; } @@ -216,7 +212,6 @@ void ccaudit_log_failure(ccaudit_t ccaudit, const char * credName, const char * void ccaudit_log_mechanism(ccaudit_t ccaudit, const char * right, const char * mech, uint32_t status, const char * interrupted) { - if (!_open(ccaudit)) { return; } diff --git a/OSX/authd/com.apple.authd.sb b/OSX/authd/com.apple.authd.sb index c4f89fb56..5b94ca8a2 100644 --- a/OSX/authd/com.apple.authd.sb +++ b/OSX/authd/com.apple.authd.sb @@ -14,9 +14,12 @@ (literal "/private/var/db/mds/system/mds.lock") (subpath (param "TMP_DIR"))) +(allow network-outbound + (literal "/private/var/run/systemkeychaincheck.socket")) + (allow mach-lookup - (global-name "com.apple.CoreAuthentication.agent.libxpc") - (global-name "com.apple.CoreAuthentication.daemon.libxpc") + (global-name "com.apple.CoreAuthentication.agent") + (global-name "com.apple.CoreAuthentication.daemon") (global-name "com.apple.CoreServices.coreservicesd") (global-name "com.apple.PowerManagement.control") (global-name "com.apple.security.agent") @@ -25,11 +28,15 @@ (global-name "com.apple.SecurityServer") (global-name "com.apple.system.opendirectoryd.api") (global-name "com.apple.ocspd")) - + (allow ipc-posix-shm (ipc-posix-name "apple.shm.notification_center") (ipc-posix-name "com.apple.AppleDatabaseChanged")) -(allow mach-per-user-lookup) +(allow mach-priv-host-port) + +(allow user-preference-read + (preference-domain "kCFPreferencesAnyApplication") + (preference-domain "com.apple.authd")) (allow system-audit system-sched) diff --git a/OSX/authd/debugging.h b/OSX/authd/debugging.h index 0e0638b3a..b1dca37f5 100644 --- a/OSX/authd/debugging.h +++ b/OSX/authd/debugging.h @@ -24,7 +24,12 @@ return log; \ #define CFReleaseNull(CF) { CFTypeRef _cf = (CF); \ if (_cf) { (CF) = NULL; CFRelease(_cf); } } #define CFRetainSafe(CF) { CFTypeRef _cf = (CF); if (_cf) CFRetain(_cf); } - +#define CFAssignRetained(VAR,CF) ({ \ +__typeof__(VAR) *const _pvar = &(VAR); \ +__typeof__(CF) _cf = (CF); \ +(*_pvar) = *_pvar ? (CFRelease(*_pvar), _cf) : _cf; \ +}) + #define xpc_release_safe(obj) if (obj) { xpc_release(obj); obj = NULL; } #define free_safe(obj) if (obj) { free(obj); obj = NULL; } diff --git a/OSX/authd/engine.c b/OSX/authd/engine.c index 61bc15eef..1e4584db4 100644 --- a/OSX/authd/engine.c +++ b/OSX/authd/engine.c @@ -21,11 +21,13 @@ int checkpw_internal( const struct passwd *pw, const char* password ); #include #include +#include #include #include #include #include #include +#include AUTHD_DEFINE_LOG @@ -38,6 +40,8 @@ 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 uint64_t global_engine_count; + enum { kEngineHintsFlagTemporary = (1 << 30) }; @@ -81,6 +85,8 @@ struct _engine_s { rule_t authenticateRule; bool dismissed; + + uint64_t engine_index; }; static void @@ -100,6 +106,7 @@ _engine_finalizer(CFTypeRef value) CFReleaseNull(engine->credentials); CFReleaseNull(engine->effectiveCredentials); CFReleaseNull(engine->authenticateRule); + CFReleaseNull(engine->la_context); } AUTH_TYPE_INSTANCE(engine, @@ -175,6 +182,7 @@ engine_create(connection_t conn, auth_token_t auth) engine->mechanism_agents = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + engine->engine_index = global_engine_count++; done: return engine; } @@ -263,7 +271,7 @@ _set_localization_hints(authdb_connection_t dbconn, auth_items_t hints, rule_t r static void _set_session_hints(engine_t engine, rule_t rule) { - os_log_debug(AUTHD_LOG, "engine: ** prepare agent hints for rule %{public}s", rule_get_name(rule)); + os_log_debug(AUTHD_LOG, "engine %lld: ** prepare agent hints for rule %{public}s", engine->engine_index, rule_get_name(rule)); if (_evaluate_user_credential_for_rule(engine, engine->sessionCredential, rule, true, true, NULL) == errAuthorizationSuccess) { const char * tmp = credential_get_name(engine->sessionCredential); if (tmp != NULL) { @@ -289,7 +297,7 @@ _evaluate_credential_for_rule(engine_t engine, credential_t cred, rule_t rule, b if (credential_is_right(cred) && credential_get_valid(cred) && _compare_string(engine->currentRightName, credential_get_name(cred))) { if (!ignoreShared) { if (!rule_get_shared(rule) && credential_get_shared(cred)) { - os_log_error(AUTHD_LOG, "engine: - shared right %{public}s (does NOT satisfy rule)", credential_get_name(cred)); + os_log_error(AUTHD_LOG, "Shared right %{public}s (does NOT satisfy rule) (engine %lld)", credential_get_name(cred), engine->engine_index); if (reason) { *reason = unknownReason; } return errAuthorizationDenied; } @@ -309,47 +317,47 @@ static OSStatus _evaluate_user_credential_for_rule(engine_t engine, credential_t cred, rule_t rule, bool ignoreShared, bool sessionOwner, enum Reason * reason) { const char * cred_label = sessionOwner ? "session owner" : "credential"; - os_log(AUTHD_LOG, "engine: - validating %{public}s%{public}s %{public}s (%i) for %{public}s", credential_get_shared(cred) ? "shared " : "", + os_log(AUTHD_LOG, "Validating %{public}s%{public}s %{public}s (%i) for %{public}s (engine %lld)", credential_get_shared(cred) ? "shared " : "", cred_label, credential_get_name(cred), credential_get_uid(cred), - rule_get_name(rule)); + rule_get_name(rule), + engine->engine_index); if (rule_get_class(rule) != RC_USER) { - os_log(AUTHD_LOG, "engine: - invalid rule class %i (denied)", rule_get_class(rule)); + os_log(AUTHD_LOG, "Invalid rule class %i (engine %lld)", rule_get_class(rule), engine->engine_index); return errAuthorizationDenied; } if (credential_get_valid(cred) != true) { - os_log(AUTHD_LOG, "engine: - %{public}s %i invalid (does NOT satisfy rule)", cred_label, credential_get_uid(cred)); + 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 (engine->now - credential_get_creation_time(cred) > rule_get_timeout(rule)) { - os_log(AUTHD_LOG, "engine: - %{public}s %i expired '%f > %lli' (does NOT satisfy rule)", cred_label, credential_get_uid(cred), - (engine->now - credential_get_creation_time(cred)), rule_get_timeout(rule)); + os_log(AUTHD_LOG, "%{public}s %i expired '%f > %lli' (does NOT satisfy rule) (engine %lld)", cred_label, credential_get_uid(cred), + (engine->now - credential_get_creation_time(cred)), rule_get_timeout(rule), engine->engine_index); if (reason) { *reason = unknownReason; } return errAuthorizationDenied; } - if (!ignoreShared) { if (!rule_get_shared(rule) && credential_get_shared(cred)) { - os_log(AUTHD_LOG, "engine: - shared %{public}s %i (does NOT satisfy rule)", cred_label, credential_get_uid(cred)); + os_log(AUTHD_LOG, "Shared %{public}s %i (does NOT satisfy rule) (engine %lld)", cred_label, credential_get_uid(cred), engine->engine_index); if (reason) { *reason = unknownReason; } return errAuthorizationDenied; } } if (credential_get_uid(cred) == 0) { - os_log(AUTHD_LOG, "engine: - %{public}s %i has uid 0 (does satisfy rule)", cred_label, credential_get_uid(cred)); + os_log(AUTHD_LOG, "%{public}s %i has uid 0 (does satisfy rule) (engine %lld)", cred_label, credential_get_uid(cred), engine->engine_index); return errAuthorizationSuccess; } if (rule_get_session_owner(rule)) { if (credential_get_uid(cred) == session_get_uid(auth_token_get_session(engine->auth))) { - os_log(AUTHD_LOG, "engine: - %{public}s %i is session owner (does satisfy rule)", cred_label, credential_get_uid(cred)); + os_log(AUTHD_LOG, "%{public}s %i is session owner (does satisfy rule) (engine %lld)", cred_label, credential_get_uid(cred), engine->engine_index); return errAuthorizationSuccess; } } @@ -369,7 +377,7 @@ _evaluate_user_credential_for_rule(engine_t engine, credential_t cred, rule_t ru } if (credential_check_membership(cred, rule_get_group(rule))) { - os_log(AUTHD_LOG, "engine: - %{public}s %i is member of group %{public}s (does satisfy rule)", cred_label, credential_get_uid(cred), rule_get_group(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 { if (reason) { *reason = userNotInGroup; } @@ -379,7 +387,7 @@ _evaluate_user_credential_for_rule(engine_t engine, credential_t cred, rule_t ru if (reason) { *reason = unacceptableUser; } } - os_log(AUTHD_LOG, "engine: - %{public}s %i (does NOT satisfy rule), reason %d", cred_label, credential_get_uid(cred), reason ? *reason : -1); + os_log(AUTHD_LOG, "%{public}s %i (does NOT satisfy rule), reason %d (engine %lld)", cred_label, credential_get_uid(cred), reason ? *reason : -1, engine->engine_index); return errAuthorizationDenied; } @@ -415,19 +423,25 @@ _evaluate_builtin_mechanism(engine_t engine, mechanism_t mech) return result; } - static bool -_extract_password_from_la(engine_t engine, CFTypeRef la_context) +_extract_password_from_la(engine_t engine) { bool retval = false; + + if (!engine->la_context) { + return retval; + } + // try to retrieve secret - CFDataRef passdata = LACopyCredential(la_context, kLACredentialTypeExtractablePasscode, NULL); + CFDataRef passdata = LACopyCredential(engine->la_context, kLACredentialTypeExtractablePasscode, NULL); if (passdata) { if (CFDataGetBytePtr(passdata)) { + os_log_debug(AUTHD_LOG, "engine %lld: LA credentials retrieved", engine->engine_index); auth_items_set_data(engine->context, kAuthorizationEnvironmentPassword, CFDataGetBytePtr(passdata), CFDataGetLength(passdata)); } else { - char nulChar = 0; - auth_items_set_data(engine->context, kAuthorizationEnvironmentPassword, &nulChar, 1); + const char *empty_pass = "\0"; // authd code is unable to process empty strings so passing empty string as terminator only + os_log_debug(AUTHD_LOG, "engine %lld: LA credentials empty", engine->engine_index); + auth_items_set_data(engine->context, kAuthorizationEnvironmentPassword, empty_pass, 1); } CFRelease(passdata); } @@ -449,55 +463,72 @@ _evaluate_mechanisms(engine_t engine, CFArrayRef mechanisms) CFDictionaryRef la_result = NULL; CFIndex count = CFArrayGetCount(mechanisms); - for (CFIndex i = 0; i < count; i++) { + bool sheet_evaluation = false; + if (engine->la_context) { + int tmp = kLAOptionNotInteractive; + CFNumberRef key = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &tmp); + tmp = 1; + CFNumberRef value = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &tmp); + if (key && value) { + CFMutableDictionaryRef options = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(options, key, value); + la_result = LACopyResultOfPolicyEvaluation(engine->la_context, kLAPolicyDeviceOwnerAuthentication, options, NULL); + os_log_debug(AUTHD_LOG, "engine %lld: Retrieve LA evaluate result: %d", engine->engine_index, la_result != NULL); + CFReleaseSafe(options); + } + CFReleaseSafe(key); + CFReleaseSafe(value); + } + + for (CFIndex i = 0; i < count; i++) { mechanism_t mech = (mechanism_t)CFArrayGetValueAtIndex(mechanisms, i); if (mechanism_get_type(mech)) { - os_log_debug(AUTHD_LOG, "engine: running builtin mechanism %{public}s (%li of %li)", mechanism_get_string(mech), i+1, count); + os_log_debug(AUTHD_LOG, "engine %lld: running builtin mechanism %{public}s (%li of %li)", engine->engine_index, mechanism_get_string(mech), i+1, count); result = _evaluate_builtin_mechanism(engine, mech); } else { - bool sheet_variant_used = false; + bool shoud_run_agent = true; // evaluate comes from sheet -> we may not want to run standard SecurityAgent or authhost if (engine->la_context) { - - if (!la_result) { - int tmp = kLAOptionNotInteractive; - CFNumberRef key = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &tmp); - tmp = 1; - CFNumberRef value = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &tmp); - if (key && value) { - CFMutableDictionaryRef options = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFDictionarySetValue(options, key, value); - la_result = LACopyResultOfPolicyEvaluation(engine->la_context, kLAPolicyDeviceOwnerAuthentication, options, NULL); - CFReleaseSafe(options); - } - CFReleaseSafe(key); - CFReleaseSafe(value); - } - // sheet variant in progress if (strcmp(mechanism_get_string(mech), "builtin:authenticate") == 0) { - // instead of running SecurityAgent, get uid from the authorization - os_log(AUTHD_LOG, "engine: running builtin sheet authenticate"); - if (!la_result) { - result = kAuthorizationResultDeny; // no la_result => was evaluate did not pass + // set the UID the same way as SecurityAgent would + if (auth_items_exist(engine->context, "sheet-uid")) { + os_log_debug(AUTHD_LOG, "engine %lld: setting sheet UID %d to the context", engine->engine_index, auth_items_get_uint(engine->context, "sheet-uid")); + auth_items_set_uint(engine->context, "uid", auth_items_get_uint(engine->context, "sheet-uid")); } - sheet_variant_used = true; - } else if (strcmp(mechanism_get_string(mech), "builtin:authenticate,privileged") == 0) { - os_log(AUTHD_LOG, "engine: running builtin sheet privileged authenticate"); - if (!la_result) { - result = kAuthorizationResultDeny; // no la_result => was evaluate did not pass + + // find out if sheet just provided credentials or did real authentication + // if password is provided or PAM service name exists, it means authd has to evaluate credentials + // otherwise we need to check la_result + if (auth_items_exist(engine->context, AGENT_CONTEXT_AP_PAM_SERVICE_NAME) || auth_items_exist(engine->context, kAuthorizationEnvironmentPassword)) { + // do not try to get credentials as it has been already passed by sheet + os_log_debug(AUTHD_LOG, "engine %lld: ignoring builtin sheet authenticate", engine->engine_index); } else { - if (!_extract_password_from_la(engine, engine->la_context)) { - os_log_debug(AUTHD_LOG, "engine: cannot extract cred"); + // sheet itself did the authenticate the user + os_log_debug(AUTHD_LOG, "engine %lld: running builtin sheet authenticate", engine->engine_index); + sheet_evaluation = true; + if (!la_result || TKGetSmartcardSetting(kTKEnforceSmartcard) != 0) { + result = kAuthorizationResultDeny; // no la_result => evaluate did not pass for sheet method. Enforced smartcard => no way to use sheet based evaluation } } - sheet_variant_used = true; + shoud_run_agent = false; // SecurityAgent should not be run for builtin:authenticate + } else if (strcmp(mechanism_get_string(mech), "builtin:authenticate,privileged") == 0) { + if (sheet_evaluation) { + os_log_debug(AUTHD_LOG, "engine %lld: running builtin sheet privileged authenticate", engine->engine_index); + shoud_run_agent = false; + if (!la_result || TKGetSmartcardSetting(kTKEnforceSmartcard) != 0) { // should not get here under normal circumstances but we need to handle this case as well + result = kAuthorizationResultDeny; // no la_result => evaluate did not pass. Enforced smartcard => no way to use sheet based evaluation + } + } else { + // should_run_agent has to be set to true because we want authorizationhost to verify the credentials + os_log_debug(AUTHD_LOG, "engine %lld: running sheet privileged authenticate", engine->engine_index); + } } } - if (!sheet_variant_used) { + if (shoud_run_agent) { agent_t agent = _get_agent(engine, mech, true, i == 0); - require_action(agent != NULL, done, result = kAuthorizationResultUndefined; os_log_error(AUTHD_LOG, "engine: error creating mechanism agent")); + require_action(agent != NULL, done, result = kAuthorizationResultUndefined; os_log_error(AUTHD_LOG, "Error creating mechanism agent (engine %lld)", engine->engine_index)); // check if any agent has been interrupted (it necessary if interrupt will come during creation) CFIndex j; @@ -509,7 +540,7 @@ _evaluate_mechanisms(engine_t engine, CFArrayRef mechanisms) } } if (j < i) { - os_log(AUTHD_LOG, "engine: mechanisms interrupted"); + os_log(AUTHD_LOG, "engine %lld: mechanisms interrupted", engine->engine_index); char * buf = NULL; asprintf(&buf, "evaluation interrupted by %s; restarting evaluation there", mechanism_get_string(agent_get_mechanism(agent1))); ccaudit_log_mechanism(ccaudit, engine->currentRightName, mechanism_get_string(agent_get_mechanism(agent1)), kAuthorizationResultAllow, buf); @@ -527,7 +558,7 @@ _evaluate_mechanisms(engine_t engine, CFArrayRef mechanisms) continue; } - os_log(AUTHD_LOG, "engine: running mechanism %{public}s (%li of %li)", mechanism_get_string(agent_get_mechanism(agent)), i+1, count); + os_log(AUTHD_LOG, "engine %lld: running mechanism %{public}s (%li of %li)", engine->engine_index, mechanism_get_string(agent_get_mechanism(agent)), i+1, count); result = agent_run(agent, hints, context, engine->immutable_hints); @@ -559,7 +590,7 @@ _evaluate_mechanisms(engine_t engine, CFArrayRef mechanisms) } if (interrupted) { - os_log(AUTHD_LOG, "engine: mechanisms interrupted"); + os_log_info(AUTHD_LOG, "Mechanisms interrupted (engine %lld)", engine->engine_index); enum Reason reason = worldChanged; auth_items_set_data(hints, AGENT_HINT_RETRY_REASON, &reason, sizeof(reason)); result = kAuthorizationResultAllow; @@ -610,7 +641,7 @@ _evaluate_mechanisms(engine_t engine, CFArrayRef mechanisms) return errAuthorizationInternal; default: { - os_log_error(AUTHD_LOG, "engine: unexpected error result"); + os_log_error(AUTHD_LOG, "Evaluate - unexpected result %llu (engine %lld)", result, engine->engine_index); return errAuthorizationInternal; } } @@ -621,7 +652,7 @@ _evaluate_authentication(engine_t engine, rule_t rule) { OSStatus status = errAuthorizationDenied; ccaudit_t ccaudit = ccaudit_create(engine->proc, engine->auth, AUE_ssauthint); - os_log_debug(AUTHD_LOG, "engine: evaluate authentication"); + os_log_debug(AUTHD_LOG, "engine %lld: evaluate authentication", engine->engine_index); _set_rule_hints(engine->hints, rule); _set_session_hints(engine, rule); @@ -629,16 +660,22 @@ _evaluate_authentication(engine_t engine, rule_t rule) if (!(CFArrayGetCount(mechanisms) > 0)) { mechanisms = rule_get_mechanisms(engine->authenticateRule); } - require_action(CFArrayGetCount(mechanisms) > 0, done, os_log_debug(AUTHD_LOG, "engine: error no mechanisms found")); + require_action(CFArrayGetCount(mechanisms) > 0, done, os_log_debug(AUTHD_LOG, "engine %lld: error - no mechanisms found", engine->engine_index)); int64_t ruleTries = rule_get_tries(rule); + + if (engine->la_context) { + ruleTries = 1; + os_log_debug(AUTHD_LOG, "engine %lld: sheet authentication in progress, one try is enough", engine->engine_index); + } + for (engine->tries = 0; engine->tries < ruleTries; engine->tries++) { auth_items_set_data(engine->hints, AGENT_HINT_RETRY_REASON, &engine->reason, sizeof(engine->reason)); auth_items_set_int(engine->hints, AGENT_HINT_TRIES, engine->tries); status = _evaluate_mechanisms(engine, mechanisms); - os_log_debug(AUTHD_LOG, "engine: evaluate mechanisms result %d", (int)status); + os_log_debug(AUTHD_LOG, "engine %lld: evaluate mechanisms result %d", engine->engine_index, (int)status); // successfully ran mechanisms to obtain credential if (status == errAuthorizationSuccess) { @@ -649,7 +686,7 @@ _evaluate_authentication(engine_t engine, rule_t rule) if (auth_items_exist(engine->context, "uid")) { newCred = credential_create(auth_items_get_uint(engine->context, "uid")); } else { - os_log_error(AUTHD_LOG, "engine: mechanism failed to return a valid uid"); + os_log_info(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); @@ -679,29 +716,24 @@ _evaluate_authentication(engine_t engine, rule_t rule) session_t session = auth_token_get_session(engine->auth); if (credential_get_uid(newCred) == session_get_uid(session)) { - os_log_debug(AUTHD_LOG, "engine: authenticated as the session owner"); + os_log_debug(AUTHD_LOG, "engine %lld: authenticated as the session owner", engine->engine_index); session_set_attributes(auth_token_get_session(engine->auth), AU_SESSION_FLAG_HAS_AUTHENTICATED); } break; } else { - os_log_error(AUTHD_LOG, "engine: user credential for rule failed (%d)", (int)status); + os_log_error(AUTHD_LOG, "User credential for rule failed (%d) (engine %lld)", (int)status, engine->engine_index); } CFReleaseSafe(newCred); } } else if (status == errAuthorizationCanceled || status == errAuthorizationInternal) { - os_log_error(AUTHD_LOG, "engine: evaluate cancelled or failed %d", (int)status); + os_log_error(AUTHD_LOG, "Evaluate cancelled or failed %d (engine %lld)", (int)status, engine->engine_index); break; } else if (status == errAuthorizationDenied) { - os_log_error(AUTHD_LOG, "engine: evaluate denied"); + os_log_error(AUTHD_LOG, "Evaluate denied (engine %lld)", engine->engine_index); engine->reason = invalidPassphrase; - if (engine->la_context) { - // for sheet authorizations do not retry with sheet as there is no new sheet UI - CFReleaseNull(engine->la_context); - auth_items_remove(engine->context, AGENT_CONTEXT_UID); - } } } @@ -709,8 +741,6 @@ _evaluate_authentication(engine_t engine, rule_t rule) engine->reason = tooManyTries; auth_items_set_data(engine->hints, AGENT_HINT_RETRY_REASON, &engine->reason, sizeof(engine->reason)); auth_items_set_int(engine->hints, AGENT_HINT_TRIES, engine->tries); - // TODO: determine why evaluate_mechanism is run once again and possibly remove this call - _evaluate_mechanisms(engine, mechanisms); ccaudit_log(ccaudit, engine->currentRightName, NULL, 1113); } @@ -729,7 +759,7 @@ _check_entitlement_for_rule(engine_t engine, rule_t rule) if (rule_check_flags(rule, RuleFlagEntitledAndGroup)) { if (auth_token_has_entitlement_for_right(engine->auth, engine->currentRightName)) { if (credential_check_membership(auth_token_get_credential(engine->auth), rule_get_group(rule))) { - os_log_debug(AUTHD_LOG, "engine: creator of authorization has entitlement for right %{public}s and is member of group '%{public}s'", engine->currentRightName, rule_get_group(rule)); + os_log_info(AUTHD_LOG, "Creator of authorization has entitlement for right %{public}s and is member of group '%{public}s' (engine %lld)", engine->currentRightName, rule_get_group(rule), engine->engine_index); entitled = true; goto done; } @@ -741,7 +771,7 @@ _check_entitlement_for_rule(engine_t engine, rule_t rule) value = auth_token_copy_entitlement_value(engine->auth, "com.apple.networking.vpn.configuration"); if (value) { if (credential_check_membership(auth_token_get_credential(engine->auth), rule_get_group(rule))) { - os_log_debug(AUTHD_LOG, "engine: creator of authorization has VPN entitlement and is member of group '%{public}s'", rule_get_group(rule)); + os_log_info(AUTHD_LOG, "Creator of authorization has VPN entitlement and is member of group '%{public}s' (engine %lld)", rule_get_group(rule), engine->engine_index); entitled = true; goto done; } @@ -763,7 +793,7 @@ _evaluate_class_user(engine_t engine, rule_t rule) } if (rule_get_allow_root(rule) && auth_token_get_uid(engine->auth) == 0) { - os_log_debug(AUTHD_LOG, "engine: creator of authorization has uid == 0 granting right %{public}s", engine->currentRightName); + os_log_info(AUTHD_LOG, "Creator of authorization has uid == 0, granting right %{public}s (engine %lld)", engine->currentRightName, engine->engine_index); return errAuthorizationSuccess; } @@ -820,7 +850,7 @@ _evaluate_class_user(engine_t engine, rule_t rule) // Finally - we didn't find a credential. Obtain a new credential if our flags let us do so. if (!(engine->flags & kAuthorizationFlagExtendRights)) { - os_log_error(AUTHD_LOG, "engine: authorization denied (kAuthorizationFlagExtendRights not set)"); + os_log_error(AUTHD_LOG, "Fatal: authorization denied (kAuthorizationFlagExtendRights not set) (engine %lld)", engine->engine_index); return errAuthorizationDenied; } @@ -831,17 +861,17 @@ _evaluate_class_user(engine_t engine, rule_t rule) if (!engine->preauthorizing) { if (!(engine->flags & kAuthorizationFlagInteractionAllowed)) { - os_log_error(AUTHD_LOG, "engine: Interaction not allowed (kAuthorizationFlagInteractionAllowed not set)"); + 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, "engine: Interaction not allowed (session has no ui 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()) { - os_log_error(AUTHD_LOG, "engine: authorization denied (DW)"); + if (server_in_dark_wake() && !(engine->flags & kAuthorizationFlagIgnoreDarkWake)) { + os_log_error(AUTHD_LOG, "Fatal: authorization denied (DW) (engine %lld)", engine->engine_index); return errAuthorizationDenied; } } @@ -858,7 +888,7 @@ _evaluate_class_rule(engine_t engine, rule_t rule, bool *save_pwd) uint32_t total = (uint32_t)rule_get_delegates_count(rule); __block uint32_t success_count = 0; __block uint32_t count = 0; - os_log_debug(AUTHD_LOG, "engine: ** rule %{public}s has %zi delegates kofn = %lli",rule_get_name(rule), total, kofn); + os_log_debug(AUTHD_LOG, "engine %lld: ** rule %{public}s has %u delegates kofn = %lli", engine->engine_index, rule_get_name(rule), total, kofn); rule_delegates_iterator(rule, ^bool(rule_t delegate) { count++; @@ -867,7 +897,7 @@ _evaluate_class_rule(engine_t engine, rule_t rule, bool *save_pwd) return false; } - os_log_debug(AUTHD_LOG, "engine: * evaluate rule %{public}s (%i)", rule_get_name(delegate), count); + os_log_debug(AUTHD_LOG, "engine %lld: * evaluate rule %{public}s (%i)", engine->engine_index, rule_get_name(delegate), count); status = _evaluate_rule(engine, delegate, save_pwd); // if status is cancel/internal error abort @@ -878,7 +908,7 @@ _evaluate_class_rule(engine_t engine, rule_t rule, bool *save_pwd) if (kofn != 0) { // if remaining is less than required abort if ((total - count) < (kofn - success_count)) { - os_log_debug(AUTHD_LOG, "engine: rule evaluation remaining: %i, required: %lli", (total - count), (kofn - success_count)); + os_log_debug(AUTHD_LOG, "engine %lld: rule evaluation remaining: %i, required: %lli", engine->engine_index, (total - count), (kofn - success_count)); return false; } return true; @@ -896,7 +926,7 @@ _evaluate_class_rule(engine_t engine, rule_t rule, bool *save_pwd) static bool _preevaluate_class_rule(engine_t engine, rule_t rule) { - os_log_debug(AUTHD_LOG, "engine: _preevaluate_class_rule %{public}s", rule_get_name(rule)); + 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) { @@ -916,15 +946,15 @@ _evaluate_class_mechanism(engine_t engine, rule_t rule) OSStatus status = errAuthorizationDenied; CFArrayRef mechanisms = NULL; - require_action(rule_get_mechanisms_count(rule) > 0, done, status = errAuthorizationSuccess; os_log_error(AUTHD_LOG, "engine: no mechanisms specified")); + require_action(rule_get_mechanisms_count(rule) > 0, done, status = errAuthorizationSuccess; os_log_error(AUTHD_LOG, "Fatal: no mechanisms specified (engine %lld)", engine->engine_index)); mechanisms = rule_get_mechanisms(rule); - if (server_in_dark_wake()) { + if (server_in_dark_wake() && !(engine->flags & kAuthorizationFlagIgnoreDarkWake)) { CFIndex count = CFArrayGetCount(mechanisms); for (CFIndex i = 0; i < count; i++) { if (!mechanism_is_privileged((mechanism_t)CFArrayGetValueAtIndex(mechanisms, i))) { - os_log_error(AUTHD_LOG, "engine: authorization denied (in DW)"); + os_log_error(AUTHD_LOG, "Fatal: authorization denied (in DW) (engine %lld)", engine->engine_index); goto done; } } @@ -937,14 +967,14 @@ _evaluate_class_mechanism(engine_t engine, rule_t rule) auth_items_set_int(engine->hints, AGENT_HINT_TRIES, engine->tries); status = _evaluate_mechanisms(engine, mechanisms); - os_log_debug(AUTHD_LOG, "engine: evaluate mechanisms result %d", (int)status); + os_log_debug(AUTHD_LOG, "engine %lld: evaluate mechanisms result %d", engine->engine_index, (int)status); if (status == errAuthorizationSuccess) { credential_t newCred = NULL; if (auth_items_exist(engine->context, "uid")) { newCred = credential_create(auth_items_get_uint(engine->context, "uid")); } else { - os_log(AUTHD_LOG, "engine: mechanism did not return a uid"); + os_log_info(AUTHD_LOG, "Mechanism did not return a uid (engine %lld)", engine->engine_index); } if (newCred) { @@ -973,28 +1003,12 @@ _evaluate_class_mechanism(engine_t engine, rule_t rule) return status; } -// TODO: Remove when all clients have adopted entitlement -static bool -enforced_entitlement(void) -{ - bool enforced_enabled = false; - //sudo defaults write /Library/Preferences/com.apple.authd enforceEntitlement -bool true - CFTypeRef enforce = (CFNumberRef)CFPreferencesCopyValue(CFSTR("enforceEntitlement"), CFSTR(SECURITY_AUTH_NAME), kCFPreferencesAnyUser, kCFPreferencesCurrentHost); - if (enforce && CFGetTypeID(enforce) == CFBooleanGetTypeID()) { - enforced_enabled = CFBooleanGetValue((CFBooleanRef)enforce); - os_log_debug(AUTHD_LOG, "enforceEntitlement for extract password: %{public}s", enforced_enabled ? "enabled" : "disabled"); - } - CFReleaseSafe(enforce); - - return enforced_enabled; -} - static OSStatus _evaluate_rule(engine_t engine, rule_t rule, bool *save_pwd) { if (rule_check_flags(rule, RuleFlagEntitled)) { if (auth_token_has_entitlement_for_right(engine->auth, engine->currentRightName)) { - os_log_debug(AUTHD_LOG, "engine: rule allow, creator of authorization has entitlement for right %{public}s", engine->currentRightName); + os_log_debug(AUTHD_LOG, "engine %lld: rule allow, creator of authorization has entitlement for right %{public}s", engine->engine_index, engine->currentRightName); return errAuthorizationSuccess; } } @@ -1003,37 +1017,22 @@ _evaluate_rule(engine_t engine, rule_t rule, bool *save_pwd) if (engine->la_context || rule_check_flags(rule, RuleFlagRequireAppleSigned)) { if (!auth_token_apple_signed(engine->auth)) { #ifdef NDEBUG - os_log_error(AUTHD_LOG, "engine: rule deny, creator of authorization is not signed by Apple"); + os_log_error(AUTHD_LOG, "Rule deny, creator of authorization is not signed by Apple (engine %lld)", engine->engine_index); return errAuthorizationDenied; #else - os_log_debug(AUTHD_LOG, "engine: in release mode, this rule would be denied because creator of authorization is not signed by Apple"); + os_log_debug(AUTHD_LOG, "engine %lld: in release mode, this rule would be denied because creator of authorization is not signed by Apple", engine->engine_index); #endif } } - - if (rule_get_extract_password(rule)) { - // check if process is entitled to extract password - CFTypeRef extract_password_entitlement = auth_token_copy_entitlement_value(engine->auth, "com.apple.authorization.extract-password"); - if (extract_password_entitlement && (CFGetTypeID(extract_password_entitlement) == CFBooleanGetTypeID()) && extract_password_entitlement == kCFBooleanTrue) { - *save_pwd = TRUE; - os_log_debug(AUTHD_LOG, "engine: authorization allowed to extract password"); - } else { - os_log_debug(AUTHD_LOG, "engine: authorization NOT allowed to extract password"); - } - CFReleaseSafe(extract_password_entitlement); - } - - // TODO: Remove when all clients have adopted entitlement - if (!enforced_entitlement()) { - *save_pwd |= rule_get_extract_password(rule); - } + + *save_pwd |= rule_get_extract_password(rule); switch (rule_get_class(rule)) { case RC_ALLOW: - os_log(AUTHD_LOG, "engine: rule set to allow"); + os_log(AUTHD_LOG, "Rule set to allow (engine %lld)", engine->engine_index); return errAuthorizationSuccess; case RC_DENY: - os_log(AUTHD_LOG, "engine: rule set to deny"); + os_log(AUTHD_LOG, "Rule set to deny (engine %lld)", engine->engine_index); return errAuthorizationDenied; case RC_USER: return _evaluate_class_user(engine, rule); @@ -1042,7 +1041,7 @@ _evaluate_rule(engine_t engine, rule_t rule, bool *save_pwd) case RC_MECHANISM: return _evaluate_class_mechanism(engine, rule); default: - os_log_error(AUTHD_LOG, "engine: invalid class for rule or rule not found: %{public}s", rule_get_name(rule)); + os_log_error(AUTHD_LOG, "Invalid class for rule or rule not found: %{public}s (engine %lld)", rule_get_name(rule), engine->engine_index); return errAuthorizationInternal; } } @@ -1051,7 +1050,7 @@ _evaluate_rule(engine_t engine, rule_t rule, bool *save_pwd) static bool _preevaluate_rule(engine_t engine, rule_t rule) { - os_log_debug(AUTHD_LOG, "engine: _preevaluate_rule %{public}s", rule_get_name(rule)); + os_log_debug(AUTHD_LOG, "engine %lld: _preevaluate_rule %{public}s", engine->engine_index, rule_get_name(rule)); switch (rule_get_class(rule)) { case RC_ALLOW: @@ -1116,7 +1115,7 @@ _find_rule(engine_t engine, authdb_connection_t dbconn, const char * string) r = rule_create_with_string("", dbconn); if (rule_get_id(r) == 0) { CFReleaseNull(r); - os_log_error(AUTHD_LOG, "engine: default rule lookup error (missing), using builtin defaults"); + os_log_error(AUTHD_LOG, "Default rule lookup error (missing), using builtin defaults (engine %lld)", engine->engine_index); r = rule_create_default(); } } @@ -1128,28 +1127,28 @@ static void _parse_environment(engine_t engine, auth_items_t environment) require(environment != NULL, done); #if DEBUG - os_log_debug(AUTHD_LOG, "engine: Dumping Environment: %@", environment); + os_log_debug(AUTHD_LOG, "engine %lld: Dumping Environment: %@", engine->engine_index, environment); #endif // Check if a credential was passed into the environment and we were asked to extend the rights - if (engine->flags & kAuthorizationFlagExtendRights) { + if (engine->flags & kAuthorizationFlagExtendRights && !(engine->flags & kAuthorizationFlagSheet)) { const char * user = auth_items_get_string(environment, kAuthorizationEnvironmentUsername); const char * pass = auth_items_get_string(environment, kAuthorizationEnvironmentPassword); const bool password_was_used = auth_items_get_string(environment, AGENT_CONTEXT_AP_PAM_SERVICE_NAME) == nil; // AGENT_CONTEXT_AP_PAM_SERVICE_NAME in the context means alternative PAM was used require(password_was_used == true, done); bool shared = auth_items_exist(environment, kAuthorizationEnvironmentShared); - require_action(user != NULL, done, os_log_debug(AUTHD_LOG, "engine: user not used password")); + require_action(user != NULL, done, os_log_debug(AUTHD_LOG, "engine %lld: user not used password", engine->engine_index)); struct passwd *pw = getpwnam(user); - require_action(pw != NULL, done, os_log_error(AUTHD_LOG, "engine: user not found %{public}s", user)); + require_action(pw != NULL, done, os_log_error(AUTHD_LOG, "User not found %{public}s (engine %lld)", user, engine->engine_index)); int checkpw_status = checkpw_internal(pw, pass ? pass : ""); - require_action(checkpw_status == CHECKPW_SUCCESS, done, os_log_error(AUTHD_LOG, "engine: checkpw() returned %d; failed to authenticate user %{public}s (uid %u).", checkpw_status, pw->pw_name, pw->pw_uid)); + require_action(checkpw_status == CHECKPW_SUCCESS, done, os_log_error(AUTHD_LOG, "engine %lld: checkpw() returned %d; failed to authenticate user %{public}s (uid %u).", engine->engine_index, checkpw_status, pw->pw_name, pw->pw_uid)); credential_t cred = credential_create(pw->pw_uid); if (credential_get_valid(cred)) { - os_log(AUTHD_LOG, "engine: checkpw() succeeded, creating credential for user %{public}s", user); + os_log_info(AUTHD_LOG, "checkpw() succeeded, creating credential for user %{public}s (engine %lld)", user, engine->engine_index); _engine_set_credential(engine, cred, shared); auth_items_set_string(engine->context, kAuthorizationEnvironmentUsername, user); @@ -1166,14 +1165,14 @@ static void _parse_environment(engine_t engine, auth_items_t environment) static bool _verify_sandbox(engine_t engine, const char * right) { pid_t pid = process_get_pid(engine->proc); - if (sandbox_check(pid, "authorization-right-obtain", SANDBOX_FILTER_RIGHT_NAME, right)) { - os_log_error(AUTHD_LOG, "Sandbox denied authorizing right '%{public}s' by client '%{public}s' [%d]", right, process_get_code_url(engine->proc), pid); + if (sandbox_check_by_audit_token(process_get_audit_info(engine->proc)->opaqueToken, "authorization-right-obtain", SANDBOX_FILTER_RIGHT_NAME, right)) { + os_log_error(AUTHD_LOG, "Sandbox denied authorizing right '%{public}s' by client '%{public}s' [%d] (engine %lld)", right, process_get_code_url(engine->proc), pid, engine->engine_index); return false; } pid = auth_token_get_pid(engine->auth); if (auth_token_get_sandboxed(engine->auth) && sandbox_check_by_audit_token(auth_token_get_audit_info(engine->auth)->opaqueToken, "authorization-right-obtain", SANDBOX_FILTER_RIGHT_NAME, right)) { - os_log_error(AUTHD_LOG, "Sandbox denied authorizing right '%{public}s' for authorization created by '%{public}s' [%d]", right, auth_token_get_code_url(engine->auth), pid); + os_log_error(AUTHD_LOG, "Sandbox denied authorizing right '%{public}s' for authorization created by '%{public}s' [%d] (engine %lld)", right, auth_token_get_code_url(engine->auth), pid, engine->engine_index); return false; } @@ -1185,31 +1184,15 @@ static bool _verify_sandbox(engine_t engine, const char * right) OSStatus engine_preauthorize(engine_t engine, auth_items_t credentials) { - os_log(AUTHD_LOG, "engine: preauthorizing"); + os_log(AUTHD_LOG, "engine %lld: preauthorizing", engine->engine_index); OSStatus status = errAuthorizationDenied; bool save_password = false; - CFTypeRef extract_password_entitlement = auth_token_copy_entitlement_value(engine->auth, "com.apple.authorization.extract-password"); - if (extract_password_entitlement && (CFGetTypeID(extract_password_entitlement) == CFBooleanGetTypeID()) && extract_password_entitlement == kCFBooleanTrue) { - save_password = true; - os_log_debug(AUTHD_LOG, "engine: authorization allowed to extract password"); - } else { - os_log_debug(AUTHD_LOG, "engine: authorization NOT allowed to extract password"); - } - CFReleaseSafe(extract_password_entitlement); - - // TODO: Remove when all clients have adopted entitlement - if (!enforced_entitlement()) { - save_password = true; - } engine->flags = kAuthorizationFlagExtendRights; engine->preauthorizing = true; - CFTypeRef la_context = engine_copy_context(engine, credentials); - if (la_context) { - _extract_password_from_la(engine, la_context); - CFRelease(la_context); - } + 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); @@ -1236,7 +1219,7 @@ OSStatus engine_preauthorize(engine_t engine, auth_items_t credentials) } auth_items_t decrypted_items = auth_items_create(); - require_action(decrypted_items != NULL, done, os_log_error(AUTHD_LOG, "engine: unable to create items")); + 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); @@ -1251,20 +1234,20 @@ OSStatus engine_preauthorize(engine_t engine, auth_items_t credentials) 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)", + 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)); + 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)", + 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); + 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, "engine: preauthorize returned %d => returning errAuthorizationInternal", (int)status); + os_log_error(AUTHD_LOG, "Preauthorize returned %d => returning errAuthorizationInternal (engine %lld)", (int)status, engine->engine_index); status = errAuthorizationInternal; break; } @@ -1272,11 +1255,11 @@ OSStatus engine_preauthorize(engine_t engine, auth_items_t credentials) CFReleaseSafe(rule); if (engine->dismissed) { - os_log_error(AUTHD_LOG, "engine: engine dismissed"); + os_log_error(AUTHD_LOG, "Engine dismissed (engine %lld)", engine->engine_index); status = errAuthorizationDenied; } - os_log_debug(AUTHD_LOG, "engine: preauthorize result: %d", (int)status); + 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; @@ -1290,9 +1273,9 @@ OSStatus engine_preauthorize(engine_t engine, auth_items_t credentials) session_set_credential(session, cred); } if (credential_is_right(cred)) { - os_log(AUTHD_LOG, "engine: adding least privileged %{public}scredential %{public}s to authorization", credential_get_shared(cred) ? "shared " : "", credential_get_name(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: adding %{public}scredential %{public}s (%i) to authorization", credential_get_shared(cred) ? "shared " : "", credential_get_name(cred), credential_get_uid(cred)); + 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; }); @@ -1304,15 +1287,15 @@ OSStatus engine_preauthorize(engine_t engine, auth_items_t credentials) if ((status == errAuthorizationSuccess) || (status == errAuthorizationCanceled)) { auth_items_t encrypted_items = auth_items_create(); - require_action(encrypted_items != NULL, done, os_log_error(AUTHD_LOG, "engine: unable to create items")); + 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: ********** Dumping preauthorized context for encryption **********"); + 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: encrypted preauthorization context data"); + os_log_debug(AUTHD_LOG, "engine %lld: encrypted preauthorization context data", engine->engine_index); CFReleaseSafe(encrypted_items); } @@ -1329,7 +1312,7 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en __block OSStatus status = errAuthorizationSuccess; __block bool save_password = false; __block bool password_only = false; - + CFIndex rights_count = auth_rights_get_count(rights); ccaudit_t ccaudit = NULL; require(rights != NULL, done); @@ -1339,24 +1322,95 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en ccaudit_log(ccaudit, "begin evaluation", NULL, 0); } + if (rights_count) { + __block CFMutableArrayRef rights_list = NULL; + rights_list = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + auth_rights_iterate(rights, ^bool(const char *key) { + if (!key) + return true; + + CFStringRef tmp = CFStringCreateWithCString(kCFAllocatorDefault, key, kCFStringEncodingUTF8); + if (tmp) { + CFArrayAppendValue(rights_list, tmp); + CFRelease(tmp); + } else { + os_log_error(AUTHD_LOG, "Unable to get details for right %{public}s", key); + } + return true; + }); + + os_log_info(AUTHD_LOG, "Process %{public}s (PID %d) evaluates %ld rights with flags %08x (engine %lld): %{public}@", process_get_code_url(engine->proc), process_get_pid(engine->proc), (long)rights_count, flags, engine->engine_index, rights_list); + CFReleaseNull(rights_list); + } + + if (!auth_token_apple_signed(engine->auth) && (flags & kAuthorizationFlagSheet)) { +#ifdef NDEBUG + os_log_error(AUTHD_LOG, "engine %lld: extra flags are ommited as creator is not signed by Apple", engine->engine_index); + flags &= ~kAuthorizationFlagSheet; +#else + os_log_debug(AUTHD_LOG, "engine %lld: in release mode, extra flags would be ommited as creator is not signed by Apple", engine->engine_index); +#endif + } + engine->flags = flags; if (environment) { _parse_environment(engine, environment); auth_items_copy(engine->hints, environment); - engine_acquire_sheet_data(engine); } - auth_items_t decrypted_items = auth_items_create(); - require_action(decrypted_items != NULL, done, os_log_error(AUTHD_LOG, "engine: enable to create items")); - 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); + // Restore all context values from the AuthorizationRef + 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); + + if (engine->flags & kAuthorizationFlagSheet) { + // Try to use/update fresh context values from the environment + require_action(environment, done, os_log_error(AUTHD_LOG, "Missing environment for sheet authorization (engine %lld)", engine->engine_index); status = errAuthorizationDenied); + + const char *user = auth_items_get_string(environment, kAuthorizationEnvironmentUsername); + require_action(user, done, os_log_error(AUTHD_LOG, "Missing username (engine %lld)", engine->engine_index); status = errAuthorizationDenied); + + auth_items_set_string(engine->context, kAuthorizationEnvironmentUsername, user); + struct passwd *pwd = getpwnam(user); + require_action(pwd, done, os_log_error(AUTHD_LOG, "Invalid username %s (engine %lld)", user, engine->engine_index); status = errAuthorizationDenied); + auth_items_set_uint(engine->context, "sheet-uid", pwd->pw_uid); + + // move sheet-specific items from hints to context + const char *service = auth_items_get_string(engine->hints, AGENT_CONTEXT_AP_PAM_SERVICE_NAME); + if (service) { + if (auth_items_exist(engine->hints, AGENT_CONTEXT_AP_USER_NAME)) { + auth_items_set_string(engine->context, AGENT_CONTEXT_AP_USER_NAME, auth_items_get_string(engine->hints, AGENT_CONTEXT_AP_USER_NAME)); + auth_items_remove(engine->hints, AGENT_CONTEXT_AP_USER_NAME); + } else { + 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); + auth_items_remove(engine->hints, AGENT_CONTEXT_AP_PAM_SERVICE_NAME); + } + + if (auth_items_exist(environment, AGENT_CONTEXT_AP_TOKEN)) { + size_t datalen = 0; + const void *data = auth_items_get_data(engine->hints, AGENT_CONTEXT_AP_TOKEN, &datalen); + if (data) { + auth_items_set_data(engine->context, AGENT_CONTEXT_AP_TOKEN, data, datalen); + } + auth_items_remove(engine->hints, AGENT_CONTEXT_AP_TOKEN); + } + + engine_acquire_sheet_data(engine); + _extract_password_from_la(engine); + engine->preauthorizing = true; + } engine->dismissed = false; auth_rights_clear(engine->grantedRights); + if (!(engine->flags & kAuthorizationFlagIgnorePasswordOnly)) { // 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. @@ -1364,7 +1418,7 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en auth_rights_iterate(rights, ^bool(const char *key) { if (!key) return true; - os_log_debug(AUTHD_LOG, "engine: checking if rule %{public}s contains password-only item", key); + 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); @@ -1377,10 +1431,12 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en return true; }); authdb_connection_release(&dbconn); // release db handle + } else { + os_log_info(AUTHD_LOG, "Password-only flag ignored (engine %lld)", engine->engine_index); } if (password_only) { - os_log_debug(AUTHD_LOG, "engine: password-only item found, forcing SecurityAgent to use password-only UI"); + os_log_debug(AUTHD_LOG, "engine %lld: password-only item found, forcing SecurityAgent to use password-only UI", engine->engine_index); auth_items_set_bool(engine->immutable_hints, AGENT_HINT_PASSWORD_ONLY, true); } @@ -1388,7 +1444,6 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en if (!key) return true; - if (!_verify_sandbox(engine, key)) { // _verify_sandbox is already logging failures status = errAuthorizationDenied; return false; @@ -1396,16 +1451,16 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en authdb_connection_t dbconn = authdb_connection_acquire(server_get_database()); // get db handle - os_log_debug(AUTHD_LOG, "engine: evaluate right %{public}s", key); + os_log_debug(AUTHD_LOG, "engine %lld: evaluate right %{public}s", engine->engine_index, key); rule_t rule = _find_rule(engine, dbconn, key); const char * rule_name = rule_get_name(rule); if (rule_name && (strcasecmp(rule_name, "") == 0)) { rule_name = "default (not defined)"; } - os_log_debug(AUTHD_LOG, "engine: using rule %{public}s", rule_name); + os_log_debug(AUTHD_LOG, "engine %lld: using rule %{public}s", engine->engine_index, rule_name); // only need the hints & mechanisms if we are going to show ui - if (engine->flags & kAuthorizationFlagInteractionAllowed) { + if (engine->flags & kAuthorizationFlagInteractionAllowed || engine->flags & kAuthorizationFlagSheet) { _set_right_hints(engine->hints, key); _set_localization_hints(dbconn, engine->hints, rule); if (!engine->authenticateRule) { @@ -1424,7 +1479,7 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en switch (status) { case errAuthorizationSuccess: auth_rights_add(engine->grantedRights, key); - auth_rights_set_flags(engine->grantedRights, key, auth_rights_get_flags(rights,key)); + auth_rights_set_flags(engine->grantedRights, key, auth_rights_get_flags(rights, key)); if ((engine->flags & kAuthorizationFlagPreAuthorize) && (rule_get_class(engine->currentRule) == RC_USER) && @@ -1433,25 +1488,27 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en auth_rights_set_flags(engine->grantedRights, engine->currentRightName, kAuthorizationFlagPreAuthorize); } - os_log(AUTHD_LOG, "Succeeded authorizing right '%{public}s' by client '%{public}s' [%d] for authorization created by '%{public}s' [%d] (%X,%d)", + os_log(AUTHD_LOG, "Succeeded authorizing right '%{public}s' by client '%{public}s' [%d] for authorization created by '%{public}s' [%d] (%X,%d) (engine %lld)", key, 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)); + 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); break; case errAuthorizationDenied: case errAuthorizationInteractionNotAllowed: case errAuthorizationCanceled: if (engine->flags & kAuthorizationFlagInteractionAllowed) { - os_log(AUTHD_LOG, "Failed to authorize right '%{public}s' by client '%{public}s' [%d] for authorization created by '%{public}s' [%d] (%X,%d) (%i)", + os_log(AUTHD_LOG, "Failed to authorize right '%{public}s' by client '%{public}s' [%d] for authorization created by '%{public}s' [%d] (%X,%d) (%i) (engine %lld)", key, 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); + 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); } else { - os_log_debug(AUTHD_LOG, "Failed to authorize right '%{public}s' by client '%{public}s' [%d] for authorization created by '%{public}s' [%d] (%X,%d) (%d)", + os_log_debug(AUTHD_LOG, "Failed to authorize right '%{public}s' by client '%{public}s' [%d] for authorization created by '%{public}s' [%d] (%X,%d) (%d) (engine %lld)", key, 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); + 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, "engine: evaluate returned %d returning errAuthorizationInternal", (int)status); + os_log_error(AUTHD_LOG, "Evaluate returned %d, returning errAuthorizationInternal (engine %lld)", (int)status, engine->engine_index); status = errAuthorizationInternal; break; } @@ -1472,7 +1529,7 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en }); if (password_only) { - os_log_debug(AUTHD_LOG, "engine: removing password-only flag"); + os_log_debug(AUTHD_LOG, "engine %lld: removing password-only flag", engine->engine_index); auth_items_remove(engine->immutable_hints, AGENT_HINT_PASSWORD_ONLY); } @@ -1481,12 +1538,16 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en } if (engine->dismissed) { - os_log_error(AUTHD_LOG, "engine: dismissed"); + os_log_error(AUTHD_LOG, "Dismissed (engine %lld)", engine->engine_index); status = errAuthorizationDenied; } - os_log_debug(AUTHD_LOG, "engine: authorize result: %d", (int)status); - + 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; @@ -1500,9 +1561,9 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en session_set_credential(session, cred); } if (credential_is_right(cred)) { - os_log_debug(AUTHD_LOG, "engine: adding least privileged %{public}scredential %{public}s to authorization", credential_get_shared(cred) ? "shared " : "", credential_get_name(cred)); + os_log_debug(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_debug(AUTHD_LOG, "engine: adding %{public}scredential %{public}s (%i) to authorization", credential_get_shared(cred) ? "shared " : "", credential_get_name(cred), credential_get_uid(cred)); + os_log_debug(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; }); @@ -1514,16 +1575,16 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en if ((status == errAuthorizationSuccess) || (status == errAuthorizationCanceled)) { auth_items_t encrypted_items = auth_items_create(); - require_action(encrypted_items != NULL, done, os_log_error(AUTHD_LOG, "engine: unable to create items")); + 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: ********** Dumping context for encryption **********"); + os_log_debug(AUTHD_LOG,"engine %lld: ********** Dumping 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: encrypted authorization context data"); - CFReleaseSafe(encrypted_items); + os_log_debug(AUTHD_LOG, "engine %lld: encrypted authorization context data", engine->engine_index); + CFReleaseSafe(encrypted_items); } if (auth_rights_get_count(rights) > 0) { @@ -1531,21 +1592,21 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en } #if DEBUG - os_log_debug(AUTHD_LOG, "engine: ********** Dumping auth->credentials **********"); + os_log_debug(AUTHD_LOG, "engine %lld: ********** Dumping auth->credentials **********", engine->engine_index); auth_token_credentials_iterate(engine->auth, ^bool(credential_t cred) { os_log_debug(AUTHD_LOG, "%@", cred); return true; }); - os_log_debug(AUTHD_LOG, "engine: ********** Dumping session->credentials **********"); + os_log_debug(AUTHD_LOG, "engine %lld: ********** Dumping session->credentials **********", engine->engine_index); session_credentials_iterate(auth_token_get_session(engine->auth), ^bool(credential_t cred) { os_log_debug(AUTHD_LOG, "%@", cred); return true; }); - os_log_debug(AUTHD_LOG, "engine: ********** Dumping engine->context **********"); + os_log_debug(AUTHD_LOG, "engine %lld: ********** Dumping engine->context **********", engine->engine_index); os_log_debug(AUTHD_LOG, "%@", engine->context); - os_log_debug(AUTHD_LOG, "engine: ********** Dumping auth->context **********"); + os_log_debug(AUTHD_LOG, "engine %lld: ********** Dumping auth->context **********", engine->engine_index); os_log_debug(AUTHD_LOG, "%@", engine->auth); - os_log_debug(AUTHD_LOG, "engine: ********** Dumping granted rights **********"); + os_log_debug(AUTHD_LOG, "engine %lld: ********** Dumping granted rights **********", engine->engine_index); os_log_debug(AUTHD_LOG, "%@", engine->grantedRights); #endif @@ -1613,7 +1674,7 @@ OSStatus engine_verify_modification(engine_t engine, rule_t rule, bool remove, b size_t len = strlen(right); require(len != 0, done); - require_action(right[len-1] != '.', done, os_log_error(AUTHD_LOG, "engine: not allowed to set wild card rules")); + require_action(right[len-1] != '.', done, os_log_error(AUTHD_LOG, "Not allowed to set wild card rules (engine %lld)", engine->engine_index)); if (strncasecmp(right, kConfigRight, strlen(kConfigRight)) == 0) { // special handling of meta right change: @@ -1645,7 +1706,7 @@ OSStatus engine_verify_modification(engine_t engine, rule_t rule, bool remove, b status = engine_authorize(engine, checkRight, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights); done: - os_log_debug(AUTHD_LOG, "engine: authorizing %{public}s for db modification: %d", right, (int)status); + os_log_debug(AUTHD_LOG, "engine %lld: authorizing %{public}s for db modification: %d", engine->engine_index, right, (int)status); CFReleaseSafe(checkRight); return status; } @@ -1653,7 +1714,7 @@ OSStatus engine_verify_modification(engine_t engine, rule_t rule, bool remove, b void _engine_set_credential(engine_t engine, credential_t cred, bool shared) { - os_log_debug(AUTHD_LOG, "engine: adding %{public}scredential %{public}s (%i) to engine shared: %i", credential_get_shared(cred) ? "shared " : "", credential_get_name(cred), credential_get_uid(cred), shared); + os_log_debug(AUTHD_LOG, "engine %lld: adding %{public}scredential %{public}s (%i) to engine shared: %i", engine->engine_index, credential_get_shared(cred) ? "shared " : "", credential_get_name(cred), credential_get_uid(cred), shared); CFSetSetValue(engine->credentials, cred); if (shared) { credential_t sharedCred = credential_create_with_credential(cred, true); @@ -1678,7 +1739,7 @@ void engine_destroy_agents(engine_t engine) engine->dismissed = true; _cf_dictionary_iterate(engine->mechanism_agents, ^bool(CFTypeRef key __attribute__((__unused__)), CFTypeRef value) { - os_log_debug(AUTHD_LOG, "engine: Destroying %{public}s", mechanism_get_string((mechanism_t)key)); + os_log_debug(AUTHD_LOG, "engine %lld: Destroying %{public}s", engine->engine_index, mechanism_get_string((mechanism_t)key)); agent_t agent = (agent_t)value; agent_destroy(agent); @@ -1701,13 +1762,13 @@ CFTypeRef engine_copy_context(engine_t engine, auth_items_t source) process_t proc = connection_get_process(engine->conn); if (!proc) { - os_log_error(AUTHD_LOG, "engine: No client process"); + os_log_error(AUTHD_LOG, "No client process (engine %lld)", engine->engine_index); return retval; } uid_t client_uid = process_get_uid(proc); if (!client_uid) { - os_log_error(AUTHD_LOG, "engine: No client UID"); + os_log_error(AUTHD_LOG, "No client UID (engine %lld)", engine->engine_index); return retval; } @@ -1716,7 +1777,7 @@ CFTypeRef engine_copy_context(engine_t engine, auth_items_t source) if (data) { CFDataRef externalized = CFDataCreate(kCFAllocatorDefault, data, dataLen); if (externalized) { - os_log_debug(AUTHD_LOG, "engine: Going to get LA context for UID %d", client_uid); + os_log_debug(AUTHD_LOG, "engine %lld: going to get LA context for UID %d", engine->engine_index, client_uid); retval = LACreateNewContextWithACMContextInSession(client_uid, externalized, NULL); CFRelease(externalized); } @@ -1727,24 +1788,19 @@ CFTypeRef engine_copy_context(engine_t engine, auth_items_t source) bool engine_acquire_sheet_data(engine_t engine) { - uid_t uid = auth_items_get_int(engine->hints, AGENT_CONTEXT_UID); - if (!uid) + if (!auth_items_exist(engine->context, "sheet-uid")) return false; + uid_t uid = auth_items_get_uint(engine->context, "sheet-uid"); + CFReleaseSafe(engine->la_context); engine->la_context = engine_copy_context(engine, engine->hints); if (engine->la_context) { - // copy UID to the context of the authorization - os_log_debug(AUTHD_LOG, "engine: Sheet user UID %d", uid); - auth_items_set_int(engine->context, AGENT_CONTEXT_UID, uid); - struct passwd *pwd = getpwuid(uid); - if (pwd) { - auth_items_set_string(engine->context, kAuthorizationEnvironmentUsername, pwd->pw_name); - } + os_log_debug(AUTHD_LOG, "engine %lld: Sheet UID %d", engine->engine_index, uid); return true; } else { // this is not real failure as no LA context in authorization context is very valid scenario - os_log_debug(AUTHD_LOG, "engine: Failed to get LA context"); + os_log_debug(AUTHD_LOG, "engine %lld: Failed to get LA context", engine->engine_index); } return false; } diff --git a/OSX/authd/process.c b/OSX/authd/process.c index 1cbf78edd..4a2457577 100644 --- a/OSX/authd/process.c +++ b/OSX/authd/process.c @@ -26,7 +26,6 @@ struct _process_s { CFMutableSetRef connections; - SecCodeRef codeRef; char code_url[PATH_MAX+1]; char * code_identifier; CFDataRef code_requirement_data; @@ -82,7 +81,6 @@ _process_finalize(CFTypeRef value) CFReleaseNull(proc->authTokens); CFReleaseNull(proc->connections); CFReleaseNull(proc->session); - CFReleaseNull(proc->codeRef); CFReleaseNull(proc->code_requirement); CFReleaseNull(proc->code_requirement_data); CFReleaseNull(proc->code_entitlements); @@ -121,6 +119,7 @@ process_create(const audit_info_s * auditInfo, session_t session) process_t proc = NULL; CFDictionaryRef code_info = NULL; CFURLRef code_url = NULL; + SecCodeRef codeRef = NULL; require(session != NULL, done); require(auditInfo != NULL, done); @@ -141,11 +140,18 @@ process_create(const audit_info_s * auditInfo, session_t session) check(proc->dispatch_queue != NULL); CFMutableDictionaryRef codeDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFNumberRef codePid = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &proc->auditInfo.pid); - CFDictionarySetValue(codeDict, kSecGuestAttributePid, codePid); - status = SecCodeCopyGuestWithAttributes(NULL, codeDict, kSecCSDefaultFlags, &proc->codeRef); + CFDataRef auditToken = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (UInt8 *)&auditInfo->opaqueToken, sizeof(auditInfo->opaqueToken), kCFAllocatorNull); + if (auditToken) { + CFDictionarySetValue(codeDict, kSecGuestAttributeAudit, auditToken); + CFReleaseNull(auditToken); + } else { + CFReleaseSafe(codeDict); + os_log_error(AUTHD_LOG, "process: PID %d failed to create audit token", proc->auditInfo.pid); + CFReleaseNull(proc); + goto done; + } + status = SecCodeCopyGuestWithAttributes(NULL, codeDict, kSecCSDefaultFlags, &codeRef); CFReleaseSafe(codeDict); - CFReleaseSafe(codePid); if (status) { os_log_error(AUTHD_LOG, "process: PID %d failed to create code ref %d", proc->auditInfo.pid, (int)status); @@ -153,7 +159,7 @@ process_create(const audit_info_s * auditInfo, session_t session) goto done; } - status = SecCodeCopySigningInformation(proc->codeRef, kSecCSRequirementInformation, &code_info); + status = SecCodeCopySigningInformation(codeRef, kSecCSRequirementInformation, &code_info); require_noerr_action(status, done, os_log_debug(AUTHD_LOG, "process: PID %d SecCodeCopySigningInformation failed with %d", proc->auditInfo.pid, (int)status)); CFTypeRef value = NULL; @@ -167,7 +173,7 @@ process_create(const audit_info_s * auditInfo, session_t session) value = NULL; } - if (SecCodeCopyPath(proc->codeRef, kSecCSDefaultFlags, &code_url) == errSecSuccess) { + if (SecCodeCopyPath(codeRef, kSecCSDefaultFlags, &code_url) == errSecSuccess) { CFURLGetFileSystemRepresentation(code_url, true, (UInt8*)proc->code_url, sizeof(proc->code_url)); } @@ -189,15 +195,15 @@ process_create(const audit_info_s * auditInfo, session_t session) // AppStore apps must have resource envelope 2. Check with spctl -a -t exec -vv CFStringRef firstPartyRequirement = CFSTR("anchor apple"); CFStringRef appStoreRequirement = CFSTR("anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.9] exists"); - SecRequirementRef secRequirementRef = NULL; + SecRequirementRef secRequirementRef = NULL; status = SecRequirementCreateWithString(firstPartyRequirement, kSecCSDefaultFlags, &secRequirementRef); if (status == errSecSuccess) { - proc->firstPartySigned = process_verify_requirement(proc, secRequirementRef); + proc->firstPartySigned = process_verify_requirement(proc, codeRef, secRequirementRef); CFReleaseNull(secRequirementRef); } status = SecRequirementCreateWithString(appStoreRequirement, kSecCSDefaultFlags, &secRequirementRef); if (status == errSecSuccess) { - proc->appStoreSigned = process_verify_requirement(proc, secRequirementRef); + proc->appStoreSigned = process_verify_requirement(proc, codeRef, secRequirementRef); CFReleaseSafe(secRequirementRef); } os_log_debug(AUTHD_LOG, "process: PID %d created (sid=%i) %{public}s", proc->auditInfo.pid, proc->auditInfo.asid, proc->code_url); @@ -205,6 +211,7 @@ process_create(const audit_info_s * auditInfo, session_t session) done: CFReleaseSafe(code_info); CFReleaseSafe(code_url); + CFReleaseSafe(codeRef); return proc; } @@ -254,12 +261,6 @@ process_get_audit_info(process_t proc) return &proc->auditInfo; } -SecCodeRef -process_get_code(process_t proc) -{ - return proc->codeRef; -} - const char * process_get_code_url(process_t proc) { @@ -466,9 +467,9 @@ process_get_requirement(process_t proc) return proc->code_requirement; } -bool process_verify_requirement(process_t proc, SecRequirementRef requirment) +bool process_verify_requirement(process_t proc, SecCodeRef codeRef, SecRequirementRef requirment) { - OSStatus status = SecCodeCheckValidity(proc->codeRef, kSecCSDefaultFlags, requirment); + OSStatus status = SecCodeCheckValidity(codeRef, kSecCSDefaultFlags, requirment); if (status != errSecSuccess) { os_log_debug(AUTHD_LOG, "process: PID %d code requirement check failed (%d)", proc->auditInfo.pid, (int)status); } diff --git a/OSX/authd/process.h b/OSX/authd/process.h index c4def5641..3f2a0284e 100644 --- a/OSX/authd/process.h +++ b/OSX/authd/process.h @@ -38,9 +38,6 @@ uint32_t process_get_count(process_t); AUTH_NONNULL_ALL const audit_info_s * process_get_audit_info(process_t); -AUTH_NONNULL_ALL -SecCodeRef process_get_code(process_t); - AUTH_NONNULL_ALL const char * process_get_code_url(process_t); @@ -84,7 +81,7 @@ AUTH_NONNULL_ALL SecRequirementRef process_get_requirement(process_t); AUTH_NONNULL_ALL -bool process_verify_requirement(process_t, SecRequirementRef); +bool process_verify_requirement(process_t, SecCodeRef, SecRequirementRef); AUTH_NONNULL_ALL bool process_apple_signed(process_t proc); diff --git a/OSX/authd/rule.c b/OSX/authd/rule.c index b084b72a7..a706b4d3a 100644 --- a/OSX/authd/rule.c +++ b/OSX/authd/rule.c @@ -11,6 +11,7 @@ #include #include #include "server.h" +#include AUTHD_DEFINE_LOG @@ -747,6 +748,7 @@ bool rule_sql_commit(rule_t rule, authdb_connection_t dbconn, CFAbsoluteTime modified, process_t proc) { bool result = false; + __block bool insert = false; // type and class required else rule is name only? RuleClass rule_class = rule_get_class(rule); require(rule_get_type(rule) != 0, done); @@ -792,6 +794,7 @@ rule_sql_commit(rule_t rule, authdb_connection_t dbconn, CFAbsoluteTime modified if (rule_get_id(rule)) { update = _sql_update(rule, dbconn); } else { + insert = true; if (proc) { const char * ident = process_get_identifier(proc); if (ident) { @@ -824,12 +827,14 @@ rule_sql_commit(rule_t rule, authdb_connection_t dbconn, CFAbsoluteTime modified done: if (!result) { os_log_debug(AUTHD_LOG, "rule: commit, failed for %{public}s (%llu)", rule_get_name(rule), rule_get_id(rule)); + } else { + rule_log_manipulation(dbconn, rule, insert ? rule_insert : rule_update, proc); } return result; } bool -rule_sql_remove(rule_t rule, authdb_connection_t dbconn) +rule_sql_remove(rule_t rule, authdb_connection_t dbconn, process_t proc) { bool result = false; int64_t id = rule_get_id(rule); @@ -844,7 +849,12 @@ rule_sql_remove(rule_t rule, authdb_connection_t dbconn) ^(sqlite3_stmt *stmt) { sqlite3_bind_int64(stmt, 1, id); }, NULL); -done: + + if (result) { + rule_log_manipulation(dbconn, rule, rule_delete, proc); + } + +done: return result; } @@ -1246,3 +1256,25 @@ SecRequirementRef rule_get_requirement(rule_t rule) return rule->requirement; } + +void +rule_log_manipulation(authdb_connection_t dbconn, rule_t rule, RuleOperation operation, process_t source) +{ + authdb_step(dbconn, "INSERT INTO rules_history (rule, source, operation, version) VALUES (?,?,?,?)", ^(sqlite3_stmt *stmt) { + char pathbuf[PROC_PIDPATHINFO_MAXSIZE]; + if (source) { + pid_t pid = process_get_pid(source); + if (!proc_pidpath(pid, pathbuf, sizeof(pathbuf))) { + os_log_error(AUTHD_LOG, "Failed to get path for pid %d", pid); + snprintf(pathbuf, sizeof(pathbuf), "Unknown process with PID %d", pid); + } + } else { + strncpy(pathbuf, "authd", sizeof(pathbuf)); + } + + sqlite3_bind_text(stmt, 1, rule_get_name(rule), -1, NULL); + sqlite3_bind_text(stmt, 2, pathbuf, -1, NULL); + sqlite3_bind_int(stmt, 3, operation); + sqlite3_bind_int64(stmt, 4, rule_get_version(rule)); + }, NULL); +} diff --git a/OSX/authd/rule.h b/OSX/authd/rule.h index f5d007234..098087d58 100644 --- a/OSX/authd/rule.h +++ b/OSX/authd/rule.h @@ -41,6 +41,12 @@ enum { }; typedef uint32_t RuleFlags; +typedef enum { + rule_insert, + rule_update, + rule_delete, +} RuleOperation; + AUTH_WARN_RESULT AUTH_MALLOC AUTH_NONNULL_ALL AUTH_RETURNS_RETAINED rule_t rule_create_default(void); @@ -75,7 +81,7 @@ AUTH_NONNULL1 AUTH_NONNULL2 bool rule_sql_commit(rule_t,authdb_connection_t,CFAbsoluteTime,process_t); AUTH_NONNULL_ALL -bool rule_sql_remove(rule_t,authdb_connection_t); +bool rule_sql_remove(rule_t,authdb_connection_t,process_t); AUTH_NONNULL_ALL CFMutableDictionaryRef rule_copy_to_cfobject(rule_t,authdb_connection_t); @@ -146,6 +152,9 @@ CFDataRef rule_get_requirement_data(rule_t); AUTH_NONNULL_ALL SecRequirementRef rule_get_requirement(rule_t); +AUTH_NONNULL1 AUTH_NONNULL2 +void rule_log_manipulation(authdb_connection_t dbconn, rule_t rule, RuleOperation operation, process_t source); + #if defined(__cplusplus) } #endif diff --git a/OSX/authd/server.c b/OSX/authd/server.c index 2d46808fc..728ae6e28 100644 --- a/OSX/authd/server.c +++ b/OSX/authd/server.c @@ -14,6 +14,7 @@ #include "debugging.h" #include "engine.h" #include "connection.h" +#include "AuthorizationTags.h" #include #include @@ -37,9 +38,6 @@ static CFMutableDictionaryRef gSessionMap = NULL; static CFMutableDictionaryRef gAuthTokenMap = NULL; static authdb_t gDatabase = NULL; -static dispatch_queue_t power_queue; -static bool gInDarkWake = false; -static IOPMConnection gIOPMconn = NULL; static bool gXPCTransaction = false; static dispatch_queue_t @@ -112,71 +110,15 @@ void server_cleanup() CFRelease(gSessionMap); CFRelease(gAuthTokenMap); - IOPMConnectionSetDispatchQueue(gIOPMconn, NULL); - IOPMConnectionRelease(gIOPMconn); - dispatch_queue_t queue = get_server_dispatch_queue(); if (queue) { dispatch_release(queue); } - dispatch_release(power_queue); -} - -static void _IOMPCallBack(void * param AUTH_UNUSED, IOPMConnection connection, IOPMConnectionMessageToken token, IOPMSystemPowerStateCapabilities capabilities) -{ - os_log_debug(AUTHD_LOG, "server: IOMP powerstates %i", capabilities); - if (capabilities & kIOPMSystemPowerStateCapabilityDisk) - os_log_debug(AUTHD_LOG, "server: disk"); - if (capabilities & kIOPMSystemPowerStateCapabilityNetwork) - os_log_debug(AUTHD_LOG, "server: net"); - if (capabilities & kIOPMSystemPowerStateCapabilityAudio) - os_log_debug(AUTHD_LOG, "server: audio"); - if (capabilities & kIOPMSystemPowerStateCapabilityVideo) - os_log_debug(AUTHD_LOG, "server: video"); - - /* if cpu and no display -> in DarkWake */ - os_log_debug(AUTHD_LOG, "server: DarkWake check current=%i==%i", (capabilities & (kIOPMSystemPowerStateCapabilityCPU|kIOPMSystemPowerStateCapabilityVideo)), kIOPMSystemPowerStateCapabilityCPU); - if ((capabilities & (kIOPMSystemPowerStateCapabilityCPU|kIOPMSystemPowerStateCapabilityVideo)) == kIOPMSystemPowerStateCapabilityCPU) { - os_log_debug(AUTHD_LOG, "server: enter DW"); - gInDarkWake = true; - } else if (gInDarkWake) { - os_log_debug(AUTHD_LOG, "server: exit DW"); - gInDarkWake = false; - } - - (void)IOPMConnectionAcknowledgeEvent(connection, token); - - return; -} - -static void -_setupDarkWake(void *__unused ctx) -{ - IOReturn ret; - - IOPMConnectionCreate(CFSTR("IOPowerWatcher"), - kIOPMSystemPowerStateCapabilityDisk - | kIOPMSystemPowerStateCapabilityNetwork - | kIOPMSystemPowerStateCapabilityAudio - | kIOPMSystemPowerStateCapabilityVideo, - &gIOPMconn); - - ret = IOPMConnectionSetNotification(gIOPMconn, NULL, _IOMPCallBack); - if (ret != kIOReturnSuccess) - return; - - IOPMConnectionSetDispatchQueue(gIOPMconn, power_queue); - - IOPMScheduleUserActiveChangedNotification(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(bool active) { - if (active) { - gInDarkWake = false; - } - }); } bool server_in_dark_wake() { - return gInDarkWake; + return IOPMIsADarkWake(IOPMConnectionGetSystemCapabilities()); } authdb_t server_get_database() @@ -256,10 +198,6 @@ OSStatus server_init(void) authdb_maintenance(dbconn); authdb_connection_release(&dbconn); - power_queue = dispatch_queue_create("com.apple.security.auth.power", DISPATCH_QUEUE_SERIAL); - require_action(power_queue != NULL, done, status = errAuthorizationInternal); - dispatch_async_f(power_queue, NULL, _setupDarkWake); - _setupAuditSessionMonitor(); _setupSignalHandlers(); @@ -711,6 +649,18 @@ authorization_copy_info(connection_t conn, xpc_object_t message, xpc_object_t re os_log_debug(AUTHD_LOG, "server: Dumping requested AuthRef items: %{public}@", items); #endif + if (auth_items_exist(local_items, kAuthorizationEnvironmentPassword)) { + // check if caller is entitled to get the password + CFTypeRef extract_password_entitlement = process_copy_entitlement_value(proc, "com.apple.authorization.extract-password"); + if (extract_password_entitlement && (CFGetTypeID(extract_password_entitlement) == CFBooleanGetTypeID()) && extract_password_entitlement == kCFBooleanTrue) { + os_log_debug(AUTHD_LOG, "server: caller allowed to extract password"); + } else { + os_log_error(AUTHD_LOG, "server: caller NOT allowed to extract password"); + auth_items_remove(local_items, kAuthorizationEnvironmentPassword); + } + CFReleaseSafe(extract_password_entitlement); + } + //reply xpc_object_t outItems = auth_items_export_xpc(local_items); xpc_dictionary_set_value(reply, AUTH_XPC_OUT_ITEMS, outItems); @@ -1148,7 +1098,7 @@ authorization_right_remove(connection_t conn, xpc_object_t message, xpc_object_t } if (rule_get_id(rule) != 0) { - rule_sql_remove(rule, dbconn); + rule_sql_remove(rule, dbconn, proc); } done: diff --git a/OSX/authd/session.c b/OSX/authd/session.c index d631e74ae..83d548e8e 100644 --- a/OSX/authd/session.c +++ b/OSX/authd/session.c @@ -196,6 +196,11 @@ session_credentials_iterate(session_t session, credential_iterator_t iter) dispatch_sync(session->dispatch_queue, ^{ CFIndex count = CFSetGetCount(session->credentials); + if (count > 128) { // Variable Length Arrays; AuthD + // session usually contains 0 or 1 credential + count = 128; + } + CFTypeRef values[count]; CFSetGetValues(session->credentials, values); for (CFIndex i = 0; i < count; i++) { diff --git a/OSX/authd/tests/authdtestlist.h b/OSX/authd/tests/authdtestlist.h index 9f43ceef6..1987df61e 100644 --- a/OSX/authd/tests/authdtestlist.h +++ b/OSX/authd/tests/authdtestlist.h @@ -3,3 +3,4 @@ ONE_TEST(authd_01_authorizationdb) ONE_TEST(authd_02_basicauthorization) +ONE_TEST(authd_04_executewithprivileges) diff --git a/OSX/authd/tests/authdtests.m b/OSX/authd/tests/authdtests.m index 0e1e034a8..c6c451804 100644 --- a/OSX/authd/tests/authdtests.m +++ b/OSX/authd/tests/authdtests.m @@ -12,15 +12,18 @@ void runRaft(NSString *arguments); int authd_03_uiauthorization(int argc, char *const *argv); +bool getCredentials(void); #define AuthorizationFreeItemSetNull(IS) { AuthorizationItemSet *_is = (IS); \ if (_is) { (IS) = NULL; AuthorizationFreeItemSet(_is); } } #define SAMPLE_RIGHT "com.apple.security.syntheticinput" #define SAMPLE_SHARED_RIGHT "system.preferences" +#define SAMPLE_PASSWORD_RIGHT "system.csfde.requestpassword" + +NSString *correctUsername; +NSString *correctPassword; -#define CORRECT_UNAME "bats" -#define CORRECT_PWD "bats" #define INCORRECT_UNAME "fs;lgp-984-25opsdakflasdg" #define INCORRECT_PWD "654sa65gsqihr6hhsfd'lbo[0q2,m23-odasdf" @@ -31,8 +34,8 @@ #define RAFT_CANCEL @"target.processes()[\"SecurityAgent\"].mainWindow().buttons()[\"Cancel\"].click();quit();" AuthorizationItem validCredentials[] = { - {AGENT_USERNAME, strlen(CORRECT_UNAME), (void *)CORRECT_UNAME, 0}, - {AGENT_PASSWORD, strlen(CORRECT_PWD), (void *)CORRECT_PWD,0} + {AGENT_USERNAME, 0, NULL, 0}, + {AGENT_PASSWORD, 0, NULL, 0} }; AuthorizationItem invalidCredentials[] = { @@ -40,6 +43,29 @@ {AGENT_PASSWORD, strlen(INCORRECT_PWD), (void *)INCORRECT_PWD,0} }; +bool getCredentials() +{ + static dispatch_once_t onceToken = 0; + dispatch_once(&onceToken, ^{ + NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:@"/etc/credentials.plist"]; + correctUsername = dict[@"username"]; + correctPassword = dict[@"password"]; + if (correctUsername) { + validCredentials[0].value = (void *)correctUsername.UTF8String; + if (validCredentials[0].value) { + validCredentials[0].valueLength = strlen(correctUsername.UTF8String); + } + } + if (correctPassword) { + validCredentials[1].value = (void *)correctPassword.UTF8String; + if (validCredentials[1].value) { + validCredentials[1].valueLength = strlen(correctPassword.UTF8String); + } + } + }); + return (correctUsername != nil) && (correctPassword != nil); +} + void runRaft(NSString *arguments) { NSTask *task = [[NSTask alloc] init]; @@ -66,7 +92,10 @@ int authd_01_authorizationdb(int argc, char *const *argv) int authd_02_basicauthorization(int argc, char *const *argv) { - plan_tests(5); + plan_tests(6); + if (!getCredentials()) { + fail("Not able to read credentials for current user!"); + } AuthorizationRef authorizationRef; @@ -96,13 +125,40 @@ int authd_02_basicauthorization(int argc, char *const *argv) ok(status == errAuthorizationSuccess, "Extending authorization rights"); AuthorizationFreeItemSetNull(authorizedRights); - AuthorizationFree(authorizationRef, kAuthorizationFlagDestroyRights); - return 0; + AuthorizationItem pwdExtractItems = {SAMPLE_PASSWORD_RIGHT, 0, NULL, 0}; + AuthorizationRights pwdExtractRight = {1, &pwdExtractItems}; + + // check that non-entitled process cannot extract password from AuthorizationRef + status = AuthorizationCopyRights(authorizationRef, &pwdExtractRight, &environment, kAuthorizationFlagExtendRights, &authorizedRights); + Boolean passwordFound = false; + if (status == errAuthorizationSuccess) { + AuthorizationItemSet *returnedInfo; + status = AuthorizationCopyInfo(authorizationRef, NULL, &returnedInfo); + if (status == errSecSuccess && returnedInfo) { + for (uint32_t index = 0; index < returnedInfo->count; ++index) { + AuthorizationItem item = returnedInfo->items[index]; + if (strncpy((char *)item.name, kAuthorizationEnvironmentPassword, strlen(kAuthorizationEnvironmentPassword)) == 0) { + passwordFound = true; + } + } + AuthorizationFreeItemSetNull(returnedInfo); + } + } + + ok(status == errAuthorizationSuccess && passwordFound == false, "Extracting password from AuthorizationRef"); + AuthorizationFreeItemSetNull(authorizedRights); + + + AuthorizationFree(authorizationRef, kAuthorizationFlagDestroyRights); + return 0; } int authd_03_uiauthorization(int argc, char *const *argv) { plan_tests(3); + if (!getCredentials()) { + fail("Not able to read credentials for current user!"); + } AuthorizationRef authorizationRef; @@ -112,7 +168,7 @@ int authd_03_uiauthorization(int argc, char *const *argv) AuthorizationItem myItems = {SAMPLE_RIGHT, 0, NULL, 0}; AuthorizationRights myRights = {1, &myItems}; - NSString *raftFillValid = [NSString stringWithFormat:RAFT_FILL, CORRECT_UNAME, CORRECT_PWD]; + NSString *raftFillValid = [NSString stringWithFormat:RAFT_FILL, correctUsername.UTF8String, correctPassword.UTF8String]; dispatch_semaphore_t sem = dispatch_semaphore_create(0); /* @@ -153,3 +209,76 @@ int authd_03_uiauthorization(int argc, char *const *argv) return 0; } + +int authd_04_executewithprivileges(int argc, char *const *argv) +{ + const int NUMBER_OF_ITERATIONS = 10; + plan_tests(2 + 4 * NUMBER_OF_ITERATIONS); + + if (!getCredentials()) { + fail("Not able to read credentials for current user!"); + } + + AuthorizationRef authorizationRef; + OSStatus status = AuthorizationCreate(NULL, NULL, kAuthorizationFlagDefaults, &authorizationRef); + ok(status == errAuthorizationSuccess, "AuthorizationRef create"); + + AuthorizationItem myItems = { kAuthorizationRightExecute, 0, NULL, 0}; + AuthorizationRights myRights = {1, &myItems}; + AuthorizationRights *authorizedRights = NULL; + AuthorizationEnvironment environment = {sizeof(validCredentials)/sizeof(AuthorizationItem), validCredentials}; + status = AuthorizationCopyRights(authorizationRef, &myRights, &environment, kAuthorizationFlagExtendRights, &authorizedRights); + ok(status == errAuthorizationSuccess, "Standard authorization"); + AuthorizationFreeItemSetNull(authorizedRights); + + for (int i = 0; i < NUMBER_OF_ITERATIONS; ++i) { + NSString *guid = [[NSProcessInfo processInfo] globallyUniqueString]; + static const char *toolArgv[3]; + NSString *arg = [NSString stringWithFormat:@"%s %@", "/usr/bin/whoami && /bin/echo", guid]; + NSString *expected = [NSString stringWithFormat:@"root\n%@", guid]; + toolArgv[0] = "-c"; + toolArgv[1] = arg.UTF8String; + toolArgv[2] = NULL; + FILE *output = NULL; + + status = AuthorizationExecuteWithPrivileges(authorizationRef, "/bin/zsh", 0, (char *const *)toolArgv, &output); + ok(status == errAuthorizationSuccess, "AuthorizationExecuteWithPrivileges call succeess"); + + if (status != 0) { + break; + } + + char buffer[1024]; + size_t bytesRead = 0; + size_t totalBytesRead = 0; + size_t buffSize = sizeof(buffer); + memset(buffer, 0, buffSize); + while ((bytesRead = fread (buffer, 1, buffSize, output) > 0)) { + totalBytesRead += bytesRead; // overwriting buffer is OK since we are reading just a small amount of data + } + + ok(ferror(output) == 0, "Authorized tool pipe closed did not end with ferror"); + if (ferror(output)) { + // test failed, ferror happened + fclose(output); + return 0; + } + + ok(feof(output), "Authorized tool pipe closed with feof"); + if (!feof(output)) { + // test failed, feof not happened + fclose(output); + return 0; + } + + fclose(output); + if (strncmp(buffer, expected.UTF8String, guid.length) == 0) { + pass("Authorized tool output matches"); + } else { + fail("AuthorizationExecuteWithPrivileges output %s does not match %s", buffer, expected.UTF8String); + } + } + + AuthorizationFree(authorizationRef, kAuthorizationFlagDestroyRights); + return 0; +} diff --git a/OSX/codesign_tests/SignatureEditing.sh b/OSX/codesign_tests/SignatureEditing.sh new file mode 100644 index 000000000..9aadfa9d0 --- /dev/null +++ b/OSX/codesign_tests/SignatureEditing.sh @@ -0,0 +1,86 @@ +#!/bin/sh + +v=${v:-:} + +fails=0 +t=$(mktemp -d /tmp/cs-edit-XXXXXX) + +runTest () { + test=$1 + shift + + echo "[BEGIN] ${test}" + + ${v} echo "> $@" + "$@" > $t/outfile.txt 2>&1 + res=$? + [ $res != 0 ] && res=1 #normalize + + if expr "$test" : "fail" > /dev/null; then + exp=1 + else + exp=0 + fi + + ${v} cat $t/outfile.txt + if [ $res -eq $exp ]; then + echo "[PASS] ${test}" + echo + rm -f $t/outfile.txt + else + echo + cat $t/outfile.txt + echo + echo "[FAIL] ${test}" + echo + fails=$(($fails+1)) + fi +} + +codesign=${codesign:-codesign} + +editTest () { + name="$1" + shift + target="$1" + shift + + rm -f $t/cms + + runTest validate-$name $codesign -v -R="anchor apple" -v "$target" + runTest dump-cms-$name $codesign -d --dump-cms=$t/cms "$target" + runTest edit-nonsense-into-cms-$name $codesign -e "$target" --edit-cms /etc/hosts + runTest fail-nonsense-validation-$name $codesign -v -R="anchor apple" -v "$target" + runTest edit-original-into-cms-$name $codesign -e "$target" --edit-cms $t/cms + runTest success-cms-validation-$name $codesign -v -R="anchor apple" -v "$target" + runTest edit-cat-cms-into-cms-$name $codesign -e "$target" --edit-cms $t/cat.cms + runTest fail-cat-cms-validation-$name $codesign -v -R="anchor apple" -v "$target" + runTest edit-original-again-into-cms-$name $codesign -e "$target" --edit-cms $t/cms + runTest success-cms-validation-again-$name $codesign -v -R="anchor apple" -v "$target" +} + +runTest dump-cat-cms $codesign -d --dump-cms=$t/cat.cms /bin/cat + +runTest prepare-ls cp -R /bin/ls $t/ls +editTest ls $t/ls +runTest prepare-TextEdit cp -R /Applications/TextEdit.app $t/TextEdit.app +editTest TextEdit $t/TextEdit.app + +runTest prepare-codeless cp -R /var/db/gke.bundle $t/gke.bundle +editTest codeless $t/gke.bundle + +runTest codesign-remove-signature $codesign --remove $t/ls +runTest codesign-omit-adhoc $codesign -s - -f --omit-adhoc-flag $t/ls +runTest adhoc-omitted sh -c "$codesign -d -v $t/ls 2>&1| grep -F 'flags=0x0(none)'" + +# cleanup + +if [ $fails != 0 ] ; then + echo "$fails signature edit tests failed" + exit 1 +else + echo "all signature edit tests passed" + rm -rf $t +fi + +exit 0 diff --git a/OSX/config/base.xcconfig b/OSX/config/base.xcconfig index 0e70fa2a7..56529e08d 100644 --- a/OSX/config/base.xcconfig +++ b/OSX/config/base.xcconfig @@ -1,11 +1,10 @@ + SDKROOT = macosx.internal ARCHS[sdk=macosx*] = $(ARCHS_STANDARD_32_64_BIT) CODE_SIGN_IDENTITY = -; GCC_VERSION = com.apple.compilers.llvm.clang.1_0 DEBUG_INFORMATION_FORMAT = dwarf-with-dsym -CURRENT_PROJECT_VERSION = $(RC_ProjectSourceVersion) -VERSIONING_SYSTEM = apple-generic; DEAD_CODE_STRIPPING = YES diff --git a/OSX/config/lib.xcconfig b/OSX/config/lib.xcconfig index fdb549027..7c298b95c 100644 --- a/OSX/config/lib.xcconfig +++ b/OSX/config/lib.xcconfig @@ -5,11 +5,14 @@ EXECUTABLE_PREFIX = CODE_SIGN_IDENTITY = +USE_HEADERMAP = YES + HEADER_SEARCH_PATHS = $(PROJECT_DIR)/../ $(PROJECT_DIR)/../include $(BUILT_PRODUCTS_DIR)/derived_src $(BUILT_PRODUCTS_DIR) $(PROJECT_DIR)/lib $(PROJECT_DIR)/../utilities $(inherited) +SYSTEM_HEADER_SEARCH_PATHS = $(PROJECT_DIR)/../../header_symlinks/macOS/ $(PROJECT_DIR)/../../header_symlinks/ SKIP_INSTALL = YES -ALWAYS_SEARCH_USER_PATHS = YES +ALWAYS_SEARCH_USER_PATHS = NO GCC_C_LANGUAGE_STANDARD = gnu99 diff --git a/OSX/config/security_framework_macos.xcconfig b/OSX/config/security_framework_macos.xcconfig index 2e878c706..6aa60fd87 100644 --- a/OSX/config/security_framework_macos.xcconfig +++ b/OSX/config/security_framework_macos.xcconfig @@ -1,4 +1,5 @@ #include "OSX/config/security_macos.xcconfig" +#include "xcconfig/security_framework.xcconfig" PRODUCT_NAME = Security PRODUCT_BUNDLE_IDENTIFIER = com.apple.security @@ -11,16 +12,25 @@ DYLIB_CURRENT_VERSION = $(CURRENT_PROJECT_VERSION) MODULEMAP_FILE = Modules/Security.macOS.modulemap DEFINES_MODULE = YES -EXPORTED_SYMBOLS_FILE = $(BUILT_PRODUCTS_DIR)/$(PRODUCT_NAME).$(CURRENT_ARCH).exp +EXPORTED_SYMBOLS_FILE = $(BUILT_PRODUCTS_DIR)/$(PRODUCT_NAME).exp ORDER_FILE = OSX/lib/Security.order INFOPLIST_FILE = OSX/lib/Info-Security.plist INSTALL_PATH = $(SYSTEM_LIBRARY_DIR)/Frameworks -OTHER_LDFLAGS = -laks -lCrashReporterClient -Wl,-upward_framework,Foundation +ASAN_EXTRA_LDFLAGS_YES = -Wl,-no_warn_inits +OTHER_LDFLAGS = -laks -lCrashReporterClient -Wl,-upward_framework,Foundation -Wl,-no_inits $(ASAN_EXTRA_LDFLAGS_$(ENABLE_ADDRESS_SANITIZER)) SECTORDER_FLAGS = -order_file_statistics APPLY_RULES_IN_COPY_FILES = NO -// Not entirely sure what this is for, but, okay. -INSTALLHDRS_SCRIPT_PHASE = YES +// Adding things here is against the spirit of TAPI. If something is in the framework, it should be in the framework headers. +// Don't add things. +OTHER_TAPI_FLAGS_TRUST = -extra-private-header $(PROJECT_DIR)/OSX/trustd/macOS/SecTrustOSXEntryPoints.h -extra-private-header $(PROJECT_DIR)/OSX/sec/Security/SecCertificateInternal.h + +OTHER_TAPI_FLAGS_USR_LIB_HEADERS = -extra-private-header $(PROJECT_DIR)/OSX/utilities/debugging.h +OTHER_TAPI_FLAGS_HACKS = -exclude-public-header $(BUILT_PRODUCTS_DIR)/Security.framework/Versions/A/Headers/AuthorizationPlugin.h -extra-public-header $(PROJECT_DIR)/OSX/macos_tapi_hacks.h -extra-public-header $(PROJECT_DIR)/OSX/sec/Security/SecItemShim.h -D SECURITY_PROJECT_TAPI_HACKS=1 + +OTHER_TAPI_FLAGS = $(inherited) $(OTHER_TAPI_FLAGS_SECURITY_FRAMEWORK) -I$(PROJECT_DIR)/header_symlinks/ $(OTHER_TAPI_FLAGS_TRUST) $(OTHER_TAPI_FLAGS_USR_LIB_HEADERS) $(OTHER_TAPI_FLAGS_HACKS) + +IS_ZIPPERED = YES diff --git a/OSX/config/security_macos.xcconfig b/OSX/config/security_macos.xcconfig index 73f31cacc..58ed08ab3 100644 --- a/OSX/config/security_macos.xcconfig +++ b/OSX/config/security_macos.xcconfig @@ -1,20 +1,18 @@ #include "OSX/config/base.xcconfig" +#include "xcconfig/Version.xcconfig" GCC_PRECOMPILE_PREFIX_HEADER = YES ALWAYS_SEARCH_USER_PATHS = NO -HEADER_SEARCH_PATHS = $(inherited) $(PROJECT_DIR)/include $(PROJECT_DIR)/sec/ProjectHeaders $(PROJECT_DIR)/utilities +HEADER_SEARCH_PATHS = $(inherited) $(PROJECT_DIR)/include $(PROJECT_DIR)/utilities LIBRARY_SEARCH_PATHS = $(inherited) /usr/lib/system STRIP_INSTALLED_PRODUCT = YES DEPLOYMENT_POSTPROCESSING = NO GCC_C_LANGUAGE_STANDARD = gnu99 -SUPPORTED_PLATFORMS = macOS - -// Don't use the inherited cflags; they set SEC_IOS_ON_OSX -GCC_PREPROCESSOR_DEFINITIONS = +SUPPORTED_PLATFORMS = macosx GCC_TREAT_WARNINGS_AS_ERRORS = YES GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO diff --git a/OSX/lib/Security.order b/OSX/lib/Security.order index 8ee5844fb..2a43b77f6 100644 --- a/OSX/lib/Security.order +++ b/OSX/lib/Security.order @@ -1940,7 +1940,6 @@ _SSLProcessServerHello _sslVerifyProtVersion _FindCipherSpec _sslVerifySelectedCipher -_SSLReallocBuffer _SSLProcessCertificate _sslVerifyCertChain _sslPubKeyFromCert diff --git a/OSX/lib/en.lproj/authorization.buttons.strings b/OSX/lib/en.lproj/authorization.buttons.strings index da9a0ee6d..1871c226a 100644 --- a/OSX/lib/en.lproj/authorization.buttons.strings +++ b/OSX/lib/en.lproj/authorization.buttons.strings @@ -142,3 +142,4 @@ "com.apple.security.sudo" = "Allow"; +"com.apple.configurationprofiles.userenrollment.install" = "Enroll"; diff --git a/OSX/lib/en.lproj/authorization.dfr.prompts-BBBAA77A32-C4EBFEA440.strings b/OSX/lib/en.lproj/authorization.dfr.prompts-BBBAA77A32-C4EBFEA440.strings deleted file mode 100644 index 3e047aa11..000000000 --- a/OSX/lib/en.lproj/authorization.dfr.prompts-BBBAA77A32-C4EBFEA440.strings +++ /dev/null @@ -1,160 +0,0 @@ -"system.preferences.accounts" = "Touch ID to Unlock Users & Groups Preferences."; - -"com.apple.SoftwareUpdate.scan" = "Touch ID to Check for New Apple-provided Software."; - -"system.preferences.datetime" = "Touch ID to Unlock the Date & Time Preferences."; - -"system.identity.write.credential" = "Touch ID to Update the Authentication Credentials."; - -"com.apple.appserver.privilege.admin" = "Touch ID to Modify the Application Server Settings."; - -"system.privilege.taskport.safe" = "Touch ID to Take Control of Another Process."; - -"com.apple.DiskManagement.internal." = "Touch ID to Modify the Selected Disk."; - -"system.print.operator" = "Touch ID to Use the Printer."; - -"com.apple.AOSNotification.FindMyMac.modify" = "Touch ID to Make Changes to Find My Mac."; - -"system.printingmanager" = "Touch ID to Print to a Locked Printer."; - -"com.apple.DiskManagement.reserveKEK" = "Touch ID to Modify an Encrypted Disk."; - -"system.services.systemconfiguration.network" = "Touch ID to Modify the System Network Configuration."; - -"sys.openfile." = "Touch ID to Open the Chosen File."; - -"com.apple.lldb.LaunchUsingXPC" = "Touch ID to Take Control of a Root Process."; - -"com.apple.OpenScripting.additions.send" = "Touch ID to Send Restricted Scripting Addition Commands to Other Applications."; - -"com.apple.library-repair" = "Touch ID to Repair Your Photo Library."; - -"com.apple.XType.fontmover.restore" = "Touch ID to Restore the Default System Fonts."; - -"system.csfde.requestpassword" = "Touch ID to Unlock Your Disk."; - -"com.apple.Safari.show-passwords" = "Touch ID to Show Passwords."; - -"com.apple.Safari.show-credit-card-numbers" = "Touch ID to Show Credit Card Numbers."; - -"com.apple.Safari.install-ephemeral-extensions" = "Touch ID to Install an Extension."; - -"com.apple.Safari.allow-apple-events-to-run-javascript" = "Touch ID to Allow Apple Events to Run JavaScript on Web Pages."; - -"com.apple.Safari.allow-javascript-in-smart-search-field" = "Touch ID to Allow JavaScript to be Used in the Smart Search Field."; - -"system.sharepoints." = "Touch ID to Modify Sharing 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.standard-user" = "Touch ID to Install Apple-provided software."; - -"com.apple.security.assessment.update" = "Touch ID to Install an App from an Unidentified Developer."; - -"com.apple.docset.install" = "Touch ID to Update the Developer Documentation."; - -"com.apple.Safari.parental-controls" = "Touch ID to Modify the Parental Controls Settings for Safari."; - -"com.apple.Safari.allow-unsigned-app-extensions" = "Touch ID to Allow Unsigned Extensions."; - -"com.apple.ServiceManagement.blesshelper" = "Touch ID to Install a New Helper Tool."; - -"system.device.dvd.setregion.initial" = "Touch ID to Set the DVD Region Code for the First Time."; - -"system.preferences.network" = "Touch ID to Unlock the Network Preferences."; - -"system.identity.write." = "Touch ID to Update the Set of Local Users."; - -"com.apple.opendirectoryd.linkidentity" = "Touch ID to Modify Your User Account."; - -"com.apple.trust-settings.user" = "Touch ID to Change Your Certificate Trust Settings."; - -"system.preferences.printing" = "Touch ID to Unlock the Printers & Scanners Preferences."; - -"system.hdd.smart" = "Touch ID to Modify the Diagnostic Settings for Your Hard Drive."; - -"system.print.admin" = "Touch ID to Modify the Printer Settings."; - -"system.preferences.accessibility" = "Touch ID to Unlock Accessibility Preferences."; - -"com.apple.activitymonitor.kill" = "Touch ID to Quit the Selected Process."; - -"system.burn" = "Touch ID to Burn a Disc."; - -"system.preferences.sharing" = "Touch ID to Unlock the Sharing Preferences."; - -"system.preferences.parental-controls" = "Touch ID to Unlock Parental Controls Preferences."; - -"system.preferences.security" = "Touch ID to Unlock Security & Privacy Preferences."; - -"system.preferences.startupdisk" = "Touch ID to Unlock the Startup Disk Preferences."; - -"com.apple.ServiceManagement.daemons.modify" = "Touch ID to Add a New Helper Tool."; - -"com.apple.DiskManagement." = "Touch ID to Modify the Selected Disk."; - -"com.apple.trust-settings.admin" = "Touch ID to Change the System Certificate Trust Settings."; - -"system.identity.write.self" = "Touch ID to Update Your Authentication Credentials."; - -"system.install.app-store-software" = "Touch ID to Install Software."; - -"system.install.app-store-software.standard-user" = "Touch ID to Install Software."; - -"system.preferences.version-cue" = "Touch ID to Modify the Version Cue Preferences."; - -"system.preferences" = "Touch ID to Modify Your System Settings."; - -"com.apple.SoftwareUpdate.modify-settings" = "Touch ID to Unlock the App Store preferences."; - -"com.apple.uninstalld.uninstall" = "Touch ID to Delete an Application."; - -"system.privilege.taskport" = "Touch ID to Take Control of Another Process."; - -"system.install.software" = "Touch ID to Install New Software."; - -"system.preferences.security.remotepair" = "Touch ID to Pair the Remote."; - -"com.apple.XType.fontmover.remove" = "Touch ID to Remove Existing System Fonts."; - -"system.global-login-items." = "Touch ID to Add a Login Item."; - -"com.apple.server.admin.streaming" = "Touch ID to Modify the QuickTime Streaming Server Settings."; - -"system.preferences.softwareupdate" = "Touch ID to Unlock the App Store preferences."; - -"system.keychain.modify" = "Touch ID to Modify the System Keychain."; - -"com.apple.XType.fontmover.install" = "Touch ID to Install New System Fonts."; - -"system.services.directory.configure" = "Touch ID to Modify the Directory Services Configuration."; - -"system.preferences.timemachine" = "Touch ID to Unlock the Time Machine Preferences."; - -"com.apple.appserver.privilege.user" = "Touch ID to Modify your Application Server Settings."; - -"system.privilege.taskport.debug" = "Touch ID to Take Control of Another Process for Debugging to Continue."; - -"com.apple.container-repair" = "Touch ID to Repair Your Library to Run Applications."; - -"com.apple.pf.rule" = "Touch ID to Modify Firewall Rules."; - -"com.apple.AOSNotification.FindMyMac.remove" = "Touch ID to Turn Off Find My Mac."; - -"com.apple.iBooksX.ParentalControl" = "Touch ID to Unlock Your Parental Controls Preferences."; - -"system.services.networkextension.vpn" = "Touch ID to Modify the VPN Configuration."; - -"system.services.networkextension.filtering" = "Touch ID to Modify the Content Filtering Configuration."; - -"com.apple.iCloud.passwordReset" = "Touch ID to Reset Your Apple ID Password."; - -"system.preferences.continuity" = "Touch ID to Unlock the Touch ID Preferences."; - -"com.apple.ctkbind.admin" = "Touch ID to Pair the Current User With the SmartCard Identity."; - -"com.apple.security.sudo" = "Touch ID to Execute a command as administrator."; - diff --git a/OSX/lib/en.lproj/authorization.dfr.prompts.strings b/OSX/lib/en.lproj/authorization.dfr.prompts.strings new file mode 100644 index 000000000..2ee028fd0 --- /dev/null +++ b/OSX/lib/en.lproj/authorization.dfr.prompts.strings @@ -0,0 +1,169 @@ +"system.preferences.accounts" = "Touch ID to Unlock Users & Groups Preferences."; + +"com.apple.SoftwareUpdate.scan" = "Touch ID to Check for New Apple-provided Software."; + +"system.preferences.datetime" = "Touch ID to Unlock the Date & Time Preferences."; + +"system.identity.write.credential" = "Touch ID to Update the Authentication Credentials."; + +"com.apple.appserver.privilege.admin" = "Touch ID to Modify the Application Server Settings."; + +"system.privilege.taskport.safe" = "Touch ID to Take Control of Another Process."; + +"com.apple.DiskManagement.internal." = "Touch ID to Modify the Selected Disk."; + +"system.print.operator" = "Touch ID to Use the Printer."; + +"com.apple.AOSNotification.FindMyMac.modify" = "Touch ID to Make Changes to Find My Mac."; + +"system.printingmanager" = "Touch ID to Print to a Locked Printer."; + +"com.apple.DiskManagement.reserveKEK" = "Touch ID to Modify an Encrypted Disk."; + +"system.services.systemconfiguration.network" = "Touch ID to Modify the System Network Configuration."; + +"sys.openfile." = "Touch ID to Open the Chosen File."; + +"com.apple.lldb.LaunchUsingXPC" = "Touch ID to Take Control of a Root Process."; + +"com.apple.OpenScripting.additions.send" = "Touch ID to Send Restricted Scripting Addition Commands to Other Applications."; + +"com.apple.library-repair" = "Touch ID to Repair Your Photo Library."; + +"com.apple.XType.fontmover.restore" = "Touch ID to Restore the Default System Fonts."; + +"system.csfde.requestpassword" = "Touch ID to Unlock Your Disk."; + +"com.apple.Safari.show-passwords" = "Touch ID to Show Passwords."; + +"com.apple.Safari.show-credit-card-numbers" = "Touch ID to Show Credit Card Numbers."; + +"com.apple.Safari.install-ephemeral-extensions" = "Touch ID to Install an Extension."; + +"com.apple.Safari.allow-apple-events-to-run-javascript" = "Touch ID to Allow Apple Events to Run JavaScript on Web Pages."; + +"com.apple.Safari.allow-javascript-in-smart-search-field" = "Touch ID to Allow JavaScript to be Used in the Smart Search Field."; + +"system.sharepoints." = "Touch ID to Modify Sharing 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.standard-user" = "Touch ID to Install Apple-provided software."; + +"com.apple.security.assessment.update" = "Touch ID to Install an App from an Unidentified Developer."; + +"com.apple.docset.install" = "Touch ID to Update the Developer Documentation."; + +"com.apple.Safari.parental-controls" = "Touch ID to Modify the Parental Controls Settings for Safari."; + +"com.apple.Safari.allow-unsigned-app-extensions" = "Touch ID to Allow Unsigned Extensions."; + +"com.apple.ServiceManagement.blesshelper" = "Touch ID to Install a New Helper Tool."; + +"system.device.dvd.setregion.initial" = "Touch ID to Set the DVD Region Code for the First Time."; + +"system.preferences.network" = "Touch ID to Unlock the Network Preferences."; + +"system.identity.write." = "Touch ID to Update the Set of Local Users."; + +"com.apple.opendirectoryd.linkidentity" = "Touch ID to Modify Your User Account."; + +"com.apple.trust-settings.user" = "Touch ID to Change Your Certificate Trust Settings."; + +"system.preferences.printing" = "Touch ID to Unlock the Printers & Scanners Preferences."; + +"system.hdd.smart" = "Touch ID to Modify the Diagnostic Settings for Your Hard Drive."; + +"system.print.admin" = "Touch ID to Modify the Printer Settings."; + +"system.preferences.accessibility" = "Touch ID to Unlock Accessibility Preferences."; + +"com.apple.activitymonitor.kill" = "Touch ID to Quit the Selected Process."; + +"system.burn" = "Touch ID to Burn a Disc."; + +"system.preferences.sharing" = "Touch ID to Unlock the Sharing Preferences."; + +"system.preferences.parental-controls" = "Touch ID to Unlock Parental Controls Preferences."; + +"system.preferences.security" = "Touch ID to Unlock Security & Privacy Preferences."; + +"system.preferences.startupdisk" = "Touch ID to Unlock the Startup Disk Preferences."; + +"com.apple.ServiceManagement.daemons.modify" = "Touch ID to Add a New Helper Tool."; + +"com.apple.DiskManagement." = "Touch ID to Modify the Selected Disk."; + +"com.apple.trust-settings.admin" = "Touch ID to Change the System Certificate Trust Settings."; + +"system.identity.write.self" = "Touch ID to Update Your Authentication Credentials."; + +"system.install.app-store-software" = "Touch ID to Install Software."; + +"system.install.app-store-software.standard-user" = "Touch ID to Install Software."; + +"system.preferences.version-cue" = "Touch ID to Modify the Version Cue Preferences."; + +"system.preferences" = "Touch ID to Modify Your System Settings."; + +"com.apple.SoftwareUpdate.modify-settings" = "Touch ID to Unlock the Software Update preferences."; + +"com.apple.uninstalld.uninstall" = "Touch ID to Delete an Application."; + +"system.privilege.taskport" = "Touch ID to Take Control of Another Process."; + +"system.install.software" = "Touch ID to Install New Software."; + +"system.preferences.security.remotepair" = "Touch ID to Pair the Remote."; + +"com.apple.XType.fontmover.remove" = "Touch ID to Remove Existing System Fonts."; + +"system.global-login-items." = "Touch ID to Add a Login Item."; + +"com.apple.server.admin.streaming" = "Touch ID to Modify the QuickTime Streaming Server Settings."; + +"system.preferences.softwareupdate" = "Touch ID to Unlock the Software Update preferences."; + +"system.keychain.modify" = "Touch ID to Modify the System Keychain."; + +"com.apple.XType.fontmover.install" = "Touch ID to Install New System Fonts."; + +"system.services.directory.configure" = "Touch ID to Modify the Directory Services Configuration."; + +"system.preferences.timemachine" = "Touch ID to Unlock the Time Machine Preferences."; + +"com.apple.appserver.privilege.user" = "Touch ID to Modify your Application Server Settings."; + +"system.privilege.taskport.debug" = "Touch ID to Take Control of Another Process for Debugging to Continue."; + +"com.apple.container-repair" = "Touch ID to Repair Your Library to Run Applications."; + +"com.apple.pf.rule" = "Touch ID to Modify Firewall Rules."; + +"com.apple.AOSNotification.FindMyMac.remove" = "Touch ID to Turn Off Find My Mac."; + +"com.apple.iBooksX.ParentalControl" = "Touch ID to Unlock Your Parental Controls Preferences."; + +"system.services.networkextension.vpn" = "Touch ID to Modify the VPN Configuration."; + +"system.services.networkextension.filtering" = "Touch ID to Modify the Content Filtering Configuration."; + +"com.apple.iCloud.passwordReset" = "Touch ID to Reset Your Apple ID Password."; + +"system.preferences.continuity" = "Touch ID to Unlock the Touch ID Preferences."; + +"com.apple.ctkbind.admin" = "Touch ID to Pair the Current User With the SmartCard Identity."; + +"com.apple.security.sudo" = "Touch ID to Execute a command as administrator."; + +"com.apple.configurationprofiles.userprofile.trustcert" = "Touch ID to Trust a Certificate from a User Configuration Profile."; + +"com.apple.app-sandbox.create-symlink" = "Touch ID to Install Symlinks into /usr/local."; + +"com.apple.app-sandbox.set-attributes" = "Touch ID to Change the Permissions of a Privileged File."; + +"com.apple.app-sandbox.replace-file" = "Touch ID to Save a File in a Privileged Location."; + +"com.apple.applepay.reset" = "Touch ID to Reset Apple Pay and add card."; diff --git a/OSX/lib/en.lproj/authorization.prompts.strings b/OSX/lib/en.lproj/authorization.prompts.strings index 29b23439d..7986719b2 100644 --- a/OSX/lib/en.lproj/authorization.prompts.strings +++ b/OSX/lib/en.lproj/authorization.prompts.strings @@ -108,7 +108,7 @@ "system.preferences" = "__APPNAME__ is trying to modify your system settings."; -"com.apple.SoftwareUpdate.modify-settings" = "__APPNAME__ is trying to unlock the App Store preferences."; +"com.apple.SoftwareUpdate.modify-settings" = "__APPNAME__ is trying to unlock the Software Update preferences."; "com.apple.uninstalld.uninstall" = "__APPNAME__ is trying to delete an application."; @@ -124,7 +124,7 @@ "com.apple.server.admin.streaming" = "__APPNAME__ is trying to modify the QuickTime Streaming Server settings."; -"system.preferences.softwareupdate" = "__APPNAME__ is trying to unlock the App Store preferences."; +"system.preferences.softwareupdate" = "__APPNAME__ is trying to unlock the Software Update preferences."; "system.keychain.modify" = "__APPNAME__ is trying to modify the system keychain."; @@ -156,8 +156,20 @@ "com.apple.ctkbind.admin" = "__APPNAME__ is trying to pair the current user with the SmartCard identity."; -"com.apple.builtin.sc-kc-new-passphrase" = "The system will now create a keychain to store your secrets. Your smart card will automatically unlock it. Please choose a password that can unlock it separately. You may use your account password or pick another one. For security reasons, do not use your smart card PIN or similar text."; +"com.apple.builtin.sc-kc-new-passphrase" = "The system will now create a keychain to store your secrets. Your SmartCard will automatically unlock it. Please choose a password that can unlock it separately. You may use your account password or pick another one. For security reasons, do not use your SmartCard PIN or similar text."; "com.apple.security.sudo" = "__APPNAME__ is trying to execute a command as administrator."; "com.apple.configurationprofiles.userprofile.trustcert" = "__APPNAME__ is trying to trust a certificate from a user configuration profile."; + +"com.apple.app-sandbox.create-symlink" = "__APPNAME__ wants to install symlinks in /usr/local."; + +"com.apple.app-sandbox.set-attributes" = "__APPNAME__ wants to change permissions of a privileged file."; + +"com.apple.app-sandbox.replace-file" = "__APPNAME__ wants to save a file in a privileged location."; + +"com.apple.applepay.reset" = "__APPNAME__ is trying to reset Apple Pay and add card."; + +"com.apple.configurationprofiles.userenrollment.install" = "__APPNAME__ is trying to enroll you in a remote management (MDM) service."; + +"com.apple.system-extensions.admin" = "__APPNAME__ is trying to modify a System Extension."; diff --git a/OSX/lib/framework.sb b/OSX/lib/framework.sb index 7fa76f2d6..e37bf7c47 100644 --- a/OSX/lib/framework.sb +++ b/OSX/lib/framework.sb @@ -1,7 +1,11 @@ ;; 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.libxpc")) -(allow mach-lookup (global-name "com.apple.CoreAuthentication.agent.libxpc")) +(allow mach-lookup (global-name "com.apple.CoreAuthentication.daemon")) +(allow mach-lookup (global-name "com.apple.CoreAuthentication.agent")) ;; allow clients to communicate with ctkd (allow mach-lookup (global-name "com.apple.ctkd.token-client")) + +;; On internal builds, allow clients to read the AMFITrustedKeys NVRAM variable +(with-filter (system-attribute apple-internal) + (allow nvram-get (nvram-variable "AMFITrustedKeys"))) diff --git a/OSX/lib/generateErrStrings.pl b/OSX/lib/generateErrStrings.pl index 509bb0885..9f9e06143 100644 --- a/OSX/lib/generateErrStrings.pl +++ b/OSX/lib/generateErrStrings.pl @@ -72,7 +72,7 @@ # CSSM_CSSM_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT + 0x10, # CSSMERR_CSSM_SCOPE_NOT_SUPPORTED = CSSM_CSSM_BASE_CSSM_ERROR + 1, # -# Style A has the comment after the comment. Style has the comment before the value, +# Style A has the comment after the value. Style has the comment before the value, # and Style C has no comment. In cases where both Style A and B apply, the # comment at the end of the line is used. # @@ -92,7 +92,7 @@ # # The English versions of the error messages can be seen with: # -# cat /System/Library/Frameworks/Security.framework/Resources/English.lproj/SecErrorMessages.strings +# cat /System/Library/Frameworks/Security.framework/Resources/en.lproj/SecErrorMessages.strings # # find -H -X -x . -name "*.h" -print0 2>/dev/null | xargs -0 grep -ri err # ----------------------------------------------------------------------------------- @@ -110,19 +110,15 @@ $GENDEBUGSTRINGS=$ARGV[0]; # If "YES", include all strings & don't localize $TMPDIR=$ARGV[1]; # temporary directory for program compile, link, run $TARGETSTR=$ARGV[2]; # path of .strings file, e.g. - # ${DERIVED_SRC}/English.lproj/SecErrorMessages.strings + # ${DERIVED_SRC}/en.lproj/SecErrorMessages.strings @INPUTFILES=@ARGV[3 .. 9999]; # list of input files $#INPUTFILES = $#ARGV - 3; # truncate to actual number of files print "gend: $GENDEBUGSTRINGS, tmpdir: $TMPDIR, targetstr: $TARGETSTR\n"; -$PROGNAME="${TMPDIR}/generateErrStrings.mm"; -open PROGRAM,"> $PROGNAME" or die "can't open $PROGNAME: $!"; -select PROGRAM; - -printAdditionalIncludes(); -printInputIncludes(); -printMainProgram(); +open STRINGFILE, "> $TARGETSTR" or die "can't open $TARGETSTR: $!"; +select STRINGFILE; +binmode STRINGFILE, ":encoding(UTF-16)"; # ----------------------------------------------------------------------------------- # Parse error headers and build array of all relevant lines @@ -132,12 +128,6 @@ close(ERR); # ----------------------------------------------------------------------------------- -printTrailer(); -select STDOUT; -close PROGRAM; - -compileLinkAndRun(); - # 4: Done! exit; @@ -147,53 +137,55 @@ sub processInput { - # 3: Read input, process each line, output it. - while ( $line = ) - { - ($enum) = ($line =~ /\n\s*(?:enum|CF_ENUM\(OSStatus\))\s*{\s*([^}]*)};/); - while ($enum ne '') #basic filter for badly formed enums - { - #Drop leading whitespace - $enum =~ s/^\s+//; - # print "A:", $enum,"\n"; - ($leadingcomment) = ($enum =~ m%^(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|(//.*)%); - if ($leadingcomment ne '') - { - $enum = substr($enum, length($leadingcomment)); - $leadingcomment = substr($leadingcomment, 2); # drop leading "/*" - $leadingcomment = substr($leadingcomment, 0, -2); # drop trailing "*/" - $leadingcomment = cleanupComment($leadingcomment); - } - next if ($enum eq ''); #basic filter for badly formed enums - - # Check for C++ style comments at start of line - if ($enum =~ /\s*(\/\/)/) - { - #Drop everything before the end of line - $enum =~ s/[^\n]*[\n]*//; - next; - } - ($identifier) = ($enum =~ /\s*([_A-Za-z][_A-Za-z0-9]*)/); - -# print "identifier: ", $identifier,"\n" if ($identifier ne ''); - - #Drop everything before the comma, end of line or trailing comment + # 3: Read input, process each line, output it. + while ( $line = ) + { + ($enum) = ($line =~ /\n\s*(?:enum|CF_ENUM\(OSStatus\))\s*{\s*([^}]*)};/); + while ($enum ne '') #basic filter for badly formed enums + { + #Drop leading whitespace + $enum =~ s/^\s+//; + + ($leadingcomment) = ($enum =~ m%^(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|(//.*)%); + if ($leadingcomment ne '') + { + $enum = substr($enum, length($leadingcomment)); + $leadingcomment = substr($leadingcomment, 2); # drop leading "/*" + $leadingcomment = substr($leadingcomment, 0, -2); # drop trailing "*/" + $leadingcomment = cleanupComment($leadingcomment); + } + next if ($enum eq ''); #basic filter for badly formed enums + + # Check for C++ style comments at start of line + if ($enum =~ /\s*(\/\/)/) + { + #Drop everything before the end of line + $enum =~ s/[^\n]*[\n]*//; + next; + } + ($identifier) = ($enum =~ /\s*([_A-Za-z][_A-Za-z0-9]*)/); + #print "identifier: ", $identifier,"\n" if ($identifier ne ''); + + ($value) = ($enum =~ /\s*[_A-Za-z][_A-Za-z0-9]*\s*=\s*(-?[0-9]*),/); + #print "value: ", $value,"\n" if ($value ne ''); + + #Drop everything before the comma, end of line or trailing comment $enum =~ s/[^,]*(,|\n|(\/\*))//; - - # Now look for trailing comment. We only consider them - # trailing if they come before the end of the line - ($trailingcomment) = ($enum =~ /^[ \t]*\/\*((.)*)?\*\//); - $trailingcomment = cleanupComment($trailingcomment); - - #Drop everything before the end of line - $enum =~ s/[^\n]*[\n]*//; - # print "B:", $enum,"\n"; - # print "lc:$leadingcomment, id:$identifier, tc:$trailingcomment\n"; - # print "===========================================\n"; - - writecomment($leadingcomment, $identifier, $trailingcomment); - } - } + + # Now look for trailing comment. We only consider them + # trailing if they come before the end of the line + ($trailingcomment) = ($enum =~ /^[ \t]*\/\*((.)*)?\*\//); + $trailingcomment = cleanupComment($trailingcomment); + + #Drop everything before the end of line + $enum =~ s/[^\n]*[\n]*//; + + #print "lc:$leadingcomment, id:$identifier, v:$value, tc:$trailingcomment\n"; + #print "===========================================\n"; + + writecomment($leadingcomment, $identifier, $trailingcomment, $value); + } + } } sub writecomment @@ -205,7 +197,7 @@ sub writecomment # tmp << "/* errAuthorizationSuccess */\n\"" << errAuthorizationSuccess # << "\" = \"The operation completed successfully.\"\n" << endl; - my($mylc,$myid,$mytc) = @_; + my($mylc,$myid,$mytc,$myvalue) = @_; if ($myid =~ /(CSSM_ERRCODE|CSSMERR_|errSec|errCS|errAuth|errSSL)[_A-Za-z][_A-Za-z0-9]*/) { $errormessage = ''; @@ -218,89 +210,13 @@ sub writecomment if ($errormessage ne '') { - print "\ttmp << \"/* ", $myid, " */\\n\\\"\" << "; - print $myid, " << \"\\\" = \\\""; - print $errormessage, "\\\";\\n\" << endl;\n"; + print "/* ", $myid, " */\n\""; + print $myvalue, "\" = \""; + print $errormessage, "\";\n\n"; } } }; - -sub printAdditionalIncludes -{ - #This uses the "here" construct to dump out lines verbatim - print <<"AdditionalIncludes"; - -#include -#include -#include -#include - -using namespace std; -AdditionalIncludes -} - -sub printInputIncludes -{ - #Now "#include" each of the input files - print "\n#include \"$_\"" foreach @INPUTFILES; - print "\n"; -} - -sub printMainProgram -{ - #Output the main part of the program using the "here" construct - print <<"MAINPROGRAM"; - -void writeStrings(const char *stringsFileName); -void createStringsTemp(); - -int main (int argc, char * const argv[]) -{ - const char *stringsFileName = NULL; - - if (argc == 2) - stringsFileName = argv[1]; - else - if (argc == 1) - stringsFileName = "SecErrorMessages.strings"; - else - return -1; - - cout << "Strings file to create: " << stringsFileName << endl; - createStringsTemp(); - writeStrings(stringsFileName); -} - -void writeStrings(const char *stringsFileName) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSFileHandle *fh = [NSFileHandle fileHandleForReadingAtPath:@"generateErrStrings.tmp"]; - NSData *rawstrings = [fh readDataToEndOfFile]; - UInt32 encoding = CFStringConvertEncodingToNSStringEncoding (kCFStringEncodingUTF8); - NSString *instring = [[NSString alloc] initWithData:rawstrings encoding:(NSStringEncoding)encoding]; - - if (instring) - { - NSString *path = [NSString stringWithUTF8String:stringsFileName]; - NSFileManager *fm = [NSFileManager defaultManager]; - if ([fm fileExistsAtPath:path]) - [fm removeItemAtPath:path error:NULL]; - BOOL bx = [fm createFileAtPath:path contents:nil attributes:nil]; - NSFileHandle *fs = [NSFileHandle fileHandleForWritingAtPath:path]; - [fs writeData:[instring dataUsingEncoding:NSUnicodeStringEncoding]]; - } - - [pool release]; -} - -void createStringsTemp() -{ - ofstream tmp("generateErrStrings.tmp") ; - -MAINPROGRAM -} - sub cleanupComment { my $comment = shift @_; @@ -310,33 +226,8 @@ sub cleanupComment $comment =~ s/\s\s+/ /g; # Squeeze multiple spaces to one $comment =~ s/^\s+//; # Drop leading whitespace $comment =~ s/\s+$//; # Drop trailing whitespace - $comment =~ s/[\"]/\\\\\\"/g; # Replace double quotes with \" (backslash is sextupled to make it through regex and printf) + $comment =~ s/[\"]/\\\"/g; # Replace double quotes with \" (backslash is sextupled to make it through regex and printf) } # print "B:",$comment,"\n"; $comment; -} - -sub printTrailer -{ - print " tmp.close();\n"; - print "}\n"; } - -sub compileLinkAndRun -{ - $status = system( <<"MAINPROGRAM"); -(cd ${TMPDIR} ; /usr/bin/cc -x objective-c++ -pipe -Wno-trigraphs -fpascal-strings -fasm-blocks -g -O0 -Wreturn-type -fmessage-length=0 -F$ENV{'BUILT_PRODUCTS_DIR'} -I$ENV{'BUILT_PRODUCTS_DIR'}/SecurityPieces/Headers -I$ENV{'BUILT_PRODUCTS_DIR'}/SecurityPieces/PrivateHeaders -c generateErrStrings.mm -o generateErrStrings.o) -MAINPROGRAM - die "$compile exited funny: $?" unless $status == 0; - - $status = system( <<"LINKERSTEP"); -(cd ${TMPDIR} ; /usr/bin/clang++ -o generateErrStrings generateErrStrings.o -framework Foundation ) -LINKERSTEP - die "$linker exited funny: $?" unless $status == 0; - - $status = system( <<"RUNSTEP"); -(cd ${TMPDIR} ; ./generateErrStrings $TARGETSTR ) -RUNSTEP - die "$built program exited funny: $?" unless $status == 0; -} - diff --git a/OSX/libsecurity_apple_csp/lib/AppleCSP.cpp b/OSX/libsecurity_apple_csp/lib/AppleCSP.cpp index db9a4bee5..1a32f514f 100644 --- a/OSX/libsecurity_apple_csp/lib/AppleCSP.cpp +++ b/OSX/libsecurity_apple_csp/lib/AppleCSP.cpp @@ -26,10 +26,6 @@ #include "cspdebugging.h" #include #include -#ifdef BSAFE_CSP_ENABLE -#include "bsafecsp.h" -#include "bsafecspi.h" -#endif #ifdef CRYPTKIT_CSP_ENABLE #include "cryptkitcsp.h" #include "FEEKeys.h" @@ -51,9 +47,6 @@ AppleCSPPlugin::AppleCSPPlugin() : normAllocator(Allocator::standard(Allocator::normal)), privAllocator(Allocator::standard(Allocator::sensitive)), - #ifdef BSAFE_CSP_ENABLE - bSafe4Factory(new BSafeFactory(&normAllocator, &privAllocator)), - #endif #ifdef CRYPTKIT_CSP_ENABLE cryptKitFactory(new CryptKitFactory(&normAllocator, &privAllocator)), #endif @@ -69,9 +62,6 @@ AppleCSPPlugin::AppleCSPPlugin() : AppleCSPPlugin::~AppleCSPPlugin() { - #ifdef BSAFE_CSP_ENABLE - delete bSafe4Factory; - #endif #ifdef CRYPTKIT_CSP_ENABLE delete cryptKitFactory; #endif @@ -128,9 +118,6 @@ AppleCSPSession::AppleCSPSession( subserviceType, attachFlags, upcalls), - #ifdef BSAFE_CSP_ENABLE - bSafe4Factory(*(dynamic_cast(plug.bSafe4Factory))), - #endif #ifdef CRYPTKIT_CSP_ENABLE cryptKitFactory(*(dynamic_cast(plug.cryptKitFactory))), #endif @@ -178,13 +165,6 @@ void AppleCSPSession::setupContext( * Note we leave the decision as to whether it's OK to * reuse a context to the individual factories. */ - #ifdef BSAFE_CSP_ENABLE - /* Give BSAFE the firsrt shot if it's present */ - if (bSafe4Factory.setup(*this, cspCtx, context)) { - CASSERT(cspCtx != NULL); - return; - } - #endif if (rsaDsaAlgFactory.setup(*this, cspCtx, context)) { CASSERT(cspCtx != NULL); return; @@ -617,14 +597,6 @@ CSPKeyInfoProvider *AppleCSPSession::infoProvider( { CSPKeyInfoProvider *provider = NULL; - #ifdef BSAFE_CSP_ENABLE - /* Give BSAFE first shot, if it's here */ - provider = BSafe::BSafeKeyInfoProvider::provider(key, *this); - if(provider != NULL) { - return provider; - } - #endif - provider = RSAKeyInfoProvider::provider(key, *this); if(provider != NULL) { return provider; diff --git a/OSX/libsecurity_apple_csp/lib/AppleCSP.h b/OSX/libsecurity_apple_csp/lib/AppleCSP.h index 513cba295..43fbcaf3f 100644 --- a/OSX/libsecurity_apple_csp/lib/AppleCSP.h +++ b/OSX/libsecurity_apple_csp/lib/AppleCSP.h @@ -68,10 +68,6 @@ class AppleCSPPlugin : public CssmPlugin { private: Allocator &normAllocator; Allocator &privAllocator; - #ifdef BSAFE_CSP_ENABLE - AppleCSPAlgorithmFactory *bSafe4Factory; // actually subclasses not visible - // in this header - #endif #ifdef CRYPTKIT_CSP_ENABLE AppleCSPAlgorithmFactory *cryptKitFactory; #endif diff --git a/OSX/libsecurity_apple_csp/lib/AppleCSPSession.h b/OSX/libsecurity_apple_csp/lib/AppleCSPSession.h index c64dbe68f..58a7b03fe 100644 --- a/OSX/libsecurity_apple_csp/lib/AppleCSPSession.h +++ b/OSX/libsecurity_apple_csp/lib/AppleCSPSession.h @@ -33,9 +33,6 @@ class CSPKeyInfoProvider; /* avoid unnecessary includes.... */ class AppleCSPPlugin; -#ifdef BSAFE_CSP_ENABLE -class BSafeFactory; -#endif #ifdef CRYPTKIT_CSP_ENABLE class CryptKitFactory; #endif @@ -129,9 +126,6 @@ class AppleCSPSession : public CSPFullPluginSession { Allocator &normAlloc() { return normAllocator; } Allocator &privAlloc() { return privAllocator; } - #ifdef BSAFE_CSP_ENABLE - BSafeFactory &bSafe4Factory; - #endif #ifdef CRYPTKIT_CSP_ENABLE CryptKitFactory &cryptKitFactory; #endif diff --git a/OSX/libsecurity_apple_csp/lib/BlockCryptor.cpp b/OSX/libsecurity_apple_csp/lib/BlockCryptor.cpp index 72e5e058d..feed16618 100644 --- a/OSX/libsecurity_apple_csp/lib/BlockCryptor.cpp +++ b/OSX/libsecurity_apple_csp/lib/BlockCryptor.cpp @@ -317,7 +317,7 @@ void BlockCryptor::update( /* * en/decrypt even blocks in (remaining) inp. */ - size_t leftOver = uInSize % mInBlockSize; + size_t leftOver = (mInBlockSize > 0) ? uInSize % mInBlockSize : 0; if((leftOver == 0) && needLeftOver) { /* * Even blocks coming in, but we really need to leave some data @@ -327,7 +327,7 @@ void BlockCryptor::update( leftOver = mInBlockSize; } toMove = uInSize - leftOver; - size_t blocks = toMove / mInBlockSize; + size_t blocks = (mInBlockSize > 0) ? toMove / mInBlockSize : 0; if(mMultiBlockCapable && !doCbc && (blocks != 0)) { /* * Optimization for algorithms that are multi-block capable and that diff --git a/OSX/libsecurity_apple_csp/lib/YarrowConnection.cpp b/OSX/libsecurity_apple_csp/lib/YarrowConnection.cpp index e6a8da606..b83a4cfdf 100644 --- a/OSX/libsecurity_apple_csp/lib/YarrowConnection.cpp +++ b/OSX/libsecurity_apple_csp/lib/YarrowConnection.cpp @@ -21,28 +21,16 @@ */ #include "YarrowConnection.h" #include -#include #include - -/* instantiated by C++ runtime at library load/init time */ -class YarrowConnection : public DevRandomGenerator { -public: - YarrowConnection() : DevRandomGenerator(getuid() == 0), writable(getuid() == 0) { } - const bool writable; -}; - -/* the single global thing */ -static ModuleNexus yarrowConnection; - +#include /* and the exported functions */ void cspGetRandomBytes(void *buf, unsigned len) { - yarrowConnection().random(buf, len); + MacOSError::check(SecRandomCopyBytes(kSecRandomDefault, len, buf)); } +/* Unused, since SecRandomCopyBytes returns from a suitable CSPRNG seeded elsewhere */ void cspAddEntropy(const void *buf, unsigned len) { - if (yarrowConnection().writable) - yarrowConnection().addEntropy(buf, len); } diff --git a/OSX/libsecurity_apple_csp/lib/algmaker.cpp b/OSX/libsecurity_apple_csp/lib/algmaker.cpp deleted file mode 100644 index 9b6729039..000000000 --- a/OSX/libsecurity_apple_csp/lib/algmaker.cpp +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - -#ifdef BSAFE_CSP_ENABLE - - -// -// algmaker - algorithm factory for BSafe 4 -// -#include "bsafecspi.h" -#include "bsafecsp.h" -#include "AppleCSPSession.h" - -// -// BSafe's Chooser table. -// These are references to all *BSafe algorithms* we use (and thus must link in) -// -const B_ALGORITHM_METHOD * const BSafe::bsChooser[] = { - // digests - &AM_SHA, - &AM_MD5, - &AM_MD2, - - // organizational - &AM_CBC_ENCRYPT, - &AM_CBC_DECRYPT, - &AM_ECB_ENCRYPT, - &AM_ECB_DECRYPT, - &AM_OFB_ENCRYPT, - &AM_OFB_DECRYPT, - - // DES & variants - &AM_DES_ENCRYPT, - &AM_DES_DECRYPT, - &AM_DESX_ENCRYPT, - &AM_DESX_DECRYPT, - &AM_DES_EDE_ENCRYPT, - &AM_DES_EDE_DECRYPT, - - // RCn stuff - &AM_RC2_CBC_ENCRYPT, - &AM_RC2_CBC_DECRYPT, - &AM_RC2_ENCRYPT, - &AM_RC2_DECRYPT, - &AM_RC4_ENCRYPT, - &AM_RC4_DECRYPT, - &AM_RC5_ENCRYPT, - &AM_RC5_DECRYPT, - &AM_RC5_CBC_ENCRYPT, - &AM_RC5_CBC_DECRYPT, - - // RSA - &AM_RSA_STRONG_KEY_GEN, - &AM_RSA_KEY_GEN, - &AM_RSA_CRT_ENCRYPT_BLIND, - &AM_RSA_CRT_DECRYPT_BLIND, - &AM_RSA_ENCRYPT, - &AM_RSA_DECRYPT, - - // DSA - &AM_DSA_PARAM_GEN, - &AM_DSA_KEY_GEN, - - // signatures - &AM_DSA_SIGN, - &AM_DSA_VERIFY, - - // random number generation - &AM_MD5_RANDOM, - &AM_SHA_RANDOM, - - // sentinel - (B_ALGORITHM_METHOD *)NULL_PTR -}; - - -// -// Makers -// -template -class Maker0 : public BSafe::MakerBase { -public: - Ctx *make(AppleCSPSession &session, const Context &context) const - { return new Ctx(session, context); } -}; - -template -class Maker1 : public BSafe::MakerBase { - Arg arg; -public: - Maker1(Arg a) : arg(a) { } - Ctx *make(AppleCSPSession &session, const Context &context) const - { return new Ctx(session, context, arg); } -}; - -template -class Maker2 : public BSafe::MakerBase { - Arg1 arg1; Arg2 arg2; -public: - Maker2(Arg1 a1, Arg2 a2) : arg1(a1), arg2(a2) { } - Ctx *make(AppleCSPSession &session, const Context &context) const - { return new Ctx(session, context, arg1, arg2); } -}; - -template -class Maker3 : public BSafe::MakerBase { - Arg1 arg1; Arg2 arg2; Arg3 arg3; -public: - Maker3(Arg1 a1, Arg2 a2, Arg3 a3) : - arg1(a1), arg2(a2), arg3(a3) { } - Ctx *make(AppleCSPSession &session, const Context &context) const - { return new Ctx(session, context, arg1, arg2, arg3); } -}; - - -bug_const BSafe::MakerTable BSafe::algorithms[] = { - // signing algorithms - // constructor args: BSafe algorithm, signature size - { - CSSM_ALGID_SHA1WithDSA, - CSSM_ALGCLASS_SIGNATURE, - new Maker2 - (AI_DSAWithSHA1, 48) // max size of 48 bytes - }, - { - CSSM_ALGID_SHA1WithRSA, - CSSM_ALGCLASS_SIGNATURE, - new Maker2 - (AI_SHA1WithRSAEncryption, 0) // size = RSA key size - }, - - { - CSSM_ALGID_MD5WithRSA, - CSSM_ALGCLASS_SIGNATURE, - new Maker2 - (AI_MD5WithRSAEncryption, 0) // size = RSA key size - }, - - { - CSSM_ALGID_MD2WithRSA, - CSSM_ALGCLASS_SIGNATURE, - new Maker2 - (AI_MD2WithRSAEncryption, 0) // size = RSA key size - }, - - // MAC algorithms - // constructor args: BSafe algorithm, signature size - { - CSSM_ALGID_SHA1HMAC, - CSSM_ALGCLASS_MAC, - new Maker2 - (AI_SHA1, 20) - }, - - // symmetric key generation - // constructor args: min/max key size in bits, mustBeByteSized - { - CSSM_ALGID_RC2, - CSSM_ALGCLASS_KEYGEN, - new Maker3 - (1*8, 128*8, true) - }, - { - CSSM_ALGID_RC4, - CSSM_ALGCLASS_KEYGEN, - new Maker3 - (1*8, 256*8, true) - }, - { - CSSM_ALGID_RC5, - CSSM_ALGCLASS_KEYGEN, - new Maker3 - (1*8, 255*8, true) - }, - { - CSSM_ALGID_DES, - CSSM_ALGCLASS_KEYGEN, - new Maker3 - (64, 64, true) - }, - { - CSSM_ALGID_DESX, - CSSM_ALGCLASS_KEYGEN, - new Maker3 - (192, 192, true) - }, - { - CSSM_ALGID_3DES_3KEY, - CSSM_ALGCLASS_KEYGEN, - new Maker3 - (192, 192, true) - }, - { - CSSM_ALGID_SHA1HMAC, - CSSM_ALGCLASS_KEYGEN, - new Maker3 - (160, 2048, true) - }, - - // symmetric encryption algorithms - // constructor arg: block size (1 ==> stream cipher) - { - CSSM_ALGID_DES, - CSSM_ALGCLASS_SYMMETRIC, - new Maker1(8) - }, - { - CSSM_ALGID_DESX, - CSSM_ALGCLASS_SYMMETRIC, - new Maker1(8) - }, - { - CSSM_ALGID_3DES_3KEY_EDE, - CSSM_ALGCLASS_SYMMETRIC, - new Maker1(8) - }, - { - CSSM_ALGID_RC2, - CSSM_ALGCLASS_SYMMETRIC, - new Maker1(8) - }, - { - CSSM_ALGID_RC4, - CSSM_ALGCLASS_SYMMETRIC, - new Maker1(1) - }, - { - CSSM_ALGID_RC5, - CSSM_ALGCLASS_SYMMETRIC, - new Maker1(8) - }, - - // asymmetric encryption algorithms - { - CSSM_ALGID_RSA, - CSSM_ALGCLASS_ASYMMETRIC, - new Maker0() - }, - { - CSSM_ALGID_DSA, - CSSM_ALGCLASS_ASYMMETRIC, - new Maker0() - }, - - // key pair generate algorithms - { - CSSM_ALGID_RSA, - CSSM_ALGCLASS_KEYGEN, - new Maker0() - }, - { - CSSM_ALGID_DSA, - CSSM_ALGCLASS_KEYGEN, - new Maker0() - }, - - // pseudo-random number generators - { - CSSM_ALGID_MD5Random, - CSSM_ALGCLASS_RANDOMGEN, - new Maker1(AI_MD5Random) - }, - { - CSSM_ALGID_SHARandom, - CSSM_ALGCLASS_RANDOMGEN, - new Maker1(AI_SHA1Random) - }, -}; - -const unsigned int BSafe::algorithmCount = sizeof(algorithms) / sizeof(algorithms[0]); - - -// -// BSafeFactory hookup -// -void BSafeFactory::setNormAllocator(Allocator *alloc) -{ - BSafe::setNormAllocator(alloc); -} -void BSafeFactory::setPrivAllocator(Allocator *alloc) -{ - BSafe::setPrivAllocator(alloc); -} - -bool BSafeFactory::setup( - AppleCSPSession &session, - CSPFullPluginSession::CSPContext * &cspCtx, - const Context &context) -{ - return BSafe::setup(session, cspCtx, context); -} - - -// -// Algorithm setup -// -bool BSafe::setup( - AppleCSPSession &session, - CSPFullPluginSession::CSPContext * &cspCtx, - const Context &context) -{ - for (const BSafe::MakerTable *alg = algorithms; - alg < algorithms + algorithmCount; - alg++) { - if ((alg->algorithmId == context.algorithm()) && - (alg->algClass == context.type())) { - if(cspCtx != NULL) { - /* we allow reuse */ - return true; - } - // make new context - cspCtx = alg->maker->make(session, context); - return true; - } - } - /* not ours */ - return false; -} -#endif /* BSAFE_CSP_ENABLE */ diff --git a/OSX/libsecurity_apple_csp/lib/bsafeAsymmetric.cpp b/OSX/libsecurity_apple_csp/lib/bsafeAsymmetric.cpp deleted file mode 100644 index e9b06e932..000000000 --- a/OSX/libsecurity_apple_csp/lib/bsafeAsymmetric.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - -#ifdef BSAFE_CSP_ENABLE - - -// -// bsafeAsymmetric.cpp - asymmetric encrypt/decrypt -// -#include "bsafecspi.h" - -#include // debug - -// -// Public key {en,de}cryption (currently RSA only) -// -// FIXME: -// We really should match the key algorithm to the en/decrypt -// algorithm. Also: verify key usage bits. -void BSafe::PublicKeyCipherContext::init(const Context &context, bool encrypting) -{ - assert(context.algorithm() == CSSM_ALGID_RSA); - - if (reusing(encrypting)) - return; // all set to go - - switch (context.getInt(CSSM_ATTRIBUTE_MODE)) { - case CSSM_ALGMODE_PUBLIC_KEY: - setAlgorithm(AI_PKCS_RSAPublic); - break; - case CSSM_ALGMODE_PRIVATE_KEY: - setAlgorithm(AI_PKCS_RSAPrivate); - break; - case CSSM_ALGMODE_NONE: - { - /* - * None specified (getInt returns zero in that case) - - * infer from key type - */ - CssmKey &key = context.get( - CSSM_ATTRIBUTE_KEY, CSSMERR_CSP_MISSING_ATTR_KEY); - B_INFO_TYPE bAlgType; - switch (key.keyClass()) { - case CSSM_KEYCLASS_PUBLIC_KEY: - bAlgType = AI_PKCS_RSAPublic; - break; - case CSSM_KEYCLASS_PRIVATE_KEY: - bAlgType = AI_PKCS_RSAPrivate; - break; - default: - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); - } - setAlgorithm(bAlgType); - break; - } - default: - CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_MODE); - } - - // put it all together - setKeyFromContext(context); // set BSafe key - setRandom(); // some PK cryption algs need random input - cipherInit(); // common cipher init - //@@@ calculate output buffer size -} - -// we assume asymmetric crypto algorithms are one-shot output non-repeating - -size_t BSafe::PublicKeyCipherContext::inputSize(size_t outSize) -{ - return 0xFFFFFFFF; // perhaps not the biggest size_t, but big enough... -} -#endif /* BSAFE_CSP_ENABLE */ diff --git a/OSX/libsecurity_apple_csp/lib/bsafeContext.cpp b/OSX/libsecurity_apple_csp/lib/bsafeContext.cpp deleted file mode 100644 index e69c8bd84..000000000 --- a/OSX/libsecurity_apple_csp/lib/bsafeContext.cpp +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - -#ifdef BSAFE_CSP_ENABLE - - -// -// bsafeContext.cpp - implementation of class BSafe::BSafeContext -// and some of its subclasses -// - -#include "bsafecspi.h" -#include "bsafePKCS1.h" -#include -#include -#include -#include "cspdebugging.h" - -#define DATA(cData) POINTER(cData.data()), cData.length() - -A_SURRENDER_CTX * const BSafe::BSafeContext::bsSurrender = NULL; - - -// -// Construct an algorithm object -// -BSafe::BSafeContext::BSafeContext(AppleCSPSession &session) - : AppleCSPContext(session) -{ - bsAlgorithm = NULL; - bsKey = NULL; - bsBinKey = NULL; - bsRandom = NULL; - initialized = false; - opStarted = false; -#ifdef SAFER - inUpdate = NULL; - inOutUpdate = NULL; - inFinal = NULL; - outFinal = NULL; - outFinalR = NULL; -#endif //SAFER -} - -BSafe::BSafeContext::~BSafeContext() -{ - reset(); -} - -void BSafe::BSafeContext::reset() -{ - B_DestroyAlgorithmObject(&bsAlgorithm); - B_DestroyAlgorithmObject(&bsRandom); - destroyBsKey(); -} - -/* - * Clear key state. We only destroy bsKey if we don't have a - * BinaryKey. - */ -void BSafe::BSafeContext::destroyBsKey() -{ - if(bsBinKey == NULL) { - B_DestroyKeyObject(&bsKey); - } - else { - // bsKey gets destroyed when bsBinKey gets deleted - bsBinKey = NULL; - bsKey = NULL; - } -} - -void BSafe::check(int status, bool isKeyOp) -{ - if(status == 0) { - return; - } - dprintf1("BSAFE Error %d\n", status); - switch (status) { - case BE_ALLOC: - throw std::bad_alloc(); - case BE_SIGNATURE: - CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED); - case BE_OUTPUT_LEN: - CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); - case BE_INPUT_LEN: - CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR); - case BE_EXPONENT_EVEN: - case BE_EXPONENT_LEN: - case BE_EXPONENT_ONE: - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); - case BE_DATA: - case BE_INPUT_DATA: - if(isKeyOp) { - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); - } - else { - CssmError::throwMe(CSSMERR_CSP_INVALID_DATA); - } - case BE_MODULUS_LEN: - case BE_OVER_32K: - case BE_INPUT_COUNT: - case BE_CANCEL: - //@@@ later... - default: - //@@@ translate BSafe errors intelligently - CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); - } -} - - -void BSafe::BSafeContext::setAlgorithm( - B_INFO_TYPE bAlgType, - const void *info) -{ - B_DestroyAlgorithmObject(&bsAlgorithm); // clear any old BSafe algorithm - check(B_CreateAlgorithmObject(&bsAlgorithm)); - check(B_SetAlgorithmInfo(bsAlgorithm, bAlgType, POINTER(info))); -} - -/* safely create bsKey */ -void BSafe::BSafeContext::createBsKey() -{ - /* reset to initial key state - some keys can't be reused */ - destroyBsKey(); - check(B_CreateKeyObject(&bsKey)); -} - -/* form of *info varies per bKeyInfo */ -void BSafe::BSafeContext::setKeyAtom( - B_INFO_TYPE bKeyInfo, - const void *info) -{ - /* debug only */ - if((bKeyInfo == KI_RSAPublicBER) || (bKeyInfo == KI_RSAPublic)) { - printf("Aargh! Unhandled KI_RSAPublic!\n"); - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); - } - assert(bKeyInfo != KI_RSAPublicBER); // handled elsewhere for now - assert(bKeyInfo != KI_RSAPublic); // handled elsewhere for now - createBsKey(); - check(B_SetKeyInfo(bsKey, bKeyInfo, POINTER(info)), true); -} - -// -// Set outSize for RSA keys. -// -void BSafe::BSafeContext::setRsaOutSize( - bool isPubKey) -{ - assert(bsKey != NULL); - - A_RSA_KEY *keyInfo; - if(isPubKey) { - keyInfo = getKey(bsKey, KI_RSAPublic); - } - else { - keyInfo = getKey(bsKey, KI_RSAPrivate); - } - mOutSize = (B_IntegerBits(keyInfo->modulus.data, - keyInfo->modulus.len) + 7) / 8; -} - -// -// Handle various forms of reference key. Symmetric -// keys are stored as SymmetricBinaryKey, with raw key bytes -// in keyData. Our asymmetric keys are stored as BSafeBinaryKeys, -// with an embedded ready-to-use B_KEY_OBJ. -// -void BSafe::BSafeContext::setRefKey(CssmKey &key) -{ - bool isPubKey = false; - - switch(key.keyClass()) { - case CSSM_KEYCLASS_SESSION_KEY: - { - assert(key.blobFormat() == - CSSM_KEYBLOB_REF_FORMAT_INTEGER); - - BinaryKey &binKey = session().lookupRefKey(key); - // fails if this is not a SymmetricBinaryKey - SymmetricBinaryKey *symBinKey = - dynamic_cast(&binKey); - if(symBinKey == NULL) { - errorLog0("BSafe::setRefKey(1): wrong BinaryKey subclass\n"); - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); - } - setKeyFromCssmData(KI_Item, symBinKey->mKeyData); - return; - } - case CSSM_KEYCLASS_PUBLIC_KEY: - isPubKey = true; // and fall thru - case CSSM_KEYCLASS_PRIVATE_KEY: - { - BinaryKey &binKey = session().lookupRefKey(key); - destroyBsKey(); - bsBinKey = dynamic_cast(&binKey); - /* this cast failing means that this is some other - * kind of binary key */ - if(bsBinKey == NULL) { - errorLog0("BSafe::setRefKey(2): wrong BinaryKey subclass\n"); - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); - } - assert(bsBinKey->bsKey() != NULL); - bsKey = bsBinKey->bsKey(); - if(key.algorithm() == CSSM_ALGID_RSA) { - setRsaOutSize(isPubKey); - } - return; - } - default: - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); - } -} - -void BSafe::BSafeContext::setKeyFromContext( - const Context &context, - bool required) -{ - CssmKey &key = - context.get(CSSM_ATTRIBUTE_KEY, CSSMERR_CSP_MISSING_ATTR_KEY); - - switch(key.blobType()) { - case CSSM_KEYBLOB_REFERENCE: - setRefKey(key); - return; - case CSSM_KEYBLOB_RAW: - break; // to main routine - default: - CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT); - } - - bool isPubKey; - switch (key.keyClass()) { - case CSSM_KEYCLASS_SESSION_KEY: - /* symmetric, one format supported for all algs */ - switch (key.blobFormat()) { - case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING: - setKeyFromCssmKey(KI_Item, key); - return; - default: - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); - } - case CSSM_KEYCLASS_PUBLIC_KEY: - isPubKey = true; - break; - case CSSM_KEYCLASS_PRIVATE_KEY: - isPubKey = false; - break; - default: - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); - } - - /* We know it's an asymmetric key; get some info */ - B_INFO_TYPE infoType; - CSSM_KEYBLOB_FORMAT expectedFormat; - - if(!bsafeAlgToInfoType(key.algorithm(), - isPubKey, - infoType, - expectedFormat)) { - /* unknown alg! */ - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); - } - - /* - * Correct format? - * NOTE: if we end up supporting multiple incoming key formats, they'll - * have to be handled here. - */ - if(expectedFormat != key.blobFormat()) { - errorLog1("setKeyFromContext: invalid blob format (%d)\n", - (int)key.blobFormat()); - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); - } - - /* - * Most formats can be handled directly by BSAFE. Handle the special cases - * requiring additional processing here. - */ - switch(expectedFormat) { - case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: - /* RSA public keys */ - createBsKey(); - BS_setKeyPkcs1(CssmData::overlay(key.KeyData), bsKey); - break; - default: - setKeyFromCssmKey(infoType, key); - break; - } - - /* - * One more thing - set mOutSize for RSA keys - */ - if(key.algorithm() == CSSM_ALGID_RSA) { - setRsaOutSize(isPubKey); - } -} - -#define BSAFE_RANDSIZE 32 - -void BSafe::BSafeContext::setRandom() -{ - if (bsRandom == NULL) { - check(B_CreateAlgorithmObject(&bsRandom)); - check(B_SetAlgorithmInfo(bsRandom, AI_X962Random_V0, NULL_PTR)); - check(B_RandomInit(bsRandom, chooser(), bsSurrender)); - uint8 seed[BSAFE_RANDSIZE]; - session().getRandomBytes(BSAFE_RANDSIZE, seed); - check(B_RandomUpdate(bsRandom, seed, sizeof(seed), bsSurrender)); - } -} - - -// -// Operational methods of BSafeContext -// -void BSafe::BSafeContext::init(const Context &, bool) -{ - // some algorithms don't need init(), because all is done in the context constructor -} - -// update for input-only block/stream algorithms -void BSafe::BSafeContext::update(const CssmData &data) -{ - opStarted = true; - check(inUpdate(bsAlgorithm, POINTER(data.data()), data.length(), bsSurrender)); -} - -// update for input/output block/stream algorithms -void BSafe::BSafeContext::update(void *inp, size_t &inSize, void *outp, size_t &outSize) -{ - unsigned int length; - opStarted = true; - check(inOutUpdate(bsAlgorithm, POINTER(outp), &length, outSize, - POINTER(inp), inSize, bsRandom, bsSurrender)); - // always eat all input (inSize unchanged) - outSize = length; - - // let the algorithm manager track I/O sizes, if needed - trackUpdate(inSize, outSize); -} - -// output-generating final call -void BSafe::BSafeContext::final(CssmData &out) -{ - unsigned int length; - if (outFinal) { - check(outFinal(bsAlgorithm, - POINTER(out.data()), - &length, - out.length(), - bsSurrender)); - } - else { - check(outFinalR(bsAlgorithm, - POINTER(out.data()), - &length, - out.length(), - bsRandom, - bsSurrender)); - } - out.length(length); - initialized = false; -} - -// verifying final call (takes additional input) -void BSafe::BSafeContext::final(const CssmData &in) -{ - int status; - - /* note sig verify errors can show up as lots of BSAFE statuses; - * munge them all into the appropriate error */ - if (inFinal) { - status = inFinal(bsAlgorithm, - POINTER(in.data()), - in.length(), - bsSurrender); - } - else { - status = inFinalR(bsAlgorithm, - POINTER(in.data()), - in.length(), - bsRandom, - bsSurrender); - } - if(status != 0) { - if((mType == CSSM_ALGCLASS_SIGNATURE) && (mDirection == false)) { - /* yep, sig verify error */ - CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED); - } - /* other error, use standard trap */ - check(status); - } - initialized = false; -} - -size_t BSafe::BSafeContext::outputSize(bool final, size_t inSize) -{ - // this default implementation only makes sense for single-output end-loaded algorithms - return final ? mOutSize : 0; -} - -void BSafe::BSafeContext::trackUpdate(size_t, size_t) -{ /* do nothing */ } - -// -// Common features of CipherContexts. -// -void BSafe::CipherContext::cipherInit() -{ - // set handlers - if (encoding) { - inOutUpdate = B_EncryptUpdate; - outFinalR = B_EncryptFinal; - } else { - inOutUpdate = B_DecryptUpdate; - outFinalR = B_DecryptFinal; - } - outFinal = NULL; - - // init the algorithm - check((encoding ? B_EncryptInit : B_DecryptInit) - (bsAlgorithm, bsKey, chooser(), bsSurrender)); - - // buffers start empty - pending = 0; - - // state is now valid - initialized = true; - opStarted = false; -} -#endif /* BSAFE_CSP_ENABLE */ - diff --git a/OSX/libsecurity_apple_csp/lib/bsafeKeyGen.cpp b/OSX/libsecurity_apple_csp/lib/bsafeKeyGen.cpp deleted file mode 100644 index 2e5391ff8..000000000 --- a/OSX/libsecurity_apple_csp/lib/bsafeKeyGen.cpp +++ /dev/null @@ -1,461 +0,0 @@ -/* - * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - -#ifdef BSAFE_CSP_ENABLE - - -// -// bsafeKeyGen.cpp - key generation routines -// -#include "bsafecspi.h" -#include "bsafePKCS1.h" -#include "cspdebugging.h" - -/* - * Stateless, private function to map a CSSM alg and pub/priv state - * to B_INFO_TYPE and format. Returns true on success, false on - * "I don't understand this algorithm". - */ -bool BSafe::bsafeAlgToInfoType( - CSSM_ALGORITHMS alg, - bool isPublic, - B_INFO_TYPE &infoType, // RETURNED - CSSM_KEYBLOB_FORMAT &format) // RETURNED -{ - switch(alg) { - case CSSM_ALGID_RSA: - if(isPublic) { - infoType = RSA_PUB_KEYINFO_TYPE; - format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1; - } - else { - infoType = RSA_PRIV_KEYINFO_TYPE; - format = CSSM_KEYBLOB_RAW_FORMAT_PKCS8; - } - return true; - case CSSM_ALGID_DSA: - format = CSSM_KEYBLOB_RAW_FORMAT_FIPS186; - if(isPublic) { - infoType = DSA_PUB_KEYINFO_TYPE; - } - else { - infoType = DSA_PRIV_KEYINFO_TYPE; - } - return true; - default: - return false; - } -} - - -BSafe::BSafeBinaryKey::BSafeBinaryKey( - bool isPub, - uint32 Alg) - : mIsPublic(isPub), - mAlg(Alg) -{ - BSafe::check(B_CreateKeyObject(&mBsKey), true); -} - -BSafe::BSafeBinaryKey::~BSafeBinaryKey() -{ - B_DestroyKeyObject(&mBsKey); -} - -void BSafe::BSafeBinaryKey::generateKeyBlob( - Allocator &allocator, - CssmData &blob, - CSSM_KEYBLOB_FORMAT &format, // input val ignored for now - AppleCSPSession &session, - const CssmKey *paramKey, // optional, unused here - CSSM_KEYATTR_FLAGS &attrFlags) // IN/OUT -{ - assert(mBsKey != NULL); - - B_INFO_TYPE bsType; - if(!bsafeAlgToInfoType(mAlg, mIsPublic, bsType, format)) { - CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); - } - if(format == CSSM_KEYBLOB_RAW_FORMAT_PKCS1) { - /* special case, encode the PKCS1 format blob */ - CssmRemoteData rData( - Allocator::standard(Allocator::sensitive), blob); - BS_GetKeyPkcs1(mBsKey, rData); - rData.release(); - } - else { - BSafeItem *info; - BSafe::check( - B_GetKeyInfo((POINTER *)&info, mBsKey, bsType), true); - blob = info->copy(allocator); - } -} - -// -// This is called from CSPFullPluginSession -// -void BSafe::BSafeKeyPairGenContext::generate( - const Context &context, - CssmKey &pubKey, - CssmKey &privKey) -{ - BSafeBinaryKey *pubBinKey = new BSafeBinaryKey(true, - context.algorithm()); - BSafeBinaryKey *privBinKey = new BSafeBinaryKey(false, - context.algorithm()); - - try { - AppleKeyPairGenContext::generate(context, - session(), - pubKey, - pubBinKey, - privKey, - privBinKey); - } - catch (...) { - delete pubBinKey; - delete privBinKey; - throw; - } -} - -// -// Called from AppleKeyPairGenContext -// -void BSafe::BSafeKeyPairGenContext::generate( - const Context &context, - BinaryKey &pubBinKey, // valid on successful return - BinaryKey &privBinKey, // ditto - uint32 &keySize) // ditto -{ - /* these casts throw exceptions if the keys are of the - * wrong classes, which is a major bogon, since we created - * the keys in the above generate() function */ - BSafeBinaryKey &bsPubBinKey = - dynamic_cast(pubBinKey); - BSafeBinaryKey &bsPrivBinKey = - dynamic_cast(privBinKey); - - if (!initialized) { - setupAlgorithm(context, keySize); - check(B_GenerateInit(bsAlgorithm, chooser(), bsSurrender), true); - initialized = true; - } - - setRandom(); - check(B_GenerateKeypair(bsAlgorithm, - bsPubBinKey.bsKey(), - bsPrivBinKey.bsKey(), - bsRandom, - bsSurrender), true); -} - -void BSafe::BSafeKeyPairGenContext::setupAlgorithm( - const Context &context, - uint32 &keySize) -{ - switch(context.algorithm()) { - case CSSM_ALGID_RSA: - { - A_RSA_KEY_GEN_PARAMS genParams; - keySize = genParams.modulusBits = - context.getInt(CSSM_ATTRIBUTE_KEY_LENGTH, - CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); - if (CssmData *params = - context.get(CSSM_ATTRIBUTE_ALG_PARAMS)) { - genParams.publicExponent = BSafeItem(*params); - } else { - static unsigned char exponent[] = { 1, 0, 1 }; - genParams.publicExponent = BSafeItem(exponent, sizeof(exponent)); - } - /* - * For test purposes, we avoid the 'strong' key generate - * algorithm if a CSSM_ALGMODE_CUSTOM mode atrtribute - * is present in the context. This is not published and - * not supported in the real world. - */ - uint32 mode = context.getInt(CSSM_ATTRIBUTE_MODE); - if(mode == CSSM_ALGMODE_CUSTOM) { - setAlgorithm(AI_RSAKeyGen, &genParams); - } - else { - setAlgorithm(AI_RSAStrongKeyGen, &genParams); - } - } - break; - case CSSM_ALGID_DSA: - { - A_DSA_PARAMS genParams; - genParams.prime = - BSafeItem(context.get( - CSSM_ATTRIBUTE_PRIME, - CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS)); - genParams.subPrime = - BSafeItem(context.get( - CSSM_ATTRIBUTE_SUBPRIME, - CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS)); - genParams.base = - BSafeItem(context.get( - CSSM_ATTRIBUTE_BASE, - CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS)); - setAlgorithm(AI_DSAKeyGen, &genParams); - keySize = B_IntegerBits(genParams.prime.data, genParams.prime.len); - } - break; - default: - CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); - } -} - -// -// DSA Parameter Generation -// -void BSafe::BSafeKeyPairGenContext::generate( - const Context &context, - uint32 bitSize, - CssmData ¶ms, - uint32 &attrCount, - Context::Attr * &attrs) -{ - assert(context.algorithm() == CSSM_ALGID_DSA); - - B_ALGORITHM_OBJ genAlg = NULL; - B_ALGORITHM_OBJ result = NULL; - - try { - check(B_CreateAlgorithmObject(&genAlg)); - - B_DSA_PARAM_GEN_PARAMS genParams; - genParams.primeBits = bitSize; - check(B_SetAlgorithmInfo(genAlg, AI_DSAParamGen, POINTER(&genParams))); - setRandom(); - check(B_GenerateInit(genAlg, chooser(), bsSurrender), true); - check(B_CreateAlgorithmObject(&result)); - check(B_GenerateParameters(genAlg, result, bsRandom, bsSurrender)); - - // get parameters out of algorithm object - A_DSA_PARAMS *kParams = NULL; - check(B_GetAlgorithmInfo((POINTER *)&kParams, result, AI_DSAKeyGen), true); - - // shred them into context attribute form - attrs = normAllocator->alloc(3); - attrs[0] = Context::Attr(CSSM_ATTRIBUTE_PRIME, - *BSafeItem(kParams->prime).copyp(*normAllocator)); - attrs[1] = Context::Attr(CSSM_ATTRIBUTE_SUBPRIME, - *BSafeItem(kParams->subPrime).copyp(*normAllocator)); - attrs[2] = Context::Attr(CSSM_ATTRIBUTE_BASE, - *BSafeItem(kParams->base).copyp(*normAllocator)); - attrCount = 3; - - // clean up - B_DestroyAlgorithmObject(&result); - B_DestroyAlgorithmObject(&genAlg); - } catch (...) { - // clean up - B_DestroyAlgorithmObject(&result); - B_DestroyAlgorithmObject(&genAlg); - throw; - } -} - -/* - * CSPKeyInfoProvider for asymmetric BSAFE keys. - */ -BSafe::BSafeKeyInfoProvider::BSafeKeyInfoProvider( - const CssmKey &cssmKey, - AppleCSPSession &session) : - CSPKeyInfoProvider(cssmKey, session) -{ -} - -CSPKeyInfoProvider *BSafe::BSafeKeyInfoProvider::provider( - const CssmKey &cssmKey, - AppleCSPSession &session) -{ - switch(cssmKey.keyClass()) { - case CSSM_KEYCLASS_PUBLIC_KEY: - case CSSM_KEYCLASS_PRIVATE_KEY: - break; - default: - return NULL; - } - switch(mKey.algorithm()) { - case CSSM_ALGID_RSA: - case CSSM_ALGID_DSA: - break; - default: - return NULL; - } - /* OK, we'll handle this one */ - return new BSafeKeyInfoProvider(cssmKey, session); -} - -/* cook up a Binary key */ -void BSafe::BSafeKeyInfoProvider::CssmKeyToBinary( - CssmKey *paramKey, // optional, ignored - CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT - BinaryKey **binKey) -{ - *binKey = NULL; - - const CSSM_KEYHEADER *hdr = &mKey.KeyHeader; - assert(hdr->BlobType == CSSM_KEYBLOB_RAW); - - B_INFO_TYPE bsType; - CSSM_KEYBLOB_FORMAT format; - bool isPub; - - switch(hdr->KeyClass) { - case CSSM_KEYCLASS_PUBLIC_KEY: - isPub = true; - break; - case CSSM_KEYCLASS_PRIVATE_KEY: - isPub = false; - break; - default: - // someone else's key - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); - } - if(!bsafeAlgToInfoType(hdr->AlgorithmId, isPub, bsType, format)) { - // someone else's key - CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); - } - if(hdr->Format != format) { - dprintf0("BSafe::cssmKeyToBinary: format mismatch\n"); - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); - } - - BSafeBinaryKey *bsBinKey = new BSafeBinaryKey(isPub, - hdr->AlgorithmId); - - // set up key material as appropriate - if(format == CSSM_KEYBLOB_RAW_FORMAT_PKCS1) { - /* special case, decode the PKCS1 format blob */ - BS_setKeyPkcs1(mKey, bsBinKey->bsKey()); - } - else { - /* normal case, use key blob as is */ - BSafeItem item(mKey.KeyData); - BSafe::check( - B_SetKeyInfo(bsBinKey->bsKey(), bsType, POINTER(&item)), true); - } - *binKey = bsBinKey; -} - -/* - * Obtain key size in bits. - */ -void BSafe::BSafeKeyInfoProvider::QueryKeySizeInBits( - CSSM_KEY_SIZE &keySize) -{ - if(mKey.blobType() != CSSM_KEYBLOB_RAW) { - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); - } - - /* cook up BSAFE key */ - B_KEY_OBJ bKey; - A_RSA_KEY *rsaKeyInfo = NULL; - A_DSA_PUBLIC_KEY *dsaPubKeyInfo = NULL; - A_DSA_PRIVATE_KEY *dsaPrivKeyInfo = NULL; - ITEM *sizeItem = NULL; - BSafe::check(B_CreateKeyObject(&bKey), true); - B_INFO_TYPE infoType; - - switch(mKey.algorithm()) { - case CSSM_ALGID_RSA: - switch(mKey.keyClass()) { - case CSSM_KEYCLASS_PUBLIC_KEY: - if(mKey.blobFormat() != - CSSM_KEYBLOB_RAW_FORMAT_PKCS1) { - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); - } - - /* convert from PKCS1 blob to raw key */ - BS_setKeyPkcs1(mKey, bKey); - infoType = KI_RSAPublic; - /* break to common RSA code */ - break; - case CSSM_KEYCLASS_PRIVATE_KEY: - { - if(mKey.blobFormat() != - CSSM_KEYBLOB_RAW_FORMAT_PKCS8) { - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); - } - - /* convert from PKCS8 blob to raw key */ - BSafeItem item(mKey.KeyData); - BSafe::check( - B_SetKeyInfo(bKey, KI_PKCS_RSAPrivateBER, - POINTER(&item)), true); - infoType = KI_RSAPrivate; - break; - } - default: - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); - } - rsaKeyInfo = getKey(bKey, infoType); - sizeItem = &rsaKeyInfo->modulus; - break; - - case CSSM_ALGID_DSA: - /* untested as of 9/11/00 */ - if(mKey.blobFormat() != - CSSM_KEYBLOB_RAW_FORMAT_FIPS186) { - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); - } - switch(mKey.keyClass()) { - case CSSM_KEYCLASS_PUBLIC_KEY: - { - BSafeItem item(mKey.KeyData); - BSafe::check(B_SetKeyInfo(bKey, - DSA_PUB_KEYINFO_TYPE, - (POINTER)&item), true); - - /* get the key bits */ - dsaPubKeyInfo = getKey(bKey, - KI_DSAPublic); - sizeItem = &dsaPubKeyInfo->params.prime; - break; - } - case CSSM_KEYCLASS_PRIVATE_KEY: - { - BSafeItem item(mKey.KeyData); - BSafe::check(B_SetKeyInfo(bKey, - DSA_PRIV_KEYINFO_TYPE, - (POINTER)&item), true); - - /* get the key bits */ - dsaPrivKeyInfo = getKey(bKey, - KI_DSAPrivate); - sizeItem = &dsaPrivKeyInfo->params.prime; - break; - } - default: - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); - } - break; - default: - CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); - } - uint32 iSize = B_IntegerBits(sizeItem->data, sizeItem->len); - keySize.LogicalKeySizeInBits = iSize; - keySize.EffectiveKeySizeInBits = iSize; - B_DestroyKeyObject(&bKey); -} - -#endif /* BSAFE_CSP_ENABLE */ - diff --git a/OSX/libsecurity_apple_csp/lib/bsafePKCS1.cpp b/OSX/libsecurity_apple_csp/lib/bsafePKCS1.cpp deleted file mode 100644 index 6eebba278..000000000 --- a/OSX/libsecurity_apple_csp/lib/bsafePKCS1.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - -#ifdef BSAFE_CSP_ENABLE - - -/* - * bsafePKCS1.cpp - support for PKCS1 format RSA public key blobs, which for some - * reason, BSAFE doesn't know about. - */ - -#include "bsafePKCS1.h" -#include "bsafecspi.h" -#include "cspdebugging.h" -#include "bsobjects.h" -#include /* for RSAPublicKey */ -#include -#include - -/* - * Simple conversion between BSAFE ITEM and snacc BigIntegerStr - */ -static void BS_ItemToSnaccBigInt( - const ITEM &item, - BigIntegerStr &snaccInt) -{ - snaccInt.Set(reinterpret_cast(item.data), item.len); -} - -/* - * This one doesn't do a malloc - the ITEM is only valid as long as - * snaccInt is! - */ -static void BS_snaccBigIntToItem( - BigIntegerStr &snaccInt, // not const - we're passing a ptr - ITEM &item) -{ - char *cp = snaccInt; - item.data = reinterpret_cast(cp); - item.len = snaccInt.Len(); -} - -/* - * Given a PKCS1-formatted key blob, decode the blob into components and do - * a B_SetKeyInfo on the specified BSAFE key. - */ -void BS_setKeyPkcs1( - const CssmData &pkcs1Blob, - B_KEY_OBJ bsKey) -{ - /* DER-decode the blob */ - RSAPublicKey snaccPubKey; - - try { - SC_decodeAsnObj(pkcs1Blob, snaccPubKey); - } - catch(const CssmError &cerror) { - CSSM_RETURN crtn = cerror.cssmError(); - - errorLog1("BS_setKeyPkcs1: SC_decodeAsnObj returned %s\n", - cssmErrorString(crtn).c_str()); - switch(crtn) { - case CSSMERR_CSSM_MEMORY_ERROR: - crtn = CSSMERR_CSP_MEMORY_ERROR; - break; - case CSSMERR_CSSM_INVALID_INPUT_POINTER: - crtn = CSSMERR_CSP_INVALID_KEY; - default: - break; - } - CssmError::throwMe(crtn); - } - - /* - * Convert BigIntegerStr modulus, publicExponent into - * ITEMS in an A_RSA_KEY. - */ - A_RSA_KEY rsaKey; - BS_snaccBigIntToItem(snaccPubKey.modulus, rsaKey.modulus); - BS_snaccBigIntToItem(snaccPubKey.publicExponent, rsaKey.exponent); - - BSafe::check( - B_SetKeyInfo(bsKey, KI_RSAPublic, POINTER(&rsaKey)), true); -} - -/* - * Obtain public key blob info, PKCS1 format. - */ -void BS_GetKeyPkcs1( - const B_KEY_OBJ bsKey, - CssmOwnedData &pkcs1Blob) -{ - /* get modulus/exponent info from BSAFE */ - A_RSA_KEY *rsaKey; - BSafe::check( - B_GetKeyInfo((POINTER *)&rsaKey, bsKey, KI_RSAPublic), true); - - /* Cook up a snacc-style RSAPublic key */ - RSAPublicKey snaccPubKey; - BS_ItemToSnaccBigInt(rsaKey->modulus, snaccPubKey.modulus); - BS_ItemToSnaccBigInt(rsaKey->exponent, snaccPubKey.publicExponent); - - /* estimate max size, BER-encode */ - size_t maxSize = 2 * (rsaKey->modulus.len + rsaKey->exponent.len); - try { - SC_encodeAsnObj(snaccPubKey, pkcs1Blob, maxSize); - } - catch(const CssmError &cerror) { - CSSM_RETURN crtn = cerror.cssmError(); - - errorLog1("BS_GetKeyPkcs1: SC_encodeAsnObj returned %s\n", - cssmErrorString(crtn).c_str()); - switch(crtn) { - case CSSMERR_CSSM_MEMORY_ERROR: - crtn = CSSMERR_CSP_MEMORY_ERROR; - break; - default: - break; - } - CssmError::throwMe(crtn); - } -} -#endif /* BSAFE_CSP_ENABLE */ diff --git a/OSX/libsecurity_apple_csp/lib/bsafePKCS1.h b/OSX/libsecurity_apple_csp/lib/bsafePKCS1.h deleted file mode 100644 index c65c0130d..000000000 --- a/OSX/libsecurity_apple_csp/lib/bsafePKCS1.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - -#ifdef BSAFE_CSP_ENABLE - - -/* - * bsafePKCS1.h - support for PKCS1 format RSA public key blobs, which for some - * reason, BSAFE doesn't know about. - */ - -#ifndef _BSAFE_PKCS1_H_ -#define _BSAFE_PKCS1_H_ - -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* DER-decode any AsnType object */ -CSSM_RETURN CL_decodeAsnObj( - const CssmData &derEncoded, - AsnType &asnObj); - -/* DER-encode any AsnType object. */ -CSSM_RETURN CL_encodeAsnObj( - AsnType &asnObj, - CssmOwnedData &derEncoded, - size_t maxEncodedSize); - -/* - * Given a PKCS1-formatted key blob, decode the blob into components and do - * a B_SetKeyInfo on the specified BSAFE key. - */ -void BS_setKeyPkcs1( - const CssmData &pkcs1Blob, - B_KEY_OBJ bsKey); - -/* - * Obtain public key blob info, PKCS1 format. - */ -void BS_GetKeyPkcs1( - const B_KEY_OBJ bsKey, - CssmOwnedData &pkcs1Blob); - -#ifdef __cplusplus -} -#endif - -#endif /* _BSAFE_PKCS1_H_ */ - -#endif /* BSAFE_CSP_ENABLE */ - diff --git a/OSX/libsecurity_apple_csp/lib/bsafeSymmetric.cpp b/OSX/libsecurity_apple_csp/lib/bsafeSymmetric.cpp deleted file mode 100644 index 477166bb4..000000000 --- a/OSX/libsecurity_apple_csp/lib/bsafeSymmetric.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - -#ifdef BSAFE_CSP_ENABLE - - -// -// bsafeSymmetric.cpp - symmetric encryption contexts and algorithms -// -#include "bsafecspi.h" -#include - -#define bbprintf(args...) secinfo("BSafeBuf", ## args) - -#define VERBOSE_DEBUG 0 -#if VERBOSE_DEBUG -static void dumpBuf( - char *title, - const CSSM_DATA *d, - uint32 maxLen) -{ - unsigned i; - uint32 len; - - if(title) { - printf("%s: ", title); - } - if(d == NULL) { - printf("NO DATA\n"); - return; - } - printf("Total Length: %d\n ", d->Length); - len = maxLen; - if(d->Length < len) { - len = d->Length; - } - for(i=0; iData[i]); - if((i % 16) == 15) { - printf("\n "); - } - } - printf("\n"); -} -#else -#define dumpBuf(t, d, m) -#endif /* VERBOSE_DEBUG */ - -void BSafe::SymmetricKeyGenContext::generate( - const Context &context, - CssmKey &symKey, - CssmKey &dummyKey) -{ - AppleSymmKeyGenContext::generateSymKey( - context, - session(), - symKey); -} - -// FIXME: -// We really should match the key algorithm to the en/decrypt -// algorithm. Also: verify key usage bits. -void BSafe::BlockCipherContext::init( - const Context &context, - bool encrypting) -{ - bool hasIV = false; - bool requirePad = false; - - if (reusing(encrypting)) - return; // all set to go - - cssmAlg = context.algorithm(); - switch(cssmAlg) { - // most are handled below; break here to special cases - case CSSM_ALGID_RC4: - RC4init(context); - return; - case CSSM_ALGID_DES: - case CSSM_ALGID_DESX: - case CSSM_ALGID_3DES_3KEY_EDE: - case CSSM_ALGID_RC5: - case CSSM_ALGID_RC2: - break; - - /* others here... */ - default: - // Should never have gotten this far - assert(0); - CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); - } - - - // these variables are used in the switch below and need to - // live until after setAlgorithm() - BSafeItem iv; - B_BLK_CIPHER_W_FEEDBACK_PARAMS spec; - A_RC5_PARAMS rc5Params; - A_RC2_PARAMS rc2Params; - - // crypto algorithm - spec.encryptionParams = NULL_PTR; // default, may change - switch (cssmAlg) { - case CSSM_ALGID_DES: - spec.encryptionMethodName = POINTER("des"); - break; - case CSSM_ALGID_DESX: - spec.encryptionMethodName = POINTER("desx"); - break; - case CSSM_ALGID_3DES_3KEY_EDE: - spec.encryptionMethodName = POINTER("des_ede"); - break; - case CSSM_ALGID_RC5: - spec.encryptionMethodName = POINTER("rc5"); - spec.encryptionParams = POINTER(&rc5Params); - rc5Params.version = 0x10; - // FIXME - get this from context attr - rc5Params.rounds = 1; - rc5Params.wordSizeInBits = 32; - break; - case CSSM_ALGID_RC2: - { - spec.encryptionMethodName = POINTER("rc2"); - spec.encryptionParams = POINTER(&rc2Params); - // effective key size in bits - either from Context, - // or the key - uint32 bits = context.getInt(CSSM_ATTRIBUTE_EFFECTIVE_BITS); - if(bits == 0) { - // OK, try the key - CssmKey &key = context.get(CSSM_ATTRIBUTE_KEY, - CSSMERR_CSP_MISSING_ATTR_KEY); - bits = key.KeyHeader.LogicalKeySizeInBits; - } - rc2Params.effectiveKeyBits = bits; - break; - } - } - - // feedback mode - cssmMode = context.getInt(CSSM_ATTRIBUTE_MODE); - switch (cssmMode) { - /* no mode attr --> 0 == CSSM_ALGMODE_NONE, not currently supported */ - case CSSM_ALGMODE_CBCPadIV8: - requirePad = true; - // and fall thru - case CSSM_ALGMODE_CBC_IV8: - { - iv = context.get(CSSM_ATTRIBUTE_INIT_VECTOR, - CSSMERR_CSP_MISSING_ATTR_INIT_VECTOR); - spec.feedbackMethodName = POINTER("cbc"); - spec.feedbackParams = POINTER(&iv); - hasIV = true; - break; - } - case CSSM_ALGMODE_OFB_IV8: { - iv = context.get(CSSM_ATTRIBUTE_INIT_VECTOR, - CSSMERR_CSP_MISSING_ATTR_INIT_VECTOR); - spec.feedbackMethodName = POINTER("ofb"); - spec.feedbackParams = POINTER(&iv); - hasIV = true; - break; - } - case CSSM_ALGMODE_ECB: { - spec.feedbackMethodName = POINTER("ecb"); - spec.feedbackParams = POINTER(&blockSize); - break; - } - default: - errorLog1("BSafe symmetric init: illegal mode (%d)\n", (int)cssmMode); - CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_MODE); - } - - // padding - spec.paddingParams = NULL_PTR; - /* no padding attr --> 0 == PADDING_NONE */ - padEnable = false; - uint32 cssmPadding = context.getInt(CSSM_ATTRIBUTE_PADDING); - if(requirePad) { - switch(cssmPadding) { - case CSSM_PADDING_PKCS1: // for backwards compatibility - case CSSM_PADDING_PKCS5: - case CSSM_PADDING_PKCS7: - spec.paddingMethodName = POINTER("pad"); - padEnable = true; - break; - default: - CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING); - } - } - else { - if(cssmPadding != CSSM_PADDING_NONE) { - CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING); - } - else { - spec.paddingMethodName = POINTER("nopad"); - } - } - - // put it all together - setAlgorithm(AI_FeedbackCipher, &spec); // set BSafe algorithm - setKeyFromContext(context); // set BSafe key - cipherInit(); // common cryption init -} - -void BSafe::BlockCipherContext::RC4init( - const Context &context) -{ - setAlgorithm(AI_RC4, NULL); // set BSafe algorithm - setKeyFromContext(context); // set BSafe key - padEnable = false; - cipherInit(); // common cryption init -} - -void BSafe::BlockCipherContext::trackUpdate(size_t inSize, size_t outSize) -{ - size_t newPending = pending + inSize; - pending = newPending % blockSize; - - /* - * Most of the time, the max size buffered by BSAFE is - * blockSize - 1 bytes. When decrypting and padding is enabled, - * BSAFE buffers up to a full block. - */ - if(!mDirection && //Êdecrypting - padEnable && // padding - (pending == 0) && // mod result was 0 - (newPending > 0)) { // but nonzero total - /* BSAFE is holding a whole block in its buffer */ - pending = blockSize; - } - bbprintf("===trackUpdte: %s; inSize=%d newPending=%d pending=%d", - (mDirection ? "encrypt" : "decrypt"), - inSize, newPending, pending); -} - -size_t BSafe::BlockCipherContext::inputSize(size_t outSize) -{ - // if we have an 'outSize' output buffer, how many input bytes may we feed in? - size_t wholeBlocks = outSize / blockSize; - return wholeBlocks * blockSize - pending + (blockSize - 1); -} - -size_t BSafe::BlockCipherContext::outputSize(bool final, size_t inSize) -{ - // how much output buffer will we need for 'size' input bytes? - - size_t totalToGo = inSize + pending; - // total to go, rounded up to next block - size_t numBlocks = (totalToGo + blockSize - 1) / blockSize; - size_t outSize; - - /* - * encrypting: may get one additional block on final() if padding - * decrypting: outsize always <= insize - */ - if(mDirection && // encrypting - final && // last time - padEnable && // padding enabled - ((totalToGo % blockSize) == 0)) { // even ptext len - numBlocks++; // extra pad block - } - outSize = numBlocks * blockSize; - bbprintf("===outputSize: %s; final=%d inSize=%d pending=%d outSize=%d", - (mDirection ? "encrypt" : "decrypt"), - final, inSize, pending, outSize); - return outSize; -} - -void BSafe::BlockCipherContext::minimumProgress(size_t &inSize, size_t &outSize) -{ - // eat up buffer, proceed one full block - inSize = blockSize - pending; - outSize = blockSize; -} -#endif /* BSAFE_CSP_ENABLE */ diff --git a/OSX/libsecurity_apple_csp/lib/bsafecsp.h b/OSX/libsecurity_apple_csp/lib/bsafecsp.h deleted file mode 100644 index 14d4511f5..000000000 --- a/OSX/libsecurity_apple_csp/lib/bsafecsp.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - -#ifdef BSAFE_CSP_ENABLE - - -// -// bsafecsp - top C++ implementation layer for BSafe 4 -// -#ifndef _H_BSAFECSP -#define _H_BSAFECSP - -#include -#include "AppleCSP.h" - -/* Can't include AppleCSPSession.h due to circular dependency */ -class AppleCSPSession; - -// no longer a subclass of AlgorithmFactory due to -// differing setup() methods -class BSafeFactory : public AppleCSPAlgorithmFactory { -public: - - BSafeFactory( - Allocator *normAlloc = NULL, - Allocator *privAlloc = NULL) - { - setNormAllocator(normAlloc); - setPrivAllocator(privAlloc); - } - ~BSafeFactory() { } - - bool setup( - AppleCSPSession &session, - CSPFullPluginSession::CSPContext * &cspCtx, - const Context &context); - - static void setNormAllocator(Allocator *alloc); - static void setPrivAllocator(Allocator *alloc); - -}; - -#endif //_H_BSAFECSP -#endif /* BSAFE_CSP_ENABLE */ diff --git a/OSX/libsecurity_apple_csp/lib/bsafecspi.h b/OSX/libsecurity_apple_csp/lib/bsafecspi.h deleted file mode 100644 index f5d6d4fa6..000000000 --- a/OSX/libsecurity_apple_csp/lib/bsafecspi.h +++ /dev/null @@ -1,463 +0,0 @@ -/* - * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - -#ifdef BSAFE_CSP_ENABLE - - -// -// bsafecspi - implementation layer for C++ BSafe 4 interface -// -#ifndef _H_BSAFECSPI -#define _H_BSAFECSPI - -#include -#include "bsobjects.h" -#include "AppleCSPContext.h" -#include "AppleCSPSession.h" -#include -#include - -// -// The BSafe class is more of a namespace than anything else. -// Just think of it as the "static binder" for BSafe's objects. -// Note that we keep a global, static allocator. We have to; BSafe -// doesn't have any state management at that level. -// -class BSafe { - class BSafeContext; friend class BSafeContext; - class BSafeFactory; friend class BSafeFactory; - -public: - static void setNormAllocator(Allocator *alloc) - { assert(!normAllocator); normAllocator = alloc; } - static void setPrivAllocator(Allocator *alloc) - { assert(!privAllocator); privAllocator = alloc; } - - static bool setup( - AppleCSPSession &session, - CSPFullPluginSession::CSPContext * &cspCtx, - const Context &context); - -private: - // BSafe's memory allocators - static Allocator *normAllocator; - static Allocator *privAllocator; - friend POINTER T_malloc(unsigned int); - friend void T_free(POINTER); - friend POINTER T_realloc(POINTER, unsigned int); - - static const B_ALGORITHM_METHOD * const bsChooser[]; - -private: - // BSafe-specific BinaryKey class. - class BSafeBinaryKey : public BinaryKey { - - public: - BSafeBinaryKey( - bool isPub, - uint32 alg); // CSSM_ALGID_{RSA,DSA} - ~BSafeBinaryKey(); - void generateKeyBlob( - Allocator &allocator, - CssmData &blob, - CSSM_KEYBLOB_FORMAT &format, - AppleCSPSession &session, - const CssmKey *paramKey, /* optional, unused here */ - CSSM_KEYATTR_FLAGS &attrFlags); /* IN/OUT */ - - bool isPublic() { return mIsPublic; } - uint32 alg() { return mAlg; } - B_KEY_OBJ bsKey() { return mBsKey; } - - private: - bool mIsPublic; - uint32 mAlg; // CSSM_ALGID_{RSA,DSA} - B_KEY_OBJ mBsKey; - }; - -private: - // - // The BSafeContext class is the parent of all BSafe-used CSPContext objects. - // It implements the CSPContext operation functions (init, update, ...) in terms - // of pointer-to-member fields set by its subclasses. This may not be pretty, but - // it avoids every subclass having to re-implement all CSPContext operations. - // Beyond that, we implement a raftload of utility methods for our children. - // - class BSafeContext : public AppleCSPContext { - friend class BSafe; - public: - BSafeContext(AppleCSPSession &session); - virtual ~BSafeContext(); - - // called by CSPFullPluginSession - void init(const Context &context, bool encoding = true); - void update(const CssmData &data); - void update(void *inp, size_t &inSize, void *outp, size_t &outSize); - void final(CssmData &out); - void final(const CssmData &in); - size_t outputSize(bool final, size_t inSize); - - protected: - // install a BSafe algorithm into bsAlgorithm - void setAlgorithm(B_INFO_TYPE bAlgType, const void *info = NULL); - - // safely create bsKey - void createBsKey(); - - // set bsKey. The different versions are equivalent - void setKeyAtom(B_INFO_TYPE bKeyInfo, const void *info); - void setKeyFromItem(B_INFO_TYPE bKeyInfo, const BSafeItem &item) - { setKeyAtom(bKeyInfo, &item); } - void setKeyFromCssmKey(B_INFO_TYPE bKeyInfo, const CssmKey &key) - { BSafeItem item(key.KeyData); setKeyAtom(bKeyInfo, &item); } - void setKeyFromCssmData(B_INFO_TYPE bKeyInfo, const CssmData &keyData) - { BSafeItem item(keyData); setKeyAtom(bKeyInfo, &item); } - void setKeyFromContext(const Context &context, bool required = true); - - void setRefKey(CssmKey &key); - void setRsaOutSize(bool isPubKey); - - // create mRandom to be a suitable random-generator BSafe object (if it isn't yet) - void setRandom(); - - // trackUpdate is called during crypto-output. Hook it to keep track of data flow - virtual void trackUpdate(size_t in, size_t out); - - // destroy bsAlgorithm and bsKey so we can start over making them - void reset(); - - // clear key state - void destroyBsKey(); - - // determine if we can reuse the current bsAlgorithm - bool reusing(bool encode = true) - { - if (initialized && !opStarted && - (encode == encoding)) return true; - encoding = encode; - return false; - } - - public: - // - // These pointers-to-member are called by the BSafeContext operations - // (update, final). They must be set by a subclasses's init() method. - // Not all members are used by all types of operations - check the - // source when in doubt. - // - int (*inUpdate)(B_ALGORITHM_OBJ, POINTER, unsigned int, A_SURRENDER_CTX *); - int (*inOutUpdate)(B_ALGORITHM_OBJ, POINTER, unsigned int *, unsigned int, - POINTER, unsigned int, B_ALGORITHM_OBJ, A_SURRENDER_CTX *); - int (*inFinal)(B_ALGORITHM_OBJ, POINTER, unsigned int, A_SURRENDER_CTX *); - int (*inFinalR)(B_ALGORITHM_OBJ, POINTER, unsigned int, - B_ALGORITHM_OBJ, A_SURRENDER_CTX *); - int (*outFinalR)(B_ALGORITHM_OBJ, POINTER, unsigned int *, unsigned int, - B_ALGORITHM_OBJ, A_SURRENDER_CTX *); - int (*outFinal)(B_ALGORITHM_OBJ, POINTER, unsigned int *, unsigned int, - A_SURRENDER_CTX *); - - protected: - - // un-consted bsChooser for BSafe's consumption. BSafe's Bad - static B_ALGORITHM_METHOD **chooser() - { return const_cast(bsChooser); } - - // a placeholder for a surrender context. Not currently used - // @@@ should perhaps test for pthread cancel? --> thread abstraction - static A_SURRENDER_CTX * const bsSurrender; - - protected: - B_ALGORITHM_OBJ bsAlgorithm; // BSafe algorithm object or NULL - B_ALGORITHM_OBJ bsRandom; // PRNG algorithm - bool encoding; // encoding direction - bool initialized; // method init() has completed - bool opStarted; // method update() has been called - // generally means that we can't reuse - // the current bsAlgorithm - // - // We have a binKey only if the caller passed in a reference - // key. In that case we avoid deleting bsKey - which is a copy - // of binKey.bsKey - because a BinaryKey is persistent - // relative to this context. - // - BSafeBinaryKey *bsBinKey; - B_KEY_OBJ bsKey; // BSafe key object or NULL - - size_t mOutSize; // simple output size, if applicable - }; /* BSafeContext */ - - // contexts for BSafe digest operations - class DigestContext : public BSafeContext { - public: - // do all work in constructor. We have no directions; thus default init() works fine - DigestContext( - AppleCSPSession &session, - const Context &, - B_INFO_TYPE bAlgInfo, - size_t sz); - }; - - // common context features for BSafe cipher operations (both symmetric and asymmetric) - class CipherContext : public BSafeContext { - public: - CipherContext( - AppleCSPSession &session) : - BSafeContext(session), - pending(0) {} - - protected: - size_t pending; // bytes not eaten still pending (staged only) - public: - void cipherInit(); // common init code (must be called from init()) - }; - - // contexts for block cipher operations using symmetric algorithms - class BlockCipherContext : public CipherContext { - size_t blockSize; - uint32 cssmAlg; - uint32 cssmMode; - bool padEnable; - public: - BlockCipherContext( - AppleCSPSession &session, - const Context &, - size_t sz) : - CipherContext(session), - blockSize(sz) { } - void init(const Context &context, bool encrypting); - size_t inputSize(size_t outSize); - size_t outputSize(bool final, size_t inSize); - void minimumProgress(size_t &in, size_t &out); - void trackUpdate(size_t in, size_t out); - private: - // special case for RC4 - void RC4init(const Context &context); - }; - - // context for generating public/private key pairs - class BSafeKeyPairGenContext : public BSafeContext, - private AppleKeyPairGenContext { - public: - BSafeKeyPairGenContext( - AppleCSPSession &session, - const Context &) : - BSafeContext(session) {} - - // generate alg params, not handled by PublicKeyGenerateContext - // For DSA only. - void generate( - const Context &context, - uint32 bitSize, - CssmData ¶ms, - uint32 &attrCount, - Context::Attr * &attrs); - - // this one is specified in CSPFullPluginSession - void generate( - const Context &context, - CssmKey &pubKey, - CssmKey &privKey); - - // this one in AppleKeyPairGenContext - void generate( - const Context &context, - BinaryKey &pubBinKey, - BinaryKey &privBinKey, - uint32 &keySize); - - private: - void setupAlgorithm( - const Context &context, - uint32 &keySize); - - }; /* BSafeKeyPairGenContext */ - - // public key cipher operations - class PublicKeyCipherContext : public CipherContext { - public: - PublicKeyCipherContext( - AppleCSPSession &session, - const Context &) : - CipherContext(session) { } - void init(const Context &context, bool encrypting); - size_t inputSize(size_t outSize); // unlimited - }; - - // contexts for BSafe signing/verifying operations - class SigningContext : public BSafeContext { - B_INFO_TYPE algorithm; - public: - SigningContext( - AppleCSPSession &session, - const Context &, - B_INFO_TYPE bAlg, - size_t sz) : - BSafeContext(session), - algorithm(bAlg) { mOutSize = sz; } - void init(const Context &context, bool signing); - }; - - // contexts for BSafe MAC generation and verification - class MacContext : public BSafeContext { - B_INFO_TYPE algorithm; - public: - MacContext( - AppleCSPSession &session, - const Context &, - B_INFO_TYPE bAlg, - size_t sz) : - BSafeContext(session), - algorithm(bAlg) { mOutSize = sz; } - void init(const Context &context, bool signing); - void final(const CssmData &in); - }; - - // contexts for BSafe's random number generation - class RandomContext : public BSafeContext { - B_INFO_TYPE algorithm; - public: - RandomContext( - AppleCSPSession &session, - const Context &, - B_INFO_TYPE alg) : - BSafeContext(session), - algorithm(alg) { } - void init(const Context &context, bool); - void final(CssmData &data); - }; - - // symmetric key generation context - class SymmetricKeyGenContext : public BSafeContext, - private AppleSymmKeyGenContext { - public: - SymmetricKeyGenContext( - AppleCSPSession &session, - const Context &ctx, - uint32 minSizeInBits, - uint32 maxSizeInBits, - bool mustBeByteSized) : - BSafeContext(session), - AppleSymmKeyGenContext( - minSizeInBits, - maxSizeInBits, - mustBeByteSized) { } - - void generate( - const Context &context, - CssmKey &symKey, - CssmKey &dummyKey); - - }; - -public: - /* - * Stateless, private function to map a CSSM alg and pub/priv state - * to B_INFO_TYPE and format. Returns true on success, false on - * "I don't understand this algorithm". - */ - static bool bsafeAlgToInfoType( - CSSM_ALGORITHMS alg, - bool isPublic, - B_INFO_TYPE &infoType, // RETURNED - CSSM_KEYBLOB_FORMAT &format); // RETURNED - - /* check result of a BSafe call and throw on error */ - static void check(int status, bool isKeyOp = false); - - /* moved here from BSafeContext - now works on any key */ - template - static KI_Type *getKey(B_KEY_OBJ bKey, B_INFO_TYPE type) - { - POINTER p; - check(B_GetKeyInfo(&p, bKey, type), true); - return reinterpret_cast(p); - } - - - // - // The context generation table - see algmaker.cpp. - // -public: - // Base class for Maker classes - class MakerBase { - public: - virtual ~MakerBase() { } - virtual BSafeContext *make( - AppleCSPSession &session, - const Context &context) const = 0; - }; - - // One entry in Maker table - struct MakerTable { - CSSM_ALGORITHMS algorithmId; - CSSM_CONTEXT_TYPE algClass; - const MakerBase *maker; - ~MakerTable() { delete maker; } - }; - -private: - static bug_const MakerTable algorithms[]; - static const unsigned int algorithmCount; - - /* - * CSPKeyInfoProvider for BSafe keys - */ - class BSafeKeyInfoProvider : public CSPKeyInfoProvider - { -private: - BSafeKeyInfoProvider( - const CssmKey &cssmKey, - AppleCSPSession &session); - public: - static CSPKeyInfoProvider *provider( - const CssmKey &cssmKey, - AppleCSPSession &session); - ~BSafeKeyInfoProvider() { } - void CssmKeyToBinary( - CssmKey *paramKey, // optional - CSSM_KEYATTR_FLAGS &attrFlags, // IN/OUT - BinaryKey **binKey); // RETURNED - void QueryKeySizeInBits( - CSSM_KEY_SIZE &keySize); // RETURNED - }; - -}; /* BSAFE namespace */ - -/* - * BSAFE Key Info types. - */ -#define BLOB_IS_PUB_KEY_INFO 0 - -#if BLOB_IS_PUB_KEY_INFO - -/* X beta values */ -#define RSA_PUB_KEYINFO_TYPE KI_RSAPublicBER -#define RSA_PRIV_KEYINFO_TYPE KI_PKCS_RSAPrivateBER -#define DSA_PUB_KEYINFO_TYPE KI_DSAPublicBER -#define DSA_PRIV_KEYINFO_TYPE KI_DSAPrivateBER - -#else /* BLOB_IS_PUB_KEY_INFO */ - -#define RSA_PUB_KEYINFO_TYPE KI_RSAPublic -#define RSA_PRIV_KEYINFO_TYPE KI_PKCS_RSAPrivateBER -#define DSA_PUB_KEYINFO_TYPE KI_DSAPublicBER -#define DSA_PRIV_KEYINFO_TYPE KI_DSAPrivateBER - -#endif - -#endif //_H_BSAFECSP -#endif /* BSAFE_CSP_ENABLE */ diff --git a/OSX/libsecurity_apple_csp/lib/bsobjects.h b/OSX/libsecurity_apple_csp/lib/bsobjects.h deleted file mode 100644 index 0491af22f..000000000 --- a/OSX/libsecurity_apple_csp/lib/bsobjects.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - -#ifdef BSAFE_CSP_ENABLE - - -// -// bsobjects - C++ adaptations of popular BSafe 4 object types -// -#ifndef _H_BSOBJECTS -#define _H_BSOBJECTS - -#include -#include -#include -#include - -// -// A PodWrapper for BSafe's ITEM objects -// -class BSafeItem : public PodWrapper { -public: - BSafeItem() { ((ITEM *)this)->data = NULL; len = 0; } - BSafeItem(void *addr, size_t sz) - { ((ITEM *)this)->data = (unsigned char *)addr; len = sz; } - BSafeItem(const CSSM_DATA &cData) - { ((ITEM *)this)->data = cData.Data; len = cData.Length; } - BSafeItem(const ITEM &cData) - { *(ITEM *)this = cData; } - - void operator = (const CssmData &cData) - { ((ITEM *)this)->data = (unsigned char *)cData.data(); len = cData.length(); } - - void *data() const { return ((ITEM *)this)->data; } - size_t length() const { return len; } - - template - T copy(Allocator &alloc) - { return T(memcpy(alloc.malloc(length()), data(), length()), length()); } - - template - T *copyp(Allocator &alloc) - { return new(alloc) T(copy(alloc)); } - - void *operator new (size_t size, Allocator &alloc) - { return alloc.malloc(size); } -}; - -#endif //_H_BSOBJECTS -#endif /* BSAFE_CSP_ENABLE */ diff --git a/OSX/libsecurity_apple_csp/lib/desContext.cpp b/OSX/libsecurity_apple_csp/lib/desContext.cpp index 43890cfdc..22531e096 100644 --- a/OSX/libsecurity_apple_csp/lib/desContext.cpp +++ b/OSX/libsecurity_apple_csp/lib/desContext.cpp @@ -65,6 +65,7 @@ void DESContext::init( if (DesInst != NULL) { CCCryptorRelease(DesInst); + DesInst = NULL; } (void) CCCryptorCreateWithMode(0, kCCModeECB, kCCAlgorithmDES, ccDefaultPadding, NULL, keyData, kCCKeySizeDES, NULL, 0, 0, 0, &DesInst); @@ -152,6 +153,7 @@ void DES3Context::init( if (DesInst != NULL) { CCCryptorRelease(DesInst); + DesInst = NULL; } (void) CCCryptorCreateWithMode(0, kCCModeECB, kCCAlgorithm3DES, ccDefaultPadding, NULL, keyData, kCCKeySize3DES, NULL, 0, 0, 0, &DesInst); diff --git a/OSX/libsecurity_apple_csp/lib/memory.cpp b/OSX/libsecurity_apple_csp/lib/memory.cpp deleted file mode 100644 index 036db1426..000000000 --- a/OSX/libsecurity_apple_csp/lib/memory.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - -#ifdef BSAFE_CSP_ENABLE - - -// -// memory - memory functions for BSafe -// -#include -#include -#include "bsafecspi.h" - - -// declared in bsafecspi.h.... -Allocator *BSafe::normAllocator; -Allocator *BSafe::privAllocator; - -// We use the private allocator for all BSAFE-alalocated memory. -// Memory allocated my BSAFE should never be visible by apps. - -POINTER CALL_CONV T_malloc (unsigned int size) -{ - return reinterpret_cast(BSafe::privAllocator->malloc(size)); -} - -POINTER CALL_CONV T_realloc (POINTER p, unsigned int size) -{ - POINTER result; - if ((result = (POINTER)BSafe::privAllocator->realloc(p, size)) == NULL_PTR) - free (p); - return (result); -} - -void CALL_CONV T_free (POINTER p) -{ - BSafe::privAllocator->free(p); -} -#endif /* BSAFE_CSP_ENABLE */ diff --git a/OSX/libsecurity_apple_csp/lib/miscAlgFactory.cpp b/OSX/libsecurity_apple_csp/lib/miscAlgFactory.cpp index 89b81d2c5..ae07d2933 100644 --- a/OSX/libsecurity_apple_csp/lib/miscAlgFactory.cpp +++ b/OSX/libsecurity_apple_csp/lib/miscAlgFactory.cpp @@ -37,22 +37,6 @@ #include "castContext.h" #include -/* - * These #defines are mainly to facilitate measuring the performance of our own - * implementation vs. the ones in BSafe. This factory gets called first; if - * we disable e.g. DES here the BSAFE version will be used. - */ -#ifdef BSAFE_CSP_ENABLE - -#define MAF_DES_ENABLE 0 -#define MAF_DES3_ENABLE 0 -#define MAF_RC2_ENABLE 0 -#define MAF_RC4_ENABLE 0 -#define MAF_RC5_ENABLE 0 -#define MAF_MAC_ENABLE 0 - -#else /* !BSAFE_CSP_ENABLE, normal case */ - #define MAF_DES_ENABLE 1 #define MAF_DES3_ENABLE 1 #define MAF_RC2_ENABLE 1 @@ -60,8 +44,6 @@ #define MAF_RC5_ENABLE 1 #define MAF_MAC_ENABLE 1 -#endif /* BSAFE_CSP_ENABLE */ - #if (!MAF_DES_ENABLE || !MAF_DES3_ENABLE || !MAF_RC2_ENABLE || !MAF_RC4_ENABLE || \ !MAF_RC5_ENABLE || !MAF_MAC_ENABLE) #warning Internal DES/RC2/RC4/RC5/Mac implementation disabled! diff --git a/OSX/libsecurity_apple_csp/lib/miscalgorithms.cpp b/OSX/libsecurity_apple_csp/lib/miscalgorithms.cpp deleted file mode 100644 index 10832749a..000000000 --- a/OSX/libsecurity_apple_csp/lib/miscalgorithms.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. - * - * The contents of this file constitute Original Code as defined in and are - * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. Please obtain - * a copy of the License at http://www.apple.com/publicsource and read it before - * using this file. - * - * This 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. - */ - -#ifdef BSAFE_CSP_ENABLE - -// -// miscalgorithms - miscellaneous BSafe context creators and managers -// -#include "bsafecspi.h" - -#include // debug - - -// -// Digest algorithms. -// NOTE: There is no init() method, since BSafe digest algorithms re-initialize -// automatically and there is no directional difference. -// -BSafe::DigestContext::DigestContext( - AppleCSPSession &session, - const Context &, - B_INFO_TYPE bAlgInfo, - size_t sz) - : BSafeContext(session) -{ - mOutSize = sz; - inUpdate = B_DigestUpdate; - outFinal = B_DigestFinal; - setAlgorithm(bAlgInfo); - check(B_DigestInit(bsAlgorithm, bsKey, chooser(), bsSurrender)); - initialized = true; -} - - -// -// Signing/Verifying algorithms -// -// FIXME: -// We really should match the key algorithm to the sign/vfy -// algorithm. Also: verify key usage bits. -void BSafe::SigningContext::init( - const Context &context, - bool signing) -{ - if (reusing(signing)) - return; // all set to go - - setAlgorithm(algorithm, NULL); - setKeyFromContext(context); // may set outSize for some keys - - if (signing) { - check(B_SignInit(bsAlgorithm, bsKey, chooser(), bsSurrender)); - setRandom(); // needed by some signing algorithms - inUpdate = B_SignUpdate; - outFinalR = B_SignFinal; - outFinal = NULL; - } else { - check(B_VerifyInit(bsAlgorithm, bsKey, chooser(), bsSurrender)); - inUpdate = B_VerifyUpdate; - inFinalR = B_VerifyFinal; - inFinal = NULL; - } -} - - -// -// MAC algorithms. -// Note that BSafe treats MACs as digest algorithms - it has no MAC algorithm -// class. Thus, verifying consists of "digesting" followed by comparing the result. -// -// FIXME : what kind of key do we expect here? For now, any old -// symmetric key will work... -// -void BSafe::MacContext::init( - const Context &context, - bool signing) -{ - if (reusing(signing)) - return; // all set to go - - B_DIGEST_SPECIFIER digestSpec; - digestSpec.digestInfoType = algorithm; - digestSpec.digestInfoParams = NULL; - - setAlgorithm(AI_HMAC, &digestSpec); - setKeyFromContext(context); - check(B_DigestInit(bsAlgorithm, bsKey, chooser(), bsSurrender)); - - if (signing) { - inUpdate = B_DigestUpdate; - outFinal = B_DigestFinal; - } else { - inUpdate = B_DigestUpdate; - // need not set xxFinal - we override final(). - } -} - -void BSafe::MacContext::final(const CssmData &in) -{ - // we need to perform a DigestFinal step into a temp buffer and compare to 'in' - void *digest = normAllocator->malloc(in.length()); - unsigned int length; - check(B_DigestFinal(bsAlgorithm, POINTER(digest), &length, in.length(), bsSurrender)); - bool verified = length == in.length() && !memcmp(digest, in.data(), in.length()); - normAllocator->free(digest); - initialized = false; - if (!verified) - CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED); -} - - -// -// Random-number generation algorithms. -// Note that we don't use bsRandom, since that's our internal fixed "best to use" method, -// not the one the user asked for. -// NOTE: We freeze the output size at init(). -// -void BSafe::RandomContext::init(const Context &context, bool) -{ - reset(); // throw away, we need to re-seed anyway - setAlgorithm(algorithm, NULL); // MD5 generator mode (RSA proprietary) - check(B_RandomInit(bsAlgorithm, chooser(), bsSurrender)); - - // set/freeze output size - mOutSize = context.getInt(CSSM_ATTRIBUTE_OUTPUT_SIZE, CSSMERR_CSP_MISSING_ATTR_OUTPUT_SIZE); - - // seed the PRNG (if specified) - if (const CssmCryptoData *seed = context.get(CSSM_ATTRIBUTE_SEED)) { - const CssmData &seedValue = (*seed)(); - check(B_RandomUpdate(bsAlgorithm, POINTER(seedValue.data()), seedValue.length(), bsSurrender)); - } -} - -void BSafe::RandomContext::final(CssmData &data) -{ - check(B_GenerateRandomBytes(bsAlgorithm, POINTER(data.data()), mOutSize, bsSurrender)); -} -#endif /* BSAFE_CSP_ENABLE */ diff --git a/OSX/libsecurity_apple_csp/lib/opensshCoding.cpp b/OSX/libsecurity_apple_csp/lib/opensshCoding.cpp index 126e3a80b..5a42320cf 100644 --- a/OSX/libsecurity_apple_csp/lib/opensshCoding.cpp +++ b/OSX/libsecurity_apple_csp/lib/opensshCoding.cpp @@ -111,10 +111,15 @@ static CSSM_RETURN appendBigNum2( return CSSMERR_CSP_INTERNAL_ERROR; } int numBytes = BN_num_bytes(bn); - unsigned char buf[numBytes]; + unsigned char *buf = (unsigned char*)malloc(numBytes); + if (buf == NULL) { + dprintf("appendBigNum: Cannot allocate a temp BN buffer\n"); + return CSSMERR_CSSM_MEMORY_ERROR; + } int moved = BN_bn2bin(bn, buf); if(moved != numBytes) { dprintf("appendBigNum: BN_bn2bin() screwup\n"); + free(buf); return CSSMERR_CSP_INTERNAL_ERROR; } bool appendZero = false; @@ -131,6 +136,7 @@ static CSSM_RETURN appendBigNum2( } CFDataAppendBytes(cfOut, buf, numBytes); memset(buf, 0, numBytes); + free(buf); return CSSM_OK; } diff --git a/OSX/libsecurity_apple_csp/lib/opensshWrap.cpp b/OSX/libsecurity_apple_csp/lib/opensshWrap.cpp index 988943b28..07185bc28 100644 --- a/OSX/libsecurity_apple_csp/lib/opensshWrap.cpp +++ b/OSX/libsecurity_apple_csp/lib/opensshWrap.cpp @@ -31,13 +31,13 @@ #include "AppleCSPUtils.h" #include "AppleCSPKeys.h" #include "RSA_DSA_keys.h" +#include "SecRandom.h" #include "opensshCoding.h" #include "cspdebugging.h" #include #include #include #include -#include #include static const char *authfile_id_string = "SSH PRIVATE KEY FILE FORMAT 1.1\n"; @@ -376,8 +376,7 @@ CSSM_RETURN encodeOpenSSHv1PrivKey( /* [0..3] check bytes */ UInt8 checkBytes[4]; - DevRandomGenerator rng = DevRandomGenerator(); - rng.random(checkBytes, 2); + MacOSError::check(SecRandomCopyBytes(kSecRandomDefault, 2, checkBytes)) ; checkBytes[2] = checkBytes[0]; checkBytes[3] = checkBytes[1]; CFDataAppendBytes(ptext, checkBytes, 4); @@ -402,7 +401,12 @@ CSSM_RETURN encodeOpenSSHv1PrivKey( /* encrypt it */ ptextLen = CFDataGetLength(ptext); - unsigned char ctext[ptextLen]; + unsigned char *ctext = (unsigned char*)malloc(ptextLen); + if(ctext == NULL) { + ourRtn = CSSMERR_CSSM_MEMORY_ERROR; + goto errOut; + } + unsigned ctextLen; ourRtn = ssh1DES3Crypt(cipherSpec, true, (unsigned char *)CFDataGetBytePtr(ptext), (unsigned)ptextLen, @@ -420,6 +424,7 @@ CSSM_RETURN encodeOpenSSHv1PrivKey( CFReleaseNull(cfOut); cleanup: /* it would be proper to zero out ptext here, but we can't do that to a CFData */ + free(ctext); CFRelease(ptext); return ourRtn; } diff --git a/OSX/libsecurity_apple_x509_cl/lib/DecodedExtensions.h b/OSX/libsecurity_apple_x509_cl/lib/DecodedExtensions.h index a44f61881..7b7f7589c 100644 --- a/OSX/libsecurity_apple_x509_cl/lib/DecodedExtensions.h +++ b/OSX/libsecurity_apple_x509_cl/lib/DecodedExtensions.h @@ -28,6 +28,7 @@ #include #include +#include #include "cldebugging.h" diff --git a/OSX/libsecurity_apple_x509_cl/lib/DecodedItem.cpp b/OSX/libsecurity_apple_x509_cl/lib/DecodedItem.cpp index 0dab4560a..797688038 100644 --- a/OSX/libsecurity_apple_x509_cl/lib/DecodedItem.cpp +++ b/OSX/libsecurity_apple_x509_cl/lib/DecodedItem.cpp @@ -86,7 +86,7 @@ const DecodedExten *DecodedItem::findDecodedExt( } } if(rtnExt != NULL) { - /* sucessful return */ + /* successful return */ if(index == 0) { numFields = found; } diff --git a/OSX/libsecurity_apple_x509_cl/lib/clNssUtils.cpp b/OSX/libsecurity_apple_x509_cl/lib/clNssUtils.cpp index bee31697e..d94b373d2 100644 --- a/OSX/libsecurity_apple_x509_cl/lib/clNssUtils.cpp +++ b/OSX/libsecurity_apple_x509_cl/lib/clNssUtils.cpp @@ -50,7 +50,6 @@ void *ArenaAllocator::malloc(size_t len) throw(std::bad_alloc) /* intentionally not implemented, should never be called */ void ArenaAllocator::free(void *p) throw() { - throw std::bad_alloc(); } void *ArenaAllocator::realloc(void *p, size_t len) throw(std::bad_alloc) diff --git a/OSX/libsecurity_apple_x509_tp/lib/TPCertInfo.cpp b/OSX/libsecurity_apple_x509_tp/lib/TPCertInfo.cpp index 62b6f7b81..a7e1a99b4 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/TPCertInfo.cpp +++ b/OSX/libsecurity_apple_x509_tp/lib/TPCertInfo.cpp @@ -2036,7 +2036,7 @@ CSSM_RETURN TPCertGroup::buildCertGroup( * certs' mUsed state. * Also handle Radar 23734683, endless loop of untrusted roots. */ - if(isInGroup(*issuerCert) || gatheredCerts->isInGroup(*issuerCert)) { + if(isInGroup(*issuerCert) || (gatheredCerts && gatheredCerts->isInGroup(*issuerCert))) { tpDebug("buildCertGroup: Multiple instances of cert"); delete issuerCert; issuerCert = NULL; diff --git a/OSX/libsecurity_apple_x509_tp/lib/TPDatabase.cpp b/OSX/libsecurity_apple_x509_tp/lib/TPDatabase.cpp index 3870a8c86..116255a7c 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/TPDatabase.cpp +++ b/OSX/libsecurity_apple_x509_tp/lib/TPDatabase.cpp @@ -435,7 +435,7 @@ static CSSM_DB_UNIQUE_RECORD_PTR tpCrlLookup( else { /* right now */ StLock _(tpTimeLock()); - timeAtNowPlus(0, TIME_CSSM, timeStr); + timeAtNowPlus(0, TP_TIME_CSSM, timeStr); } CSSM_DATA timeData; timeData.Data = (uint8 *)timeStr; diff --git a/OSX/libsecurity_apple_x509_tp/lib/TPNetwork.cpp b/OSX/libsecurity_apple_x509_tp/lib/TPNetwork.cpp index bc9cf3fe5..0e6cdc139 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/TPNetwork.cpp +++ b/OSX/libsecurity_apple_x509_tp/lib/TPNetwork.cpp @@ -106,7 +106,7 @@ static CSSM_RETURN tpCrlViaNet( /* verifyTime: we want a CRL that's valid right now. */ { StLock _(tpTimeLock()); - timeAtNowPlus(0, TIME_CSSM, cssmTime); + timeAtNowPlus(0, TP_TIME_CSSM, cssmTime); } crtn = tpFetchViaNet(url, issuer, LT_Crl, cssmTime, alloc, crlData); diff --git a/OSX/libsecurity_apple_x509_tp/lib/ocspRequest.cpp b/OSX/libsecurity_apple_x509_tp/lib/ocspRequest.cpp index c609b7801..460af75a8 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/ocspRequest.cpp +++ b/OSX/libsecurity_apple_x509_tp/lib/ocspRequest.cpp @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include @@ -159,8 +159,8 @@ const CSSM_DATA *OCSPRequest::encode() /* one extension - the nonce */ if(mGenNonce) { - DevRandomGenerator drg; - drg.random(nonceBytes, OCSP_NONCE_SIZE); + MacOSError::check(SecRandomCopyBytes(kSecRandomDefault, OCSP_NONCE_SIZE, nonceBytes)); + nonce = new OCSPNonce(mCoder, false, nonceData); extenArray[0] = nonce->nssExt(); tbs.requestExtensions = extenArray; diff --git a/OSX/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp b/OSX/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp index 3aee72f92..28e9e1793 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp +++ b/OSX/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp @@ -136,10 +136,10 @@ void AppleTPSession::freeX509Name( */ #define TP_FOUR_DIGIT_YEAR 0 #if TP_FOUR_DIGIT_YEAR -#define TP_TIME_FORMAT TIME_GEN +#define TP_TIME_FORMAT TP_TIME_GEN #define TP_TIME_TAG BER_TAG_GENERALIZED_TIME #else -#define TP_TIME_FORMAT TIME_UTC +#define TP_TIME_FORMAT TP_TIME_UTC #define TP_TIME_TAG BER_TAG_UTC_TIME #endif /* TP_FOUR_DIGIT_YEAR */ diff --git a/OSX/libsecurity_apple_x509_tp/lib/tpPolicies.cpp b/OSX/libsecurity_apple_x509_tp/lib/tpPolicies.cpp index cdedecc7f..786c21f1e 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/tpPolicies.cpp +++ b/OSX/libsecurity_apple_x509_tp/lib/tpPolicies.cpp @@ -167,9 +167,6 @@ const CSSM_OID CSSMOID_PIV_AUTH = {PIV_AUTH_OID_LEN, (uint8 *)OID_PIV_AUTH}; static const uint8 OID_PIV_AUTH_2048[] = {PIV_AUTH_2048_OID}; const CSSM_OID CSSMOID_PIV_AUTH_2048 = {PIV_AUTH_2048_OID_LEN, (uint8 *)OID_PIV_AUTH_2048}; -static CSSM_RETURN tp_verifyAppleIDSharingOpts(TPCertGroup &certGroup, - const CSSM_DATA *fieldOpts, // optional Common Name - const iSignCertInfo *certInfo); /* * Setup a single iSignExtenInfo. Called once per known extension * per cert. @@ -1990,7 +1987,7 @@ static CSSM_RETURN tp_verifyMacAppStoreReceiptOpts( if (!isCertInfo->basicConstraints.present) { - tpPolicyError("tp_verifyAppleIDSharingOpts: no basicConstraints in intermediate"); + tpPolicyError("tp_verifyMacAppStoreReceiptOpts: no basicConstraints in intermediate"); if (tpCert->addStatusCode(CSSMERR_APPLETP_CS_NO_BASIC_CONSTRAINTS)) return CSSMERR_APPLETP_CS_NO_BASIC_CONSTRAINTS; } @@ -2037,177 +2034,6 @@ bool certificatePoliciesContainsOID(const CE_CertPolicies *certPolicies, const C return false; } - -/* - * Verify Apple ID Sharing options. - * - * -- Do basic cert validation (OCSP-based certs) - * -- Validate that the cert is an Apple ID sharing cert: - * has a custom extension: OID: Apple ID Sharing Certificate ( 1 2 840 113635 100 4 7 ) - * (CSSMOID_APPLE_EXTENSION_APPLEID_SHARING) - * EKU should have both client and server authentication - * chains to the "Apple Application Integration Certification Authority" intermediate - * -- optionally has a client-specified common name, which is the Apple ID account's UUID. - - * -- Must have one intermediate cert ("Apple Application Integration Certification Authority") - * -- intermediate must have basic constraints with path length 0 - * -- intermediate has CSSMOID_APPLE_EXTENSION_AAI_INTERMEDIATE extension (OID 1 2 840 113635 100 6 2 3) - OR APPLE_EXTENSION_AAI_INTERMEDIATE_2 - */ - -static CSSM_RETURN tp_verifyAppleIDSharingOpts(TPCertGroup &certGroup, - const CSSM_DATA *fieldOpts, // optional Common Name - const iSignCertInfo *certInfo) // all certs, size certGroup.numCerts() -{ - unsigned numCerts = certGroup.numCerts(); - const iSignCertInfo *isCertInfo; - TPCertInfo *tpCert; - // const CE_BasicConstraints *bc; // currently unused - CE_ExtendedKeyUsage *eku; - CSSM_RETURN crtn = CSSM_OK; - unsigned int serverNameLen = 0; - const char *serverName = NULL; - - // The CSSM_APPLE_TP_SMIME_OPTIONS pointer is optional as is everything in it. - if (fieldOpts && fieldOpts->Data) - { - CSSM_APPLE_TP_SSL_OPTIONS *sslOpts = (CSSM_APPLE_TP_SSL_OPTIONS *)fieldOpts->Data; - switch (sslOpts->Version) - { - case CSSM_APPLE_TP_SSL_OPTS_VERSION: - if (fieldOpts->Length != sizeof(CSSM_APPLE_TP_SSL_OPTIONS)) - return CSSMERR_TP_INVALID_POLICY_IDENTIFIERS; - break; - /* handle backwards compatibility here if necessary */ - default: - return CSSMERR_TP_INVALID_POLICY_IDENTIFIERS; - } - serverNameLen = sslOpts->ServerNameLen; - serverName = sslOpts->ServerName; - } - - //------------------------------------------------------------------------ - - if (numCerts != 3) - { - if (!certGroup.isAllowedError(CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH)) - { - tpPolicyError("tp_verifyAppleIDSharingOpts: numCerts %u", numCerts); - return CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH; - } - else - if (numCerts < 3) - { - /* this error allowed, but no intermediate...check leaf */ - goto checkLeaf; - } - } - - /* verify intermediate cert */ - isCertInfo = &certInfo[1]; - tpCert = certGroup.certAtIndex(1); - - if (!isCertInfo->basicConstraints.present) - { - tpPolicyError("tp_verifyAppleIDSharingOpts: no basicConstraints in intermediate"); - if (tpCert->addStatusCode(CSSMERR_APPLETP_CS_NO_BASIC_CONSTRAINTS)) - return CSSMERR_APPLETP_CS_NO_BASIC_CONSTRAINTS; - } - -checkLeaf: - - /* verify leaf cert */ - isCertInfo = &certInfo[0]; - tpCert = certGroup.certAtIndex(0); - - /* host name check is optional */ - if (serverNameLen != 0) - { - if (serverName == NULL) - return CSSMERR_TP_INVALID_POINTER; - - /* convert caller's hostname string to lower case */ - char *hostName = (char *)certGroup.alloc().malloc(serverNameLen); - memmove(hostName, serverName, serverNameLen); - tpToLower(hostName, serverNameLen); - - /* Check common name... */ - - bool fieldFound; - CSSM_BOOL match = tpCompareSubjectName(*tpCert, SN_CommonName, false, hostName, - serverNameLen, fieldFound); - - certGroup.alloc().free(hostName); - if (!match && tpCert->addStatusCode(CSSMERR_APPLETP_HOSTNAME_MISMATCH)) - return CSSMERR_APPLETP_HOSTNAME_MISMATCH; - } - - if (certInfo->certificatePolicies.present) - { - const CE_CertPolicies *certPolicies = - &isCertInfo->certificatePolicies.extnData->certPolicies; - if (!certificatePoliciesContainsOID(certPolicies, &CSSMOID_APPLEID_SHARING_CERT_POLICY)) - if (tpCert->addStatusCode(CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION)) - return CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION; - } - else - if (tpCert->addStatusCode(CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION)) - return CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION; - - if (!isCertInfo->extendKeyUsage.present) - { - tpPolicyError("tp_verifyAppleIDSharingOpts: no extendedKeyUse in leaf"); - if (tpCert->addStatusCode(CSSMERR_APPLETP_CS_NO_EXTENDED_KEY_USAGE)) - return crtn ? crtn : CSSMERR_APPLETP_CS_NO_EXTENDED_KEY_USAGE; - - /* have to skip remainder */ - return CSSM_OK; - } - - // Check that certificate can do Client and Server Authentication (EKU) - eku = &isCertInfo->extendKeyUsage.extnData->extendedKeyUsage; - assert(eku != NULL); - if(eku->numPurposes != 2) - { - tpPolicyError("tp_verifyAppleIDSharingOpts: bad eku->numPurposes (%lu)", - (unsigned long)eku->numPurposes); - if (tpCert->addStatusCode(CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE)) - { - if (crtn == CSSM_OK) - crtn = CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE; - } - return crtn; - } - bool canDoClientAuth = false, canDoServerAuth = false, ekuError = false; - for (int ix=0;ix<2;ix++) - { - if (tpCompareOids(&eku->purposes[ix], &CSSMOID_ClientAuth)) - canDoClientAuth = true; - else - if (tpCompareOids(&eku->purposes[ix], &CSSMOID_ServerAuth)) - canDoServerAuth = true; - else - { - ekuError = true; - break; - } - } - - if (!(canDoClientAuth && canDoServerAuth)) - ekuError = true; - if (ekuError) - { - tpPolicyError("tp_verifyAppleIDSharingOpts: bad EKU in leaf"); - if (tpCert->addStatusCode(CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE)) - { - if (crtn == CSSM_OK) - crtn = CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE; - } - } - - return crtn; -} - /* * Verify Time Stamping (RFC3161) policy options. * @@ -3325,8 +3151,11 @@ CSSM_RETURN tp_policyVerify( policyError = tp_verifyMacAppStoreReceiptOpts(*certGroup, policyFieldData, certInfo); break; case kTP_AppleIDSharing: - policyError = tp_verifyAppleIDSharingOpts(*certGroup, policyFieldData, certInfo); - break; + /* As of macOS 10.12, this code path should be unused. Until we can remove this + * module entirely, ensure that no Apple ID evaluations take this path. [10119995] */ + tpPolicyError("tp_policyVerify: unexpected attempt to use legacy kTP_AppleIDSharing"); + policyFail = CSSM_TRUE; + abort(); case kTP_TimeStamping: policyError = tp_verifyTimeStampingOpts(*certGroup, policyFieldData, certInfo); break; diff --git a/OSX/libsecurity_apple_x509_tp/lib/tpTime.c b/OSX/libsecurity_apple_x509_tp/lib/tpTime.c index 7d6cc7a9e..058cab00f 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/tpTime.c +++ b/OSX/libsecurity_apple_x509_tp/lib/tpTime.c @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. - * + * Copyright (c) 2000-2001,2011-2012,2014-2019 Apple Inc. All Rights Reserved. + * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). * You may not use this file except in compliance with the License. Please obtain * a copy of the License at http://www.apple.com/publicsource and read it before * using this file. - * + * * This 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 @@ -20,7 +20,7 @@ * tpTime.c - cert related time functions * */ - + #include "tpTime.h" #include #include @@ -31,7 +31,7 @@ /* * Given a string containing either a UTC-style or "generalized time" * time string, convert to a CFDateRef. Returns nonzero on - * error. + * error. */ int timeStringToCfDate( const char *str, @@ -49,11 +49,11 @@ int timeStringToCfDate( CFGregorianDate gd; CFTimeZoneRef timeZone; CFTimeInterval gmtOff = 0; - + if((str == NULL) || (len == 0) || (cfDate == NULL)) { return 1; } - + /* tolerate NULL terminated or not */ if(str[len - 1] == '\0') { len--; @@ -77,12 +77,12 @@ int timeStringToCfDate( case LOCALIZED_TIME_STRLEN: // "YYYYMMDDhhmmssThhmm" (where T=[+,-]) isLocal = 1; break; - default: // unknown format + default: // unknown format return 1; } - + cp = (char *)str; - + /* check that all characters except last (or timezone indicator, if localized) are digits */ for(i=0; i<(len - 1); i++) { if ( !(isdigit(cp[i])) ) @@ -101,7 +101,7 @@ int timeStringToCfDate( return 1; } } - + /* YEAR */ szTemp[0] = *cp++; szTemp[1] = *cp++; @@ -111,13 +111,13 @@ int timeStringToCfDate( szTemp[3] = *cp++; szTemp[4] = '\0'; } - else { + else { szTemp[2] = '\0'; } x = atoi( szTemp ); if(isUtc) { - /* - * 2-digit year. + /* + * 2-digit year. * 0 <= year < 50 : assume century 21 * 50 <= year < 70 : illegal per PKIX * ...though we allow this as of 10/10/02...dmitch @@ -133,7 +133,7 @@ int timeStringToCfDate( */ else { /* century 20 */ - x += 1900; + x += 1900; } } gd.year = x; @@ -194,7 +194,7 @@ int timeStringToCfDate( } gd.second = x; } - + if (isLocal) { /* ZONE INDICATOR */ switch(*cp++) { @@ -263,19 +263,19 @@ int compareTimes( * (UTC_TIME_STRLEN+1), (GENERALIZED_TIME_STRLEN+1), or (CSSM_TIME_STRLEN+1) * respectively. Caller must hold tpTimeLock. */ -void timeAtNowPlus(unsigned secFromNow, +void timeAtNowPlus(unsigned secFromNow, TpTimeSpec timeSpec, char *outStr) { struct tm utc; time_t baseTime; - + baseTime = time(NULL); baseTime += (time_t)secFromNow; utc = *gmtime(&baseTime); - + switch(timeSpec) { - case TIME_UTC: + case TP_TIME_UTC: /* UTC - 2 year digits - code which parses this assumes that * (2-digit) years between 0 and 49 are in century 21 */ if(utc.tm_year >= 100) { @@ -285,16 +285,16 @@ void timeAtNowPlus(unsigned secFromNow, utc.tm_year /* + 1900 */, utc.tm_mon + 1, utc.tm_mday, utc.tm_hour, utc.tm_min, utc.tm_sec); break; - case TIME_GEN: + case TP_TIME_GEN: sprintf(outStr, "%04d%02d%02d%02d%02d%02dZ", - /* note year is relative to 1900, hopefully it'll have + /* note year is relative to 1900, hopefully it'll have * four valid digits! */ utc.tm_year + 1900, utc.tm_mon + 1, utc.tm_mday, utc.tm_hour, utc.tm_min, utc.tm_sec); break; - case TIME_CSSM: + case TP_TIME_CSSM: sprintf(outStr, "%04d%02d%02d%02d%02d%02d", - /* note year is relative to 1900, hopefully it'll have + /* note year is relative to 1900, hopefully it'll have * four valid digits! */ utc.tm_year + 1900, utc.tm_mon + 1, utc.tm_mday, utc.tm_hour, utc.tm_min, utc.tm_sec); @@ -306,7 +306,7 @@ void timeAtNowPlus(unsigned secFromNow, * Convert a time string, which can be in any of three forms (UTC, * generalized, or CSSM_TIMESTRING) into a CSSM_TIMESTRING. Caller * mallocs the result, which must be at least (CSSM_TIME_STRLEN+1) bytes. - * Returns nonzero if incoming time string is badly formed. + * Returns nonzero if incoming time string is badly formed. */ int tpTimeToCssmTimestring( const char *inStr, // not necessarily NULL terminated @@ -327,8 +327,8 @@ int tpTimeToCssmTimestring( tmp[1] = inStr[1]; tmp[2] = '\0'; year = atoi(tmp); - - /* + + /* * 0 <= year < 50 : assume century 21 * 50 <= year < 70 : illegal per PKIX * 70 < year <= 99 : assume century 20 @@ -353,7 +353,7 @@ int tpTimeToCssmTimestring( case GENERALIZED_TIME_STRLEN: memmove(outTime, inStr, inStrLen - 1); // don't copy the Z break; - + default: return 1; } diff --git a/OSX/libsecurity_apple_x509_tp/lib/tpTime.h b/OSX/libsecurity_apple_x509_tp/lib/tpTime.h index 0c9019a91..90fc8b98a 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/tpTime.h +++ b/OSX/libsecurity_apple_x509_tp/lib/tpTime.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2001,2011,2014 Apple Inc. All Rights Reserved. - * + * Copyright (c) 2000-2001,2011,2014-2019 Apple Inc. All Rights Reserved. + * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). * You may not use this file except in compliance with the License. Please obtain * a copy of the License at http://www.apple.com/publicsource and read it before * using this file. - * + * * This 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 @@ -20,7 +20,7 @@ * tpTime.h - cert related time functions * */ - + #ifndef _TP_TIME_H_ #define _TP_TIME_H_ @@ -36,14 +36,14 @@ extern "C" { #define UTC_TIME_NOSEC_LEN 11 #define UTC_TIME_STRLEN 13 #define CSSM_TIME_STRLEN 14 /* no trailing 'Z' */ -#define GENERALIZED_TIME_STRLEN 15 +#define GENERALIZED_TIME_STRLEN 15 #define LOCALIZED_UTC_TIME_STRLEN 17 #define LOCALIZED_TIME_STRLEN 19 /* * Given a string containing either a UTC-style or "generalized time" * time string, convert to a CFDateRef. Returns nonzero on - * error. + * error. */ extern int timeStringToCfDate( const char *str, @@ -59,7 +59,7 @@ extern int timeStringToCfDate( extern int compareTimes( CFDateRef t1, CFDateRef t2); - + /* * Create a time string, in either UTC (2-digit) or or Generalized (4-digit) * year format. Caller mallocs the output string whose length is at least @@ -67,9 +67,9 @@ extern int compareTimes( * respectively. Caller must hold tpTimeLock. */ typedef enum { - TIME_UTC, - TIME_GEN, - TIME_CSSM + TP_TIME_UTC = 0, + TP_TIME_GEN = 1, + TP_TIME_CSSM = 2 } TpTimeSpec; void timeAtNowPlus(unsigned secFromNow, @@ -80,7 +80,7 @@ void timeAtNowPlus(unsigned secFromNow, * Convert a time string, which can be in any of three forms (UTC, * generalized, or CSSM_TIMESTRING) into a CSSM_TIMESTRING. Caller * mallocs the result, which must be at least (CSSM_TIME_STRLEN+1) bytes. - * Returns nonzero if incoming time string is badly formed. + * Returns nonzero if incoming time string is badly formed. */ int tpTimeToCssmTimestring( const char *inStr, // not necessarily NULL terminated diff --git a/OSX/libsecurity_asn1/lib/SecAsn1Types.h b/OSX/libsecurity_asn1/lib/SecAsn1Types.h index 9cb362b91..78596a4e8 100644 --- a/OSX/libsecurity_asn1/lib/SecAsn1Types.h +++ b/OSX/libsecurity_asn1/lib/SecAsn1Types.h @@ -48,11 +48,7 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" -#if TARGET_OS_EMBEDDED || TARGET_IPHONE_SIMULATOR -/* @@@ We need something that tells us which platform we are building - for that let's us distinguish if we are doing an emulator build. */ - -typedef struct { +typedef struct cssm_data { size_t Length; uint8_t * __nullable Data; } SecAsn1Item, SecAsn1Oid; @@ -67,17 +63,6 @@ typedef struct { SecAsn1Item subjectPublicKey; } SecAsn1PubKeyInfo; -#else -#include -#include - -typedef CSSM_DATA SecAsn1Item; -typedef CSSM_OID SecAsn1Oid; -typedef CSSM_X509_ALGORITHM_IDENTIFIER SecAsn1AlgId; -typedef CSSM_X509_SUBJECT_PUBLIC_KEY_INFO SecAsn1PubKeyInfo; - -#endif - CF_ASSUME_NONNULL_BEGIN /* diff --git a/OSX/libsecurity_asn1/lib/SecNssCoder.cpp b/OSX/libsecurity_asn1/lib/SecNssCoder.cpp index 08bac8fb2..067fb8d89 100644 --- a/OSX/libsecurity_asn1/lib/SecNssCoder.cpp +++ b/OSX/libsecurity_asn1/lib/SecNssCoder.cpp @@ -25,7 +25,7 @@ */ #include -#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) +#if TARGET_OS_OSX #include "SecNssCoder.h" #include diff --git a/OSX/libsecurity_asn1/lib/X509Templates.h b/OSX/libsecurity_asn1/lib/X509Templates.h index c4532d14d..3822844f5 100644 --- a/OSX/libsecurity_asn1/lib/X509Templates.h +++ b/OSX/libsecurity_asn1/lib/X509Templates.h @@ -84,6 +84,9 @@ typedef struct { extern const SecAsn1Template kSecAsn1CertExtensionTemplate[]; extern const SecAsn1Template kSecAsn1SequenceOfCertExtensionTemplate[]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + /* * X.509 certificate object (the unsigned form) * @@ -192,6 +195,8 @@ typedef struct { extern const SecAsn1Template kSecAsn1SignedCertOrCRLTemplate[]; +#pragma clang diagnostic pop + #ifdef __cplusplus } #endif diff --git a/OSX/libsecurity_asn1/lib/asn1Templates.h b/OSX/libsecurity_asn1/lib/asn1Templates.h index ec00625f1..9ee99fada 100644 --- a/OSX/libsecurity_asn1/lib/asn1Templates.h +++ b/OSX/libsecurity_asn1/lib/asn1Templates.h @@ -26,7 +26,9 @@ #ifndef _ASN1_TEMPLATES_H_ #define _ASN1_TEMPLATES_H_ +#ifndef SECURITY_PROJECT_TAPI_HACKS #warning This is for backwards compatibility. Please use instead. +#endif // SECURITY_PROJECT_TAPI_HACKS #include diff --git a/OSX/libsecurity_asn1/lib/csrTemplates.h b/OSX/libsecurity_asn1/lib/csrTemplates.h index bedc7e673..2db4197ae 100644 --- a/OSX/libsecurity_asn1/lib/csrTemplates.h +++ b/OSX/libsecurity_asn1/lib/csrTemplates.h @@ -37,12 +37,12 @@ extern "C" { * ASN class : CertificationRequestInfo * C struct : NSSCertRequestInfo */ -typedef struct { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER { SecAsn1Item version; NSS_Name subject; SecAsn1PubKeyInfo subjectPublicKeyInfo; NSS_Attribute **attributes; -} NSSCertRequestInfo; +} NSSCertRequestInfo DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; extern const SecAsn1Template kSecAsn1CertRequestInfoTemplate[]; @@ -50,11 +50,11 @@ extern const SecAsn1Template kSecAsn1CertRequestInfoTemplate[]; * ASN class : CertificationRequest * C struct : NSSCertRequest */ -typedef struct { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER { NSSCertRequestInfo reqInfo; SecAsn1AlgId signatureAlgorithm; SecAsn1Item signature;// BIT STRING, length in bits -} NSSCertRequest; +} NSSCertRequest DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; extern const SecAsn1Template kSecAsn1CertRequestTemplate[]; @@ -62,11 +62,11 @@ extern const SecAsn1Template kSecAsn1CertRequestTemplate[]; * This is what we use use to avoid unnecessary setup and teardown of * a full NSSCertRequest when signing and verifying. */ -typedef struct { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER { SecAsn1Item certRequestBlob; // encoded, ASN_ANY SecAsn1AlgId signatureAlgorithm; SecAsn1Item signature;// BIT STRING, length in bits -} NSS_SignedCertRequest; +} NSS_SignedCertRequest DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; extern const SecAsn1Template kSecAsn1SignedCertRequestTemplate[]; diff --git a/OSX/libsecurity_asn1/lib/keyTemplates.h b/OSX/libsecurity_asn1/lib/keyTemplates.h index ce726ff3b..1b7c0bbe8 100644 --- a/OSX/libsecurity_asn1/lib/keyTemplates.h +++ b/OSX/libsecurity_asn1/lib/keyTemplates.h @@ -71,12 +71,12 @@ extern const SecAsn1Template kSecAsn1SetOfAttributeTemplate[]; * ASN class : PrivateKeyInfo * C struct : NSS_PrivateKeyInfo */ -typedef struct { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER { SecAsn1Item version; SecAsn1AlgId algorithm; SecAsn1Item privateKey; NSS_Attribute **attributes; -} NSS_PrivateKeyInfo; +} NSS_PrivateKeyInfo DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; extern const SecAsn1Template kSecAsn1PrivateKeyInfoTemplate[]; @@ -88,10 +88,10 @@ extern const SecAsn1Template kSecAsn1PrivateKeyInfoTemplate[]; * The decrypted encryptedData field is a DER-encoded * NSS_PrivateKeyInfo. */ -typedef struct { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER { SecAsn1AlgId algorithm; SecAsn1Item encryptedData; -} NSS_EncryptedPrivateKeyInfo; +} NSS_EncryptedPrivateKeyInfo DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; extern const SecAsn1Template kSecAsn1EncryptedPrivateKeyInfoTemplate[]; @@ -99,10 +99,10 @@ extern const SecAsn1Template kSecAsn1EncryptedPrivateKeyInfoTemplate[]; * ASN class : DigestInfo * C struct : NSS_DigestInfo */ -typedef struct { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER { SecAsn1AlgId digestAlgorithm; SecAsn1Item digest; -} NSS_DigestInfo; +} NSS_DigestInfo DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; extern const SecAsn1Template kSecAsn1DigestInfoTemplate[]; diff --git a/OSX/libsecurity_asn1/lib/ocspTemplates.h b/OSX/libsecurity_asn1/lib/ocspTemplates.h index 2af1efc36..1d338e9ec 100644 --- a/OSX/libsecurity_asn1/lib/ocspTemplates.h +++ b/OSX/libsecurity_asn1/lib/ocspTemplates.h @@ -33,6 +33,9 @@ extern "C" { #endif +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + // MARK: ----- OCSP Request ----- /* @@ -330,6 +333,8 @@ typedef struct { extern const SecAsn1Template kSecAsn1OCSPDReplyTemplate[]; extern const SecAsn1Template kSecAsn1OCSPDRepliesTemplate[]; +#pragma clang diagnostic pop + #ifdef __cplusplus } #endif diff --git a/OSX/libsecurity_asn1/lib/secasn1e.c b/OSX/libsecurity_asn1/lib/secasn1e.c index e695972f3..8a4cbc547 100644 --- a/OSX/libsecurity_asn1/lib/secasn1e.c +++ b/OSX/libsecurity_asn1/lib/secasn1e.c @@ -3,25 +3,25 @@ * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ - * + * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. - * + * * The Original Code is the Netscape security libraries. - * + * * The Initial Developer of the Original Code is Netscape - * Communications Corporation. Portions created by Netscape are + * Communications Corporation. Portions created by Netscape are * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. - * + * * Contributor(s): - * + * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and @@ -60,6 +60,14 @@ typedef enum { needBytes } sec_asn1e_parse_status; +typedef enum { + hdr_normal = 0, /* encode header normally */ + hdr_any = 1, /* header already encoded in content */ + hdr_decoder = 2, /* template only used by decoder. skip it. */ + hdr_optional = 3, /* optional component, to be omitted */ + hdr_placeholder = 4 /* place holder for from_buf content */ +} sec_asn1e_hdr_encoding; + typedef struct sec_asn1e_state_struct { SEC_ASN1EncoderContext *top; const SecAsn1Template *theTemplate; @@ -80,16 +88,16 @@ typedef struct sec_asn1e_state_struct { int depth; PRBool explicit, /* we are handling an explicit header */ - indefinite, /* need end-of-contents */ - is_string, /* encoding a simple string or an ANY */ - may_stream, /* when streaming, do indefinite encoding */ - optional, /* omit field if it has no contents */ - ignore_stream /* ignore streaming value of sub-template */ - #ifdef __APPLE__ - , - signedInt /* signed alternate to SEC_ASN1_INTEGER */ - #endif - ; + indefinite, /* need end-of-contents */ + is_string, /* encoding a simple string or an ANY */ + may_stream, /* when streaming, do indefinite encoding */ + optional, /* omit field if it has no contents */ + ignore_stream /* ignore streaming value of sub-template */ +#ifdef __APPLE__ + , + signedInt /* signed alternate to SEC_ASN1_INTEGER */ +#endif + ; } sec_asn1e_state; /* @@ -117,33 +125,34 @@ struct sec_EncoderContext_struct { static sec_asn1e_state * -sec_asn1e_push_state (SEC_ASN1EncoderContext *cx, - const SecAsn1Template *theTemplate, - const void *src, PRBool new_depth) +sec_asn1e_push_state(SEC_ASN1EncoderContext *cx, + const SecAsn1Template *theTemplate, + const void *src, PRBool new_depth) { sec_asn1e_state *state, *new_state; state = cx->current; - new_state = (sec_asn1e_state*)PORT_ArenaZAlloc (cx->our_pool, - sizeof(*new_state)); + new_state = (sec_asn1e_state*)PORT_ArenaZAlloc(cx->our_pool, sizeof(*new_state)); if (new_state == NULL) { - cx->status = encodeError; - return NULL; + cx->status = encodeError; + return NULL; } new_state->top = cx; new_state->parent = state; new_state->theTemplate = theTemplate; new_state->place = notInUse; - if (src != NULL) - new_state->src = (char *)src + theTemplate->offset; + if (src != NULL) { + new_state->src = (char *)src + theTemplate->offset; + } if (state != NULL) { - new_state->depth = state->depth; - if (new_depth) - new_state->depth++; - state->child = new_state; + new_state->depth = state->depth; + if (new_depth) { + new_state->depth++; + } + state->child = new_state; } cx->current = new_state; @@ -152,7 +161,7 @@ sec_asn1e_push_state (SEC_ASN1EncoderContext *cx, static void -sec_asn1e_scrub_state (sec_asn1e_state *state) +sec_asn1e_scrub_state(sec_asn1e_state *state) { /* * Some default "scrubbing". @@ -164,44 +173,45 @@ sec_asn1e_scrub_state (sec_asn1e_state *state) static void -sec_asn1e_notify_before (SEC_ASN1EncoderContext *cx, void *src, int depth) +sec_asn1e_notify_before(SEC_ASN1EncoderContext *cx, void *src, int depth) { - if (cx->notify_proc == NULL) - return; + if (cx->notify_proc == NULL) { + return; + } cx->during_notify = PR_TRUE; - (* cx->notify_proc) (cx->notify_arg, PR_TRUE, src, depth); + (* cx->notify_proc)(cx->notify_arg, PR_TRUE, src, depth); cx->during_notify = PR_FALSE; } static void -sec_asn1e_notify_after (SEC_ASN1EncoderContext *cx, void *src, int depth) +sec_asn1e_notify_after(SEC_ASN1EncoderContext *cx, void *src, int depth) { - if (cx->notify_proc == NULL) - return; + if (cx->notify_proc == NULL) { + return; + } cx->during_notify = PR_TRUE; - (* cx->notify_proc) (cx->notify_arg, PR_FALSE, src, depth); + (* cx->notify_proc)(cx->notify_arg, PR_FALSE, src, depth); cx->during_notify = PR_FALSE; } static sec_asn1e_state * -sec_asn1e_init_state_based_on_template (sec_asn1e_state *state) +sec_asn1e_init_state_based_on_template(sec_asn1e_state *state) { PRBool explicit, is_string, may_stream, optional, universal, ignore_stream; unsigned char tag_modifiers; unsigned long encode_kind, under_kind; unsigned long tag_number; - #ifdef __APPLE__ - PRBool signedInt, dynamic; - #endif +#ifdef __APPLE__ + PRBool signedInt, dynamic; +#endif encode_kind = state->theTemplate->kind; - universal = ((encode_kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL) - ? PR_TRUE : PR_FALSE; + universal = ((encode_kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL) ? PR_TRUE : PR_FALSE; explicit = (encode_kind & SEC_ASN1_EXPLICIT) ? PR_TRUE : PR_FALSE; encode_kind &= ~SEC_ASN1_EXPLICIT; @@ -209,7 +219,7 @@ sec_asn1e_init_state_based_on_template (sec_asn1e_state *state) optional = (encode_kind & SEC_ASN1_OPTIONAL) ? PR_TRUE : PR_FALSE; encode_kind &= ~SEC_ASN1_OPTIONAL; - PORT_Assert (!(explicit && universal)); /* bad templates */ + PORT_Assert(!(explicit && universal)); /* bad templates */ may_stream = (encode_kind & SEC_ASN1_MAY_STREAM) ? PR_TRUE : PR_FALSE; encode_kind &= ~SEC_ASN1_MAY_STREAM; @@ -217,104 +227,104 @@ sec_asn1e_init_state_based_on_template (sec_asn1e_state *state) ignore_stream = (encode_kind & SEC_ASN1_NO_STREAM) ? PR_TRUE : PR_FALSE; encode_kind &= ~SEC_ASN1_NO_STREAM; - #ifdef __APPLE__ - signedInt = (encode_kind & SEC_ASN1_SIGNED_INT) ? PR_TRUE : PR_FALSE; +#ifdef __APPLE__ + signedInt = (encode_kind & SEC_ASN1_SIGNED_INT) ? PR_TRUE : PR_FALSE; encode_kind &= ~SEC_ASN1_SIGNED_INT; - #endif +#endif - #ifdef __APPLE__ - dynamic = (encode_kind & SEC_ASN1_DYNAMIC) ? PR_TRUE : PR_FALSE; - #endif +#ifdef __APPLE__ + dynamic = (encode_kind & SEC_ASN1_DYNAMIC) ? PR_TRUE : PR_FALSE; +#endif encode_kind &= ~SEC_ASN1_DYNAMIC; if( encode_kind & SEC_ASN1_CHOICE ) { - under_kind = SEC_ASN1_CHOICE; - } else - - if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) || (!universal - && !explicit)) { - const SecAsn1Template *subt; - void *src; - - PORT_Assert ((encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) == 0); - - sec_asn1e_scrub_state (state); - - if (encode_kind & SEC_ASN1_POINTER) { - /* - * XXX This used to PORT_Assert (encode_kind == SEC_ASN1_POINTER); - * but that was too restrictive. This needs to be fixed, - * probably copying what the decoder now checks for, and - * adding a big comment here to explain what the checks mean. - */ - src = *(void **)state->src; - state->place = afterPointer; - if (src == NULL) { - /* - * If this is optional, but NULL, then the field does - * not need to be encoded. In this case we are done; - * we do not want to push a subtemplate. - */ - if (optional) - return state; - - /* - * XXX this is an error; need to figure out - * how to handle this - */ - } - } else { - src = state->src; - if (encode_kind & SEC_ASN1_INLINE) { - /* check that there are no extraneous bits */ - PORT_Assert (encode_kind == SEC_ASN1_INLINE && !optional); - state->place = afterInline; - } else { - /* - * Save the tag modifiers and tag number here before moving - * on to the next state in case this is a member of a - * SEQUENCE OF - */ - state->tag_modifiers = (unsigned char)encode_kind & SEC_ASN1_TAG_MASK - & ~SEC_ASN1_TAGNUM_MASK; - state->tag_number = (unsigned char)encode_kind & SEC_ASN1_TAGNUM_MASK; - - state->place = afterImplicit; - state->optional = optional; - } - } - - subt = SEC_ASN1GetSubtemplate (state->theTemplate, state->src, PR_TRUE, - NULL /* __APPLE__ */, 0 /* __APPLE__ */); - state = sec_asn1e_push_state (state->top, subt, src, PR_FALSE); - if (state == NULL) - return NULL; - - if (universal) { - /* - * This is a POINTER or INLINE; just init based on that - * and we are done. - */ - return sec_asn1e_init_state_based_on_template (state); - } - - /* - * This is an implicit, non-universal (meaning, application-private - * or context-specific) field. This results in a "magic" tag but - * encoding based on the underlying type. We pushed a new state - * that is based on the subtemplate (the underlying type), but - * now we will sort of alias it to give it some of our properties - * (tag, optional status, etc.). - */ - - under_kind = state->theTemplate->kind; - if (under_kind & SEC_ASN1_MAY_STREAM) { - if (!ignore_stream) - may_stream = PR_TRUE; - under_kind &= ~SEC_ASN1_MAY_STREAM; - } + under_kind = SEC_ASN1_CHOICE; + } else if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) || + (!universal && !explicit)) { + const SecAsn1Template *subt; + void *src = NULL; + + PORT_Assert((encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) == 0); + + sec_asn1e_scrub_state(state); + + if (encode_kind & SEC_ASN1_POINTER) { + /* + * XXX This used to PORT_Assert (encode_kind == SEC_ASN1_POINTER); + * but that was too restrictive. This needs to be fixed, + * probably copying what the decoder now checks for, and + * adding a big comment here to explain what the checks mean. + */ + src = *(void **)state->src; + state->place = afterPointer; + if (src == NULL) { + /* + * If this is optional, but NULL, then the field does + * not need to be encoded. In this case we are done; + * we do not want to push a subtemplate. + */ + if (optional) { + return state; + } + + /* + * XXX this is an error; need to figure out + * how to handle this + */ + } + } else { + src = state->src; + if (encode_kind & SEC_ASN1_INLINE) { + /* check that there are no extraneous bits */ + PORT_Assert(encode_kind == SEC_ASN1_INLINE && !optional); + state->place = afterInline; + } else { + /* + * Save the tag modifiers and tag number here before moving + * on to the next state in case this is a member of a + * SEQUENCE OF + */ + state->tag_modifiers = (unsigned char)encode_kind & SEC_ASN1_TAG_MASK & ~SEC_ASN1_TAGNUM_MASK; + state->tag_number = (unsigned char)encode_kind & SEC_ASN1_TAGNUM_MASK; + + state->place = afterImplicit; + state->optional = optional; + } + } + + subt = SEC_ASN1GetSubtemplate(state->theTemplate, state->src, PR_TRUE, + NULL /* __APPLE__ */, 0 /* __APPLE__ */); + state = sec_asn1e_push_state(state->top, subt, src, PR_FALSE); + if (state == NULL) { + return NULL; + } + + if (universal) { + /* + * This is a POINTER or INLINE; just init based on that + * and we are done. + */ + return sec_asn1e_init_state_based_on_template(state); + } + + /* + * This is an implicit, non-universal (meaning, application-private + * or context-specific) field. This results in a "magic" tag but + * encoding based on the underlying type. We pushed a new state + * that is based on the subtemplate (the underlying type), but + * now we will sort of alias it to give it some of our properties + * (tag, optional status, etc.). + */ + + under_kind = state->theTemplate->kind; + if (under_kind & SEC_ASN1_MAY_STREAM) { + if (!ignore_stream) { + may_stream = PR_TRUE; + } + under_kind &= ~SEC_ASN1_MAY_STREAM; + } } else { - under_kind = encode_kind; + under_kind = encode_kind; } /* @@ -324,70 +334,69 @@ sec_asn1e_init_state_based_on_template (sec_asn1e_state *state) * XXX is this the right set of bits to test here? (i.e. need to add * or remove any?) */ - PORT_Assert ((under_kind & (/*SEC_ASN1_EXPLICIT | */SEC_ASN1_OPTIONAL - | SEC_ASN1_SKIP | SEC_ASN1_INNER - | SEC_ASN1_DYNAMIC | SEC_ASN1_MAY_STREAM - | SEC_ASN1_INLINE | SEC_ASN1_POINTER)) == 0); + PORT_Assert((under_kind & (/*SEC_ASN1_EXPLICIT | */SEC_ASN1_OPTIONAL + | SEC_ASN1_SKIP | SEC_ASN1_INNER + | SEC_ASN1_DYNAMIC | SEC_ASN1_MAY_STREAM + | SEC_ASN1_INLINE | SEC_ASN1_POINTER)) == 0); if (encode_kind & SEC_ASN1_ANY) { - PORT_Assert (encode_kind == under_kind); - tag_modifiers = 0; - tag_number = 0; - is_string = PR_TRUE; + PORT_Assert(encode_kind == under_kind); + tag_modifiers = 0; + tag_number = 0; + is_string = PR_TRUE; } else { - tag_modifiers = (unsigned char)encode_kind & SEC_ASN1_TAG_MASK & - ~SEC_ASN1_TAGNUM_MASK; - /* - * XXX This assumes only single-octet identifiers. To handle - * the HIGH TAG form we would need to do some more work, especially - * in how to specify them in the template, because right now we - * do not provide a way to specify more *tag* bits in encode_kind. - */ - - #ifdef __APPLE__ - /* - * Apple change: if this is a DYNAMIC template, use the tag number - * from the subtemplate's kind - */ - if(dynamic) { - tag_number = state->theTemplate->kind & SEC_ASN1_TAGNUM_MASK; - explicit = (state->theTemplate->kind & SEC_ASN1_EXPLICIT) ? PR_TRUE : PR_FALSE; - tag_modifiers |= (state->theTemplate->kind & SEC_ASN1_CONSTRUCTED); - } - else - #endif /* __APPLE__ */ - tag_number = encode_kind & SEC_ASN1_TAGNUM_MASK; - - is_string = PR_FALSE; - switch (under_kind & SEC_ASN1_TAGNUM_MASK) { - case SEC_ASN1_SET: - /* - * XXX A plain old SET (as opposed to a SET OF) is not implemented. - * If it ever is, remove this assert... - */ - PORT_Assert ((under_kind & SEC_ASN1_GROUP) != 0); - /* fallthru */ - case SEC_ASN1_SEQUENCE: - tag_modifiers |= SEC_ASN1_CONSTRUCTED; - break; - case SEC_ASN1_BIT_STRING: - case SEC_ASN1_BMP_STRING: - case SEC_ASN1_GENERALIZED_TIME: - case SEC_ASN1_IA5_STRING: - case SEC_ASN1_OCTET_STRING: - case SEC_ASN1_PRINTABLE_STRING: - case SEC_ASN1_T61_STRING: - case SEC_ASN1_UNIVERSAL_STRING: - case SEC_ASN1_UTC_TIME: - case SEC_ASN1_UTF8_STRING: - case SEC_ASN1_VISIBLE_STRING: - /* - * We do not yet know if we will be constructing the string, - * so we have to wait to do this final tag modification. - */ - is_string = PR_TRUE; - break; - } + tag_modifiers = (unsigned char)encode_kind & SEC_ASN1_TAG_MASK & ~SEC_ASN1_TAGNUM_MASK; + /* + * XXX This assumes only single-octet identifiers. To handle + * the HIGH TAG form we would need to do some more work, especially + * in how to specify them in the template, because right now we + * do not provide a way to specify more *tag* bits in encode_kind. + */ + +#ifdef __APPLE__ + /* + * Apple change: if this is a DYNAMIC template, use the tag number + * from the subtemplate's kind + */ + if (dynamic) { + tag_number = state->theTemplate->kind & SEC_ASN1_TAGNUM_MASK; + explicit = (state->theTemplate->kind & SEC_ASN1_EXPLICIT) ? PR_TRUE : PR_FALSE; + tag_modifiers |= (state->theTemplate->kind & SEC_ASN1_CONSTRUCTED); + } + else +#endif /* __APPLE__ */ + tag_number = encode_kind & SEC_ASN1_TAGNUM_MASK; + + is_string = PR_FALSE; + switch (under_kind & SEC_ASN1_TAGNUM_MASK) { + case SEC_ASN1_SET: + /* + * XXX A plain old SET (as opposed to a SET OF) is not implemented. + * If it ever is, remove this assert... + */ + PORT_Assert((under_kind & SEC_ASN1_GROUP) != 0); + /* fallthru */ + case SEC_ASN1_SEQUENCE: + tag_modifiers |= SEC_ASN1_CONSTRUCTED; + break; + case SEC_ASN1_BIT_STRING: + case SEC_ASN1_BMP_STRING: + case SEC_ASN1_GENERALIZED_TIME: + case SEC_ASN1_IA5_STRING: + case SEC_ASN1_OCTET_STRING: + case SEC_ASN1_PRINTABLE_STRING: + case SEC_ASN1_T61_STRING: + case SEC_ASN1_UNIVERSAL_STRING: + case SEC_ASN1_UTC_TIME: + case SEC_ASN1_UTF8_STRING: + case SEC_ASN1_VISIBLE_STRING: + /* + * We do not yet know if we will be constructing the string, + * so we have to wait to do this final tag modification. + */ + is_string = PR_TRUE; + break; + } } state->tag_modifiers = tag_modifiers; @@ -398,25 +407,25 @@ sec_asn1e_init_state_based_on_template (sec_asn1e_state *state) state->is_string = is_string; state->optional = optional; state->ignore_stream = ignore_stream; - #ifdef __APPLE__ - state->signedInt = signedInt; - #endif +#ifdef __APPLE__ + state->signedInt = signedInt; +#endif - sec_asn1e_scrub_state (state); + sec_asn1e_scrub_state(state); return state; } static void -sec_asn1e_write_part (sec_asn1e_state *state, - const char *buf, size_t len, - SEC_ASN1EncodingPart part) +sec_asn1e_write_part(sec_asn1e_state *state, + const char *buf, size_t len, + SEC_ASN1EncodingPart part) { SEC_ASN1EncoderContext *cx; cx = state->top; - (* cx->output_proc) (cx->output_arg, buf, len, state->depth, part); + (* cx->output_proc)(cx->output_arg, buf, len, state->depth, part); } @@ -426,110 +435,107 @@ sec_asn1e_write_part (sec_asn1e_state *state, * teach it to properly encode the special form. */ static void -sec_asn1e_write_identifier_bytes (sec_asn1e_state *state, unsigned char value) +sec_asn1e_write_identifier_bytes(sec_asn1e_state *state, unsigned char value) { char byte; byte = (char) value; - sec_asn1e_write_part (state, &byte, 1, SEC_ASN1_Identifier); + sec_asn1e_write_part(state, &byte, 1, SEC_ASN1_Identifier); } int SEC_ASN1EncodeLength(unsigned char *buf,unsigned long value) { int lenlen; - lenlen = SEC_ASN1LengthLength (value); + lenlen = SEC_ASN1LengthLength(value); if (lenlen == 1) { - buf[0] = value; + buf[0] = value; } else { - int i; - - i = lenlen - 1; - buf[0] = 0x80 | i; - while (i) { - buf[i--] = value; - value >>= 8; - } - PORT_Assert (value == 0); + int i; + + i = lenlen - 1; + buf[0] = 0x80 | i; + while (i) { + buf[i--] = value; + value >>= 8; + } + PORT_Assert(value == 0); } return lenlen; } static void -sec_asn1e_write_length_bytes (sec_asn1e_state *state, unsigned long value, - PRBool indefinite) +sec_asn1e_write_length_bytes(sec_asn1e_state *state, unsigned long value, + PRBool indefinite) { int lenlen; unsigned char buf[sizeof(unsigned long) + 1]; if (indefinite) { - PORT_Assert (value == 0); - buf[0] = 0x80; - lenlen = 1; + PORT_Assert(value == 0); + buf[0] = 0x80; + lenlen = 1; } else { - lenlen = SEC_ASN1EncodeLength(buf,value); + lenlen = SEC_ASN1EncodeLength(buf,value); } - sec_asn1e_write_part (state, (char *) buf, lenlen, SEC_ASN1_Length); + sec_asn1e_write_part(state, (char *) buf, lenlen, SEC_ASN1_Length); } static void -sec_asn1e_write_contents_bytes (sec_asn1e_state *state, - const char *buf, unsigned long len) +sec_asn1e_write_contents_bytes(sec_asn1e_state *state, + const char *buf, unsigned long len) { - sec_asn1e_write_part (state, buf, len, SEC_ASN1_Contents); + sec_asn1e_write_part(state, buf, len, SEC_ASN1_Contents); } static void -sec_asn1e_write_end_of_contents_bytes (sec_asn1e_state *state) +sec_asn1e_write_end_of_contents_bytes(sec_asn1e_state *state) { const char eoc[2] = {0, 0}; - sec_asn1e_write_part (state, eoc, 2, SEC_ASN1_EndOfContents); + sec_asn1e_write_part(state, eoc, 2, SEC_ASN1_EndOfContents); } static int -sec_asn1e_which_choice -( - void *src, - const SecAsn1Template *theTemplate -) +sec_asn1e_which_choice(void *src, const SecAsn1Template *theTemplate) { - int rv; - unsigned int which = *(unsigned int *)src; + int rv; + unsigned int which = *(unsigned int *)src; - for( rv = 1, theTemplate++; theTemplate->kind != 0; rv++, theTemplate++ ) { - if( which == theTemplate->size ) { - return rv; + for( rv = 1, theTemplate++; theTemplate->kind != 0; rv++, theTemplate++ ) { + if( which == theTemplate->size ) { + return rv; + } } - } - return 0; + return 0; } static unsigned long -sec_asn1e_contents_length (const SecAsn1Template *theTemplate, void *src, - PRBool ignoresubstream, PRBool *noheaderp) +sec_asn1e_contents_length(const SecAsn1Template *theTemplate, void *src, + PRBool ignoresubstream, PRBool insideIndefinite, + sec_asn1e_hdr_encoding *pHdrException) { unsigned long encode_kind, underlying_kind; PRBool explicit, optional, universal, may_stream; unsigned long len; - #ifdef __APPLE__ - PRBool signedInt; - #endif - +#ifdef __APPLE__ + PRBool signedInt; +#endif + /* * This function currently calculates the length in all cases - * except the following: when writing out the contents of a + * except the following: when writing out the contents of a * template that belongs to a state where it was a sub-template * with the SEC_ASN1_MAY_STREAM bit set and it's parent had the * optional bit set. The information that the parent is optional - * and that we should return the length of 0 when that length is + * and that we should return the length of 0 when that length is * present since that means the optional field is no longer present. * So we add the ignoresubstream flag which is passed in when - * writing the contents, but for all recursive calls to + * writing the contents, but for all recursive calls to * sec_asn1e_contents_length, we pass PR_FALSE, because this * function correctly calculates the length for children templates * from that point on. Confused yet? At least you didn't have @@ -537,8 +543,7 @@ sec_asn1e_contents_length (const SecAsn1Template *theTemplate, void *src, */ encode_kind = theTemplate->kind; - universal = ((encode_kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL) - ? PR_TRUE : PR_FALSE; + universal = ((encode_kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL) ? PR_TRUE : PR_FALSE; explicit = (encode_kind & SEC_ASN1_EXPLICIT) ? PR_TRUE : PR_FALSE; encode_kind &= ~SEC_ASN1_EXPLICIT; @@ -546,242 +551,253 @@ sec_asn1e_contents_length (const SecAsn1Template *theTemplate, void *src, optional = (encode_kind & SEC_ASN1_OPTIONAL) ? PR_TRUE : PR_FALSE; encode_kind &= ~SEC_ASN1_OPTIONAL; - PORT_Assert (!(explicit && universal)); /* bad templates */ + PORT_Assert(!(explicit && universal)); /* bad templates */ may_stream = (encode_kind & SEC_ASN1_MAY_STREAM) ? PR_TRUE : PR_FALSE; encode_kind &= ~SEC_ASN1_MAY_STREAM; /* Just clear this to get it out of the way; we do not need it here */ encode_kind &= ~SEC_ASN1_DYNAMIC; + + if (encode_kind & SEC_ASN1_NO_STREAM) { + ignoresubstream = PR_TRUE; + } encode_kind &= ~SEC_ASN1_NO_STREAM; - if( encode_kind & SEC_ASN1_CHOICE ) { - void *src2; - int indx = sec_asn1e_which_choice(src, theTemplate); - if( 0 == indx ) { - /* XXX set an error? "choice not found" */ - /* state->top->status = encodeError; */ - return 0; - } + if (encode_kind & SEC_ASN1_CHOICE) { + void *src2; + int indx = sec_asn1e_which_choice(src, theTemplate); + if( 0 == indx ) { + /* XXX set an error? "choice not found" */ + /* state->top->status = encodeError; */ + return 0; + } - src2 = (void *)((char *)src - theTemplate->offset + theTemplate[indx].offset); + src2 = (void *)((char *)src - theTemplate->offset + theTemplate[indx].offset); - return sec_asn1e_contents_length(&theTemplate[indx], src2, - PR_FALSE, noheaderp); + return sec_asn1e_contents_length(&theTemplate[indx], src2, + ignoresubstream, insideIndefinite, + pHdrException); } if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) || !universal) { - /* XXX any bits we want to disallow (PORT_Assert against) here? */ - - theTemplate = SEC_ASN1GetSubtemplate (theTemplate, src, PR_TRUE, - NULL /* __APPLE__ */, 0 /* __APPLE__ */); - - if (encode_kind & SEC_ASN1_POINTER) { - /* - * XXX This used to PORT_Assert (encode_kind == SEC_ASN1_POINTER); - * but that was too restrictive. This needs to be fixed, - * probably copying what the decoder now checks for, and - * adding a big comment here to explain what the checks mean. - * Alternatively, the check here could be omitted altogether - * just letting sec_asn1e_init_state_based_on_template - * do it, since that routine can do better error handling, too. - */ - src = *(void **)src; - if (src == NULL) { - if (optional) - *noheaderp = PR_TRUE; - else - *noheaderp = PR_FALSE; - return 0; - } - } else if (encode_kind & SEC_ASN1_INLINE) { - /* check that there are no extraneous bits */ - PORT_Assert (encode_kind == SEC_ASN1_INLINE && !optional); - } - - src = (char *)src + theTemplate->offset; - - if (explicit) { - len = sec_asn1e_contents_length (theTemplate, src, PR_FALSE, - noheaderp); - if (len == 0 && optional) { - *noheaderp = PR_TRUE; - } else if (*noheaderp) { - /* Okay, *we* do not want to add in a header, but our caller still does. */ - *noheaderp = PR_FALSE; - } else { - /* if the inner content exists, our length is - * len(identifier) + len(length) + len(innercontent) - * XXX we currently assume len(identifier) == 1; - * to support a high-tag-number this would need to be smarter. - */ - len += 1 + SEC_ASN1LengthLength (len); - } - return len; - } - - underlying_kind = theTemplate->kind; - underlying_kind &= ~SEC_ASN1_MAY_STREAM; - /* XXX Should we recurse here? */ - } else { - underlying_kind = encode_kind; + /* XXX any bits we want to disallow (PORT_Assert against) here? */ + + theTemplate = SEC_ASN1GetSubtemplate(theTemplate, src, PR_TRUE, + NULL /* __APPLE__ */, 0 /* __APPLE__ */); + + if (encode_kind & SEC_ASN1_POINTER) { + /* + * XXX This used to PORT_Assert (encode_kind == SEC_ASN1_POINTER); + * but that was too restrictive. This needs to be fixed, + * probably copying what the decoder now checks for, and + * adding a big comment here to explain what the checks mean. + * Alternatively, the check here could be omitted altogether + * just letting sec_asn1e_init_state_based_on_template + * do it, since that routine can do better error handling, too. + */ + src = *(void **)src; + if (src == NULL) { + *pHdrException = optional ? hdr_optional : hdr_normal; + return 0; + } + } else if (encode_kind & SEC_ASN1_INLINE) { + /* check that there are no extraneous bits */ + PORT_Assert (encode_kind == SEC_ASN1_INLINE && !optional); + } + + src = (char *)src + theTemplate->offset; + + len = sec_asn1e_contents_length(theTemplate, src, + ignoresubstream, insideIndefinite, + pHdrException); + if (len == 0 && optional) { + *pHdrException = hdr_optional; + } else if (explicit) { + if (*pHdrException == hdr_any) { + /* *we* do not want to add in a header, + ** but our caller still does. + */ + *pHdrException = hdr_normal; + } else if (*pHdrException == hdr_normal) { + /* if the inner content exists, our length is + * len(identifier) + len(length) + len(innercontent) + * XXX we currently assume len(identifier) == 1; + * to support a high-tag-number this would need to be smarter. + */ + len += 1 + SEC_ASN1LengthLength(len); + } + } + return len; } - #ifdef __APPLE__ - signedInt = (underlying_kind & SEC_ASN1_SIGNED_INT) ? - PR_TRUE : PR_FALSE; - #endif - + underlying_kind = encode_kind; + +#ifdef __APPLE__ + signedInt = (underlying_kind & SEC_ASN1_SIGNED_INT) ? + PR_TRUE : PR_FALSE; +#endif + /* This is only used in decoding; it plays no part in encoding. */ if (underlying_kind & SEC_ASN1_SAVE) { - /* check that there are no extraneous bits */ - PORT_Assert (underlying_kind == SEC_ASN1_SAVE); - *noheaderp = PR_TRUE; - return 0; + /* check that there are no extraneous bits */ + PORT_Assert (underlying_kind == SEC_ASN1_SAVE); + *pHdrException = hdr_decoder; + return 0; } /* Having any of these bits is not expected here... */ PORT_Assert ((underlying_kind & (SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL - | SEC_ASN1_INLINE | SEC_ASN1_POINTER - | SEC_ASN1_DYNAMIC | SEC_ASN1_MAY_STREAM - | SEC_ASN1_SAVE | SEC_ASN1_SKIP)) == 0); - - if( underlying_kind & SEC_ASN1_CHOICE ) { - void *src2; - int indx = sec_asn1e_which_choice(src, theTemplate); - if( 0 == indx ) { - /* XXX set an error? "choice not found" */ - /* state->top->status = encodeError; */ - return 0; - } - - src2 = (void *)((char *)src - theTemplate->offset + theTemplate[indx].offset); - len = sec_asn1e_contents_length(&theTemplate[indx], src2, PR_FALSE, - noheaderp); - } else - - switch (underlying_kind) { - case SEC_ASN1_SEQUENCE_OF: - case SEC_ASN1_SET_OF: - { - const SecAsn1Template *tmpt; - void *sub_src; - unsigned long sub_len; - void **group; - - len = 0; - - group = *(void ***)src; - if (group == NULL) - break; - - tmpt = SEC_ASN1GetSubtemplate (theTemplate, src, PR_TRUE, - NULL /* __APPLE__ */, 0 /* __APPLE__ */); - - for (; *group != NULL; group++) { - sub_src = (char *)(*group) + tmpt->offset; - sub_len = sec_asn1e_contents_length (tmpt, sub_src, PR_FALSE, - noheaderp); - len += sub_len; - /* - * XXX The 1 below is the presumed length of the identifier; - * to support a high-tag-number this would need to be smarter. - */ - if (!*noheaderp) - len += 1 + SEC_ASN1LengthLength (sub_len); - } - } - break; - - case SEC_ASN1_SEQUENCE: - case SEC_ASN1_SET: - { - const SecAsn1Template *tmpt; - void *sub_src; - unsigned long sub_len; - - len = 0; - for (tmpt = theTemplate + 1; tmpt->kind; tmpt++) { - sub_src = (char *)src + tmpt->offset; - sub_len = sec_asn1e_contents_length (tmpt, sub_src, PR_FALSE, - noheaderp); - len += sub_len; - /* - * XXX The 1 below is the presumed length of the identifier; - * to support a high-tag-number this would need to be smarter. - */ - if (!*noheaderp) - len += 1 + SEC_ASN1LengthLength (sub_len); - } - } - break; - - case SEC_ASN1_BIT_STRING: - /* convert bit length to byte */ - len = (((SecAsn1Item *)src)->Length + 7) >> 3; - /* bit string contents involve an extra octet */ - if (len) - len++; - break; - - case SEC_ASN1_INTEGER: - /* ASN.1 INTEGERs are signed. - * If the source is an unsigned integer, the encoder will need - * to handle the conversion here. - */ - { - unsigned char *buf = ((SecAsn1Item *)src)->Data; - #ifndef __APPLE__ - SecAsn1ItemType integerType = ((SecAsn1Item *)src)->type; - #endif - len = ((SecAsn1Item *)src)->Length; - while (len > 0) { - if (*buf != 0) { - #ifdef __APPLE__ - if (*buf & 0x80 && !signedInt) { - #else - if (*buf & 0x80 && integerType == siUnsignedInteger) { - #endif // __APPLE__ - len++; /* leading zero needed to make number signed */ - } - break; /* reached beginning of number */ - } - if (len == 1) { - break; /* the number 0 */ - } - if (buf[1] & 0x80) { - break; /* leading zero already present */ - } - /* extraneous leading zero, keep going */ - buf++; - len--; - } - } - break; - - default: - len = ((SecAsn1Item *)src)->Length; - if (may_stream && len == 0 && !ignoresubstream) - len = 1; /* if we're streaming, we may have a secitem w/len 0 as placeholder */ - break; - } - - if ((len == 0 && optional) || underlying_kind == SEC_ASN1_ANY) - *noheaderp = PR_TRUE; - else - *noheaderp = PR_FALSE; + | SEC_ASN1_INLINE | SEC_ASN1_POINTER + | SEC_ASN1_DYNAMIC | SEC_ASN1_MAY_STREAM + | SEC_ASN1_SAVE | SEC_ASN1_SKIP)) == 0); + + if (underlying_kind & SEC_ASN1_CHOICE) { + void *src2; + int indx = sec_asn1e_which_choice(src, theTemplate); + if( 0 == indx ) { + /* XXX set an error? "choice not found" */ + /* state->top->status = encodeError; */ + return 0; + } + + src2 = (void *)((char *)src - theTemplate->offset + theTemplate[indx].offset); + len = sec_asn1e_contents_length(&theTemplate[indx], src2, ignoresubstream, + insideIndefinite, pHdrException); + } else { + switch (underlying_kind) { + case SEC_ASN1_SEQUENCE_OF: + case SEC_ASN1_SET_OF: { + const SecAsn1Template *tmpt; + void *sub_src; + unsigned long sub_len; + void **group; + + len = 0; + + group = *(void ***)src; + if (group == NULL) { + break; + } + + tmpt = SEC_ASN1GetSubtemplate(theTemplate, src, PR_TRUE, + NULL /* __APPLE__ */, 0 /* __APPLE__ */); + + for (; *group != NULL; group++) { + sub_src = (char *)(*group) + tmpt->offset; + sub_len = sec_asn1e_contents_length(tmpt, sub_src, ignoresubstream, + insideIndefinite, pHdrException); + len += sub_len; + /* + * XXX The 1 below is the presumed length of the identifier; + * to support a high-tag-number this would need to be smarter. + */ + if (*pHdrException == hdr_normal) { + len += 1 + SEC_ASN1LengthLength(sub_len); + } + } + } + break; + + case SEC_ASN1_SEQUENCE: + case SEC_ASN1_SET: { + const SecAsn1Template *tmpt; + void *sub_src; + unsigned long sub_len; + + len = 0; + for (tmpt = theTemplate + 1; tmpt->kind; tmpt++) { + sub_src = (char *)src + tmpt->offset; + sub_len = sec_asn1e_contents_length(tmpt, sub_src, ignoresubstream, + insideIndefinite, pHdrException); + len += sub_len; + /* + * XXX The 1 below is the presumed length of the identifier; + * to support a high-tag-number this would need to be smarter. + */ + if (*pHdrException == hdr_normal) { + len += 1 + SEC_ASN1LengthLength (sub_len); + } + } + } + break; + + case SEC_ASN1_BIT_STRING: + /* convert bit length to byte */ + len = (((SecAsn1Item *)src)->Length + 7) >> 3; + /* bit string contents involve an extra octet */ + if (len) { + len++; + } + break; + + case SEC_ASN1_INTEGER: { + /* ASN.1 INTEGERs are signed. + * If the source is an unsigned integer, the encoder will need + * to handle the conversion here. + */ + unsigned char *buf = ((SecAsn1Item *)src)->Data; +#ifndef __APPLE__ + SecAsn1ItemType integerType = ((SecAsn1Item *)src)->type; +#endif + len = ((SecAsn1Item *)src)->Length; + while (len > 0) { + if (*buf != 0) { +#ifdef __APPLE__ + if (*buf & 0x80 && !signedInt) +#else + if (*buf & 0x80 && integerType == siUnsignedInteger) +#endif // __APPLE__ + { + len++; /* leading zero needed to make number signed */ + } + break; /* reached beginning of number */ + } + if (len == 1) { + break; /* the number 0 */ + } + if (buf[1] & 0x80) { + break; /* leading zero already present */ + } + /* extraneous leading zero, keep going */ + buf++; + len--; + } + } + break; + + default: + len = ((SecAsn1Item *)src)->Length; + break; + } /* end switch */ + +#ifndef WHAT_PROBLEM_DOES_THIS_SOLVE + /* if we're streaming, we may have a secitem w/len 0 as placeholder */ + if (!len && insideIndefinite && may_stream && !ignoresubstream) { + len = 1; + } +#endif + } /* end else */ + + if (len == 0 && optional) + *pHdrException = hdr_optional; + else if (underlying_kind == SEC_ASN1_ANY) + *pHdrException = hdr_any; + else + *pHdrException = hdr_normal; return len; } static void -sec_asn1e_write_header (sec_asn1e_state *state) +sec_asn1e_write_header(sec_asn1e_state *state) { unsigned long contents_length; unsigned char tag_number, tag_modifiers; - PRBool noheader; + sec_asn1e_hdr_encoding hdrException = hdr_normal; + PRBool indefinite = PR_FALSE; PORT_Assert (state->place == beforeHeader); @@ -789,89 +805,101 @@ sec_asn1e_write_header (sec_asn1e_state *state) tag_modifiers = state->tag_modifiers; if (state->underlying_kind == SEC_ASN1_ANY) { - state->place = duringContents; - return; + state->place = duringContents; + return; } - if( state->underlying_kind & SEC_ASN1_CHOICE ) { - int indx = sec_asn1e_which_choice(state->src, state->theTemplate); - if( 0 == indx ) { - /* XXX set an error? "choice not found" */ - state->top->status = encodeError; + if (state->underlying_kind & SEC_ASN1_CHOICE) { + int indx = sec_asn1e_which_choice(state->src, state->theTemplate); + if( 0 == indx ) { + /* XXX set an error? "choice not found" */ + state->top->status = encodeError; + return; + } + + state->place = afterChoice; + state = sec_asn1e_push_state(state->top, &state->theTemplate[indx], + (char *)state->src - state->theTemplate->offset, + PR_TRUE); + + if (state) { + /* + * Do the "before" field notification. + */ + sec_asn1e_notify_before (state->top, state->src, state->depth); + (void)sec_asn1e_init_state_based_on_template (state); + } return; - } - - state->place = afterChoice; - state = sec_asn1e_push_state(state->top, &state->theTemplate[indx], - (char *)state->src - state->theTemplate->offset, - PR_TRUE); - - if( (sec_asn1e_state *)NULL != state ) { - /* - * Do the "before" field notification. - */ - sec_asn1e_notify_before (state->top, state->src, state->depth); - state = sec_asn1e_init_state_based_on_template (state); - } - - (void) state; - - return; } + /* The !isString test below is apparently intended to ensure that all + ** constructed types receive indefinite length encoding. + */ + indefinite = (PRBool)(state->top->streaming && state->may_stream && + (state->top->from_buf || !state->is_string)); + /* - * We are doing a definite-length encoding. First we have to + * If we are doing a definite-length encoding, first we have to * walk the data structure to calculate the entire contents length. + * If we are doing an indefinite-length encoding, we still need to + * know if the contents is: + * optional and to be omitted, or + * an ANY (header is pre-encoded), or + * a SAVE or some other kind of template used only by the decoder. + * So, we call this function either way. */ - contents_length = sec_asn1e_contents_length (state->theTemplate, - state->src, - state->ignore_stream, - &noheader); + contents_length = sec_asn1e_contents_length(state->theTemplate, + state->src, + state->ignore_stream, + indefinite, + &hdrException); /* * We might be told explicitly not to put out a header. * But it can also be the case, via a pushed subtemplate, that * sec_asn1e_contents_length could not know that this field is * really optional. So check for that explicitly, too. */ - if (noheader || (contents_length == 0 && state->optional)) { - state->place = afterContents; - if (state->top->streaming && state->may_stream && state->top->from_buf) - /* we did not find an optional indefinite string, so we don't encode it. - * However, if TakeFromBuf is on, we stop here anyway to give our caller - * a chance to intercept at the same point where we would stop if the - * field were present. */ - state->top->status = needBytes; - return; + if (hdrException != hdr_normal || + (contents_length == 0 && state->optional)) { + state->place = afterContents; + if (state->top->streaming && + state->may_stream && + state->top->from_buf) { + /* we did not find an optional indefinite string, so we + * don't encode it. However, if TakeFromBuf is on, we stop + * here anyway to give our caller a chance to intercept at the + * same point where we would stop if the field were present. + */ + state->top->status = needBytes; + } + return; } - if (state->top->streaming && state->may_stream - && (state->top->from_buf || !state->is_string)) { - /* - * We need to put out an indefinite-length encoding. - */ - state->indefinite = PR_TRUE; - /* - * The only universal types that can be constructed are SETs, - * SEQUENCEs, and strings; so check that it is one of those, - * or that it is not universal (e.g. context-specific). - */ - PORT_Assert ((tag_number == SEC_ASN1_SET) - || (tag_number == SEC_ASN1_SEQUENCE) - || ((tag_modifiers & SEC_ASN1_CLASS_MASK) != 0) - || state->is_string); - tag_modifiers |= SEC_ASN1_CONSTRUCTED; - contents_length = 0; + if (indefinite) { + /* + * We need to put out an indefinite-length encoding. + * The only universal types that can be constructed are SETs, + * SEQUENCEs, and strings; so check that it is one of those, + * or that it is not universal (e.g. context-specific). + */ + state->indefinite = PR_TRUE; + PORT_Assert ((tag_number == SEC_ASN1_SET) + || (tag_number == SEC_ASN1_SEQUENCE) + || ((tag_modifiers & SEC_ASN1_CLASS_MASK) != 0) + || state->is_string); + tag_modifiers |= SEC_ASN1_CONSTRUCTED; + contents_length = 0; } - sec_asn1e_write_identifier_bytes (state, (unsigned char)(tag_number | tag_modifiers)); - sec_asn1e_write_length_bytes (state, contents_length, state->indefinite); + sec_asn1e_write_identifier_bytes(state, (unsigned char)(tag_number | tag_modifiers)); + sec_asn1e_write_length_bytes(state, contents_length, state->indefinite); if (contents_length == 0 && !state->indefinite) { - /* - * If no real contents to encode, then we are done with this field. - */ - state->place = afterContents; - return; + /* + * If no real contents to encode, then we are done with this field. + */ + state->place = afterContents; + return; } /* @@ -879,256 +907,251 @@ sec_asn1e_write_header (sec_asn1e_state *state) * written. Now we need to do the inner header and contents. */ if (state->explicit) { - state->place = afterContents; - state = sec_asn1e_push_state (state->top, - SEC_ASN1GetSubtemplate(state->theTemplate, - state->src, - PR_TRUE, - NULL /* __APPLE__ */, 0 /* __APPLE__ */), - state->src, PR_TRUE); - if (state != NULL) - state = sec_asn1e_init_state_based_on_template (state); - - (void) state; - - return; + state->place = afterContents; + const SecAsn1Template *subt = SEC_ASN1GetSubtemplate(state->theTemplate, state->src, PR_TRUE, + NULL /* __APPLE__ */, 0 /* __APPLE__ */); + state = sec_asn1e_push_state(state->top, subt, state->src, PR_TRUE); + if (state != NULL) { + (void)sec_asn1e_init_state_based_on_template(state); + } + return; } switch (state->underlying_kind) { - case SEC_ASN1_SET_OF: - case SEC_ASN1_SEQUENCE_OF: - /* - * We need to push a child to handle each member. - */ - { - void **group; - const SecAsn1Template *subt; - - group = *(void ***)state->src; - if (group == NULL || *group == NULL) { - /* - * Group is empty; we are done. - */ - state->place = afterContents; - return; - } - state->place = duringGroup; - subt = SEC_ASN1GetSubtemplate (state->theTemplate, state->src, - PR_TRUE, NULL /* __APPLE__ */, 0 /* __APPLE__ */); - state = sec_asn1e_push_state (state->top, subt, *group, PR_TRUE); - if (state != NULL) - state = sec_asn1e_init_state_based_on_template (state); - } - break; - - case SEC_ASN1_SEQUENCE: - case SEC_ASN1_SET: - /* - * We need to push a child to handle the individual fields. - */ - state->place = duringSequence; - state = sec_asn1e_push_state (state->top, state->theTemplate + 1, - state->src, PR_TRUE); - if (state != NULL) { - /* - * Do the "before" field notification. - */ - sec_asn1e_notify_before (state->top, state->src, state->depth); - state = sec_asn1e_init_state_based_on_template (state); - } - break; - - default: - /* - * I think we do not need to do anything else. - * XXX Correct? - */ - state->place = duringContents; - break; + case SEC_ASN1_SET_OF: + case SEC_ASN1_SEQUENCE_OF: { + /* + * We need to push a child to handle each member. + */ + void **group; + const SecAsn1Template *subt; + + group = *(void ***)state->src; + if (group == NULL || *group == NULL) { + /* + * Group is empty; we are done. + */ + state->place = afterContents; + return; + } + state->place = duringGroup; + subt = SEC_ASN1GetSubtemplate(state->theTemplate, state->src, + PR_TRUE, NULL /* __APPLE__ */, 0 /* __APPLE__ */); + state = sec_asn1e_push_state(state->top, subt, *group, PR_TRUE); + if (state != NULL) { + (void)sec_asn1e_init_state_based_on_template(state); + } + } + break; + + case SEC_ASN1_SEQUENCE: + case SEC_ASN1_SET: + /* + * We need to push a child to handle the individual fields. + */ + state->place = duringSequence; + state = sec_asn1e_push_state(state->top, state->theTemplate + 1, + state->src, PR_TRUE); + if (state != NULL) { + /* + * Do the "before" field notification. + */ + sec_asn1e_notify_before(state->top, state->src, state->depth); + (void)sec_asn1e_init_state_based_on_template(state); + } + break; + + default: + /* + * I think we do not need to do anything else. + * XXX Correct? + */ + state->place = duringContents; + break; } - - (void) state; } static void -sec_asn1e_write_contents (sec_asn1e_state *state, - const char *buf, unsigned long len) +sec_asn1e_write_contents_from_buf(sec_asn1e_state *state, + const char *buf, unsigned long len) { - PORT_Assert (state->place == duringContents); - - if (state->top->from_buf) { - /* - * Probably they just turned on "take from buf", but have not - * yet given us any bytes. If there is nothing in the buffer - * then we have nothing to do but return and wait. - */ - if (buf == NULL || len == 0) { - state->top->status = needBytes; - return; - } - /* - * We are streaming, reading from a passed-in buffer. - * This means we are encoding a simple string or an ANY. - * For the former, we need to put out a substring, with its - * own identifier and length. For an ANY, we just write it - * out as is (our caller is required to ensure that it - * is a properly encoded entity). - */ - PORT_Assert (state->is_string); /* includes ANY */ - if (state->underlying_kind != SEC_ASN1_ANY) { - unsigned char identifier; - - /* - * Create the identifier based on underlying_kind. We cannot - * use tag_number and tag_modifiers because this can be an - * implicitly encoded field. In that case, the underlying - * substrings *are* encoded with their real tag. - */ - identifier = (unsigned char)state->underlying_kind & SEC_ASN1_TAG_MASK; - /* - * The underlying kind should just be a simple string; there - * should be no bits like CONTEXT_SPECIFIC or CONSTRUCTED set. - */ - PORT_Assert ((identifier & SEC_ASN1_TAGNUM_MASK) == identifier); - /* - * Write out the tag and length for the substring. - */ - sec_asn1e_write_identifier_bytes (state, identifier); - if (state->underlying_kind == SEC_ASN1_BIT_STRING) { - char byte; - /* - * Assume we have a length in bytes but we need to output - * a proper bit string. This interface only works for bit - * strings that are full multiples of 8. If support for - * real, variable length bit strings is needed then the - * caller will have to know to pass in a bit length instead - * of a byte length and then this code will have to - * perform the encoding necessary (length written is length - * in bytes plus 1, and the first octet of string is the - * number of bits remaining between the end of the bit - * string and the next byte boundary). - */ - sec_asn1e_write_length_bytes (state, len + 1, PR_FALSE); - byte = 0; - sec_asn1e_write_contents_bytes (state, &byte, 1); - } else { - sec_asn1e_write_length_bytes (state, len, PR_FALSE); - } - } - sec_asn1e_write_contents_bytes (state, buf, len); - state->top->status = needBytes; - } else { - switch (state->underlying_kind) { - case SEC_ASN1_SET: - case SEC_ASN1_SEQUENCE: - PORT_Assert (0); - break; - - case SEC_ASN1_BIT_STRING: - { - SecAsn1Item *item; - char rem; - - item = (SecAsn1Item *)state->src; - len = (item->Length + 7) >> 3; - rem = (unsigned char)((len << 3) - item->Length); /* remaining bits */ - sec_asn1e_write_contents_bytes (state, &rem, 1); - sec_asn1e_write_contents_bytes (state, (char *) item->Data, - len); - } - break; - - case SEC_ASN1_BMP_STRING: - /* The number of bytes must be divisable by 2 */ - if ((((SecAsn1Item *)state->src)->Length) % 2) { - SEC_ASN1EncoderContext *cx; - - cx = state->top; - cx->status = encodeError; - break; - } - /* otherwise, fall through to write the content */ - goto process_string; - - case SEC_ASN1_UNIVERSAL_STRING: - /* The number of bytes must be divisable by 4 */ - if ((((SecAsn1Item *)state->src)->Length) % 4) { - SEC_ASN1EncoderContext *cx; - - cx = state->top; - cx->status = encodeError; - break; - } - /* otherwise, fall through to write the content */ - goto process_string; - - case SEC_ASN1_INTEGER: - /* ASN.1 INTEGERs are signed. If the source is an unsigned - * integer, the encoder will need to handle the conversion here. - */ - { - size_t blen; - unsigned char *intbuf; - #ifdef __APPLE__ - PRBool signedInt = state->signedInt; - #else - SECItemType integerType = ((SecAsn1Item *)state->src)->type; - #endif - blen = ((SecAsn1Item *)state->src)->Length; - intbuf = ((SecAsn1Item *)state->src)->Data; - while (blen > 0) { - #ifdef __APPLE__ - if (*intbuf & 0x80 && !signedInt) { - #else - if (*intbuf & 0x80 && integerType == siUnsignedInteger) { - #endif - char zero = 0; /* write a leading 0 */ - sec_asn1e_write_contents_bytes(state, &zero, 1); - /* and then the remaining buffer */ - sec_asn1e_write_contents_bytes(state, - (char *)intbuf, blen); - break; - } - /* Check three possibilities: - * 1. No leading zeros, msb of MSB is not 1; - * 2. The number is zero itself; - * 3. Encoding a signed integer with a leading zero, - * keep the zero so that the number is positive. - */ - if (*intbuf != 0 || - blen == 1 || - #ifdef __APPLE__ - (intbuf[1] & 0x80 && signedInt) ) - #else - (intbuf[1] & 0x80 && integerType != siUnsignedInteger) ) - #endif - { - sec_asn1e_write_contents_bytes(state, - (char *)intbuf, blen); - break; - } - /* byte is 0, continue */ - intbuf++; - blen--; - } - } - /* done with this content */ - break; - -process_string: - default: - { - SecAsn1Item *item; - - item = (SecAsn1Item *)state->src; - sec_asn1e_write_contents_bytes (state, (char *) item->Data, - item->Length); - } - break; - } - state->place = afterContents; + PORT_Assert(state->place == duringContents); + PORT_Assert(state->top->from_buf); + PORT_Assert(state->may_stream && !state->ignore_stream); + + /* + * Probably they just turned on "take from buf", but have not + * yet given us any bytes. If there is nothing in the buffer + * then we have nothing to do but return and wait. + */ + if (buf == NULL || len == 0) { + state->top->status = needBytes; + return; + } + /* + * We are streaming, reading from a passed-in buffer. + * This means we are encoding a simple string or an ANY. + * For the former, we need to put out a substring, with its + * own identifier and length. For an ANY, we just write it + * out as is (our caller is required to ensure that it + * is a properly encoded entity). + */ + PORT_Assert(state->is_string); /* includes ANY */ + if (state->underlying_kind != SEC_ASN1_ANY) { + unsigned char identifier; + + /* + * Create the identifier based on underlying_kind. We cannot + * use tag_number and tag_modifiers because this can be an + * implicitly encoded field. In that case, the underlying + * substrings *are* encoded with their real tag. + */ + identifier = (unsigned char)(state->underlying_kind & SEC_ASN1_TAG_MASK); + /* + * The underlying kind should just be a simple string; there + * should be no bits like CONTEXT_SPECIFIC or CONSTRUCTED set. + */ + PORT_Assert((identifier & SEC_ASN1_TAGNUM_MASK) == identifier); + /* + * Write out the tag and length for the substring. + */ + sec_asn1e_write_identifier_bytes(state, identifier); + if (state->underlying_kind == SEC_ASN1_BIT_STRING) { + char byte; + /* + * Assume we have a length in bytes but we need to output + * a proper bit string. This interface only works for bit + * strings that are full multiples of 8. If support for + * real, variable length bit strings is needed then the + * caller will have to know to pass in a bit length instead + * of a byte length and then this code will have to + * perform the encoding necessary (length written is length + * in bytes plus 1, and the first octet of string is the + * number of bits remaining between the end of the bit + * string and the next byte boundary). + */ + sec_asn1e_write_length_bytes(state, len + 1, PR_FALSE); + byte = 0; + sec_asn1e_write_contents_bytes(state, &byte, 1); + } else { + sec_asn1e_write_length_bytes(state, len, PR_FALSE); + } + } + sec_asn1e_write_contents_bytes(state, buf, len); + state->top->status = needBytes; +} + +static void +sec_asn1e_write_contents(sec_asn1e_state *state) +{ + unsigned long len = 0; + + PORT_Assert(state->place == duringContents); + switch (state->underlying_kind) { + case SEC_ASN1_SET: + case SEC_ASN1_SEQUENCE: + PORT_Assert (0); + break; + + case SEC_ASN1_BIT_STRING: { + SecAsn1Item *item; + char rem; + + item = (SecAsn1Item *)state->src; + len = (item->Length + 7) >> 3; + rem = (unsigned char)((len << 3) - item->Length); /* remaining bits */ + sec_asn1e_write_contents_bytes(state, &rem, 1); + sec_asn1e_write_contents_bytes(state, (char *) item->Data, len); + } + break; + + case SEC_ASN1_BMP_STRING: + /* The number of bytes must be divisable by 2 */ + if ((((SecAsn1Item *)state->src)->Length) % 2) { + SEC_ASN1EncoderContext *cx; + + cx = state->top; + cx->status = encodeError; + break; + } + /* otherwise, fall through to write the content */ + goto process_string; + + case SEC_ASN1_UNIVERSAL_STRING: + /* The number of bytes must be divisable by 4 */ + if ((((SecAsn1Item *)state->src)->Length) % 4) { + SEC_ASN1EncoderContext *cx; + + cx = state->top; + cx->status = encodeError; + break; + } + /* otherwise, fall through to write the content */ + goto process_string; + + case SEC_ASN1_INTEGER: { + /* ASN.1 INTEGERs are signed. If the source is an unsigned + * integer, the encoder will need to handle the conversion here. + */ + size_t blen; + unsigned char *intbuf; +#ifdef __APPLE__ + PRBool signedInt = state->signedInt; +#else + SECItemType integerType = ((SecAsn1Item *)state->src)->type; +#endif + blen = ((SecAsn1Item *)state->src)->Length; + intbuf = ((SecAsn1Item *)state->src)->Data; + while (blen > 0) { +#ifdef __APPLE__ + if (*intbuf & 0x80 && !signedInt) +#else + if (*intbuf & 0x80 && integerType == siUnsignedInteger) +#endif + { + char zero = 0; /* write a leading 0 */ + sec_asn1e_write_contents_bytes(state, &zero, 1); + /* and then the remaining buffer */ + sec_asn1e_write_contents_bytes(state, (char *)intbuf, blen); + break; + } + /* Check three possibilities: + * 1. No leading zeros, msb of MSB is not 1; + * 2. The number is zero itself; + * 3. Encoding a signed integer with a leading zero, + * keep the zero so that the number is positive. + */ + if (*intbuf != 0 || + blen == 1 || +#ifdef __APPLE__ + (intbuf[1] & 0x80 && signedInt) ) +#else + (intbuf[1] & 0x80 && integerType != siUnsignedInteger) ) +#endif + { + sec_asn1e_write_contents_bytes(state, (char *)intbuf, blen); + break; + } + /* byte is 0, continue */ + intbuf++; + blen--; + } + } + /* done with this content */ + break; + + process_string: + default: + { + SecAsn1Item *item; + + item = (SecAsn1Item *)state->src; + sec_asn1e_write_contents_bytes(state, (char *) item->Data, item->Length); + } + break; } + state->place = afterContents; } @@ -1136,14 +1159,14 @@ sec_asn1e_write_contents (sec_asn1e_state *state, * We are doing a SET OF or SEQUENCE OF, and have just finished an item. */ static void -sec_asn1e_next_in_group (sec_asn1e_state *state) +sec_asn1e_next_in_group(sec_asn1e_state *state) { sec_asn1e_state *child; void **group; void *member; - PORT_Assert (state->place == duringGroup); - PORT_Assert (state->child != NULL); + PORT_Assert(state->place == duringGroup); + PORT_Assert(state->child != NULL); child = state->child; @@ -1153,27 +1176,28 @@ sec_asn1e_next_in_group (sec_asn1e_state *state) * Find placement of current item. */ member = (char *)(state->child->src) - child->theTemplate->offset; - while (*group != member) - group++; + while (*group != member) { + group++; + } /* * Move forward to next item. */ group++; if (*group == NULL) { - /* - * That was our last one; we are done now. - */ - child->place = notInUse; - state->place = afterContents; - return; + /* + * That was our last one; we are done now. + */ + child->place = notInUse; + state->place = afterContents; + return; } child->src = (char *)(*group) + child->theTemplate->offset; /* * Re-"push" child. */ - sec_asn1e_scrub_state (child); + sec_asn1e_scrub_state(child); state->top->current = child; } @@ -1183,31 +1207,31 @@ sec_asn1e_next_in_group (sec_asn1e_state *state) * (detecting end-of-sequence when it happens). */ static void -sec_asn1e_next_in_sequence (sec_asn1e_state *state) +sec_asn1e_next_in_sequence(sec_asn1e_state *state) { sec_asn1e_state *child; - PORT_Assert (state->place == duringSequence); - PORT_Assert (state->child != NULL); + PORT_Assert(state->place == duringSequence); + PORT_Assert(state->child != NULL); child = state->child; /* * Do the "after" field notification. */ - sec_asn1e_notify_after (state->top, child->src, child->depth); + sec_asn1e_notify_after(state->top, child->src, child->depth); /* * Move forward. */ child->theTemplate++; if (child->theTemplate->kind == 0) { - /* - * We are done with this sequence. - */ - child->place = notInUse; - state->place = afterContents; - return; + /* + * We are done with this sequence. + */ + child->place = notInUse; + state->place = afterContents; + return; } /* @@ -1219,20 +1243,21 @@ sec_asn1e_next_in_sequence (sec_asn1e_state *state) /* * Do the "before" field notification. */ - sec_asn1e_notify_before (state->top, child->src, child->depth); + sec_asn1e_notify_before(state->top, child->src, child->depth); state->top->current = child; - (void) sec_asn1e_init_state_based_on_template (child); + (void)sec_asn1e_init_state_based_on_template(child); } static void sec_asn1e_after_contents (sec_asn1e_state *state) { - PORT_Assert (state->place == afterContents); + PORT_Assert(state->place == afterContents); - if (state->indefinite) - sec_asn1e_write_end_of_contents_bytes (state); + if (state->indefinite) { + sec_asn1e_write_end_of_contents_bytes(state); + } /* * Just make my parent be the current state. It will then clean @@ -1254,68 +1279,72 @@ sec_asn1e_after_contents (sec_asn1e_state *state) * (for now) with the buffer. */ SECStatus -SEC_ASN1EncoderUpdate (SEC_ASN1EncoderContext *cx, - const char *buf, unsigned long len) +SEC_ASN1EncoderUpdate(SEC_ASN1EncoderContext *cx, + const char *buf, unsigned long len) { sec_asn1e_state *state; if (cx->status == needBytes) { - PORT_Assert (buf != NULL && len != 0); - cx->status = keepGoing; + PORT_Assert(buf != NULL && len != 0); + cx->status = keepGoing; } while (cx->status == keepGoing) { - state = cx->current; - switch (state->place) { - case beforeHeader: - sec_asn1e_write_header (state); - break; - case duringContents: - sec_asn1e_write_contents (state, buf, len); - break; - case duringGroup: - sec_asn1e_next_in_group (state); - break; - case duringSequence: - sec_asn1e_next_in_sequence (state); - break; - case afterContents: - sec_asn1e_after_contents (state); - break; - case afterImplicit: - case afterInline: - case afterPointer: - case afterChoice: - /* - * These states are more documentation than anything. - * They just need to force a pop. - */ - PORT_Assert (!state->indefinite); - state->place = afterContents; - break; - case notInUse: - default: - /* This is not an error, but rather a plain old BUG! */ - PORT_Assert (0); - cx->status = encodeError; - break; - } - - if (cx->status == encodeError) - break; - - /* It might have changed, so we have to update our local copy. */ - state = cx->current; - - /* If it is NULL, we have popped all the way to the top. */ - if (state == NULL) { - cx->status = allDone; - break; - } + state = cx->current; + switch (state->place) { + case beforeHeader: + sec_asn1e_write_header(state); + break; + case duringContents: + if (cx->from_buf) + sec_asn1e_write_contents_from_buf(state, buf, len); + else + sec_asn1e_write_contents(state); + break; + case duringGroup: + sec_asn1e_next_in_group(state); + break; + case duringSequence: + sec_asn1e_next_in_sequence(state); + break; + case afterContents: + sec_asn1e_after_contents(state); + break; + case afterImplicit: + case afterInline: + case afterPointer: + case afterChoice: + /* + * These states are more documentation than anything. + * They just need to force a pop. + */ + PORT_Assert(!state->indefinite); + state->place = afterContents; + break; + case notInUse: + default: + /* This is not an error, but rather a plain old BUG! */ + PORT_Assert(0); + cx->status = encodeError; + break; + } + + if (cx->status == encodeError) { + break; + } + + /* It might have changed, so we have to update our local copy. */ + state = cx->current; + + /* If it is NULL, we have popped all the way to the top. */ + if (state == NULL) { + cx->status = allDone; + break; + } } if (cx->status == encodeError) { - return SECFailure; + return SECFailure; } return SECSuccess; @@ -1323,31 +1352,32 @@ SEC_ASN1EncoderUpdate (SEC_ASN1EncoderContext *cx, void -SEC_ASN1EncoderFinish (SEC_ASN1EncoderContext *cx) +SEC_ASN1EncoderFinish(SEC_ASN1EncoderContext *cx) { /* * XXX anything else that needs to be finished? */ - PORT_FreeArena (cx->our_pool, PR_FALSE); + PORT_FreeArena(cx->our_pool, PR_FALSE); } SEC_ASN1EncoderContext * -SEC_ASN1EncoderStart (const void *src, const SecAsn1Template *theTemplate, - SEC_ASN1WriteProc output_proc, void *output_arg) +SEC_ASN1EncoderStart(const void *src, const SecAsn1Template *theTemplate, + SEC_ASN1WriteProc output_proc, void *output_arg) { PRArenaPool *our_pool; SEC_ASN1EncoderContext *cx; - our_pool = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE); - if (our_pool == NULL) - return NULL; + our_pool = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); + if (our_pool == NULL) { + return NULL; + } - cx = (SEC_ASN1EncoderContext*)PORT_ArenaZAlloc (our_pool, sizeof(*cx)); + cx = (SEC_ASN1EncoderContext*)PORT_ArenaZAlloc(our_pool, sizeof(*cx)); if (cx == NULL) { - PORT_FreeArena (our_pool, PR_FALSE); - return NULL; + PORT_FreeArena(our_pool, PR_FALSE); + return NULL; } cx->our_pool = our_pool; @@ -1357,13 +1387,13 @@ SEC_ASN1EncoderStart (const void *src, const SecAsn1Template *theTemplate, cx->status = keepGoing; if (sec_asn1e_push_state(cx, theTemplate, src, PR_FALSE) == NULL - || sec_asn1e_init_state_based_on_template (cx->current) == NULL) { - /* - * Trouble initializing (probably due to failed allocations) - * requires that we just give up. - */ - PORT_FreeArena (our_pool, PR_FALSE); - return NULL; + || sec_asn1e_init_state_based_on_template(cx->current) == NULL) { + /* + * Trouble initializing (probably due to failed allocations) + * requires that we just give up. + */ + PORT_FreeArena (our_pool,PR_FALSE); + return NULL; } return cx; @@ -1376,8 +1406,8 @@ SEC_ASN1EncoderStart (const void *src, const SecAsn1Template *theTemplate, void -SEC_ASN1EncoderSetNotifyProc (SEC_ASN1EncoderContext *cx, - SEC_ASN1NotifyProc fn, void *arg) +SEC_ASN1EncoderSetNotifyProc(SEC_ASN1EncoderContext *cx, + SEC_ASN1NotifyProc fn, void *arg) { cx->notify_proc = fn; cx->notify_arg = arg; @@ -1385,7 +1415,7 @@ SEC_ASN1EncoderSetNotifyProc (SEC_ASN1EncoderContext *cx, void -SEC_ASN1EncoderClearNotifyProc (SEC_ASN1EncoderContext *cx) +SEC_ASN1EncoderClearNotifyProc(SEC_ASN1EncoderContext *cx) { cx->notify_proc = NULL; cx->notify_arg = NULL; /* not necessary; just being clean */ @@ -1402,7 +1432,7 @@ SEC_ASN1EncoderAbort(SEC_ASN1EncoderContext *cx, int error) void -SEC_ASN1EncoderSetStreaming (SEC_ASN1EncoderContext *cx) +SEC_ASN1EncoderSetStreaming(SEC_ASN1EncoderContext *cx) { /* XXX is there a way to check that we are "between" fields here? */ @@ -1411,7 +1441,7 @@ SEC_ASN1EncoderSetStreaming (SEC_ASN1EncoderContext *cx) void -SEC_ASN1EncoderClearStreaming (SEC_ASN1EncoderContext *cx) +SEC_ASN1EncoderClearStreaming(SEC_ASN1EncoderContext *cx) { /* XXX is there a way to check that we are "between" fields here? */ @@ -1420,66 +1450,67 @@ SEC_ASN1EncoderClearStreaming (SEC_ASN1EncoderContext *cx) void -SEC_ASN1EncoderSetTakeFromBuf (SEC_ASN1EncoderContext *cx) +SEC_ASN1EncoderSetTakeFromBuf(SEC_ASN1EncoderContext *cx) { - /* + /* * XXX is there a way to check that we are "between" fields here? this * needs to include a check for being in between groups of items in * a SET_OF or SEQUENCE_OF. */ - PORT_Assert (cx->streaming); - + PORT_Assert(cx->streaming); cx->from_buf = PR_TRUE; } void -SEC_ASN1EncoderClearTakeFromBuf (SEC_ASN1EncoderContext *cx) +SEC_ASN1EncoderClearTakeFromBuf(SEC_ASN1EncoderContext *cx) { /* we should actually be taking from buf *now* */ PORT_Assert (cx->from_buf); - if (! cx->from_buf) /* if not, just do nothing */ - return; + if (! cx->from_buf) { /* if not, just do nothing */ + return; + } cx->from_buf = PR_FALSE; if (cx->status == needBytes) { - cx->status = keepGoing; - cx->current->place = afterContents; + cx->status = keepGoing; + cx->current->place = afterContents; } } SECStatus -SEC_ASN1Encode (const void *src, const SecAsn1Template *theTemplate, - SEC_ASN1WriteProc output_proc, void *output_arg) +SEC_ASN1Encode(const void *src, const SecAsn1Template *theTemplate, + SEC_ASN1WriteProc output_proc, void *output_arg) { SEC_ASN1EncoderContext *ecx; SECStatus rv; - ecx = SEC_ASN1EncoderStart (src, theTemplate, output_proc, output_arg); - if (ecx == NULL) - return SECFailure; + ecx = SEC_ASN1EncoderStart(src, theTemplate, output_proc, output_arg); + if (ecx == NULL) { + return SECFailure; + } - rv = SEC_ASN1EncoderUpdate (ecx, NULL, 0); + rv = SEC_ASN1EncoderUpdate(ecx, NULL, 0); - SEC_ASN1EncoderFinish (ecx); + SEC_ASN1EncoderFinish(ecx); return rv; } /* * XXX depth and data_kind are unused; is there a PC way to silence warnings? - * (I mean "politically correct", not anything to do with intel/win platform) + * (I mean "politically correct", not anything to do with intel/win platform) */ void -sec_asn1e_encode_item_count (void *arg, const char *buf, size_t len, - int depth, SEC_ASN1EncodingPart data_kind) +sec_asn1e_encode_item_count(void *arg, const char *buf, size_t len, + int depth, SEC_ASN1EncodingPart data_kind) { size_t *count; count = (unsigned long*)arg; - PORT_Assert (count != NULL); + PORT_Assert(count != NULL); *count += len; } @@ -1487,16 +1518,18 @@ sec_asn1e_encode_item_count (void *arg, const char *buf, size_t len, /* XXX depth and data_kind are unused; is there a PC way to silence warnings? */ void -sec_asn1e_encode_item_store (void *arg, const char *buf, size_t len, - int depth, SEC_ASN1EncodingPart data_kind) +sec_asn1e_encode_item_store(void *arg, const char *buf, size_t len, + int depth, SEC_ASN1EncodingPart data_kind) { SecAsn1Item *dest; dest = (SecAsn1Item*)arg; - PORT_Assert (dest != NULL); + PORT_Assert(dest != NULL); - PORT_Memcpy (dest->Data + dest->Length, buf, len); - dest->Length += len; + if (len > 0) { + PORT_Memcpy(dest->Data + dest->Length, buf, len); + dest->Length += len; + } } @@ -1508,44 +1541,47 @@ sec_asn1e_encode_item_store (void *arg, const char *buf, size_t len, * XXX This seems like a reasonable general-purpose function (for SECITEM_)? */ SecAsn1Item * -sec_asn1e_allocate_item (PRArenaPool *poolp, SecAsn1Item *dest, unsigned long len) +sec_asn1e_allocate_item(PRArenaPool *poolp, SecAsn1Item *dest, unsigned long len) { if (poolp != NULL) { - void *release; - - release = PORT_ArenaMark (poolp); - if (dest == NULL) - dest = (SecAsn1Item*)PORT_ArenaAlloc (poolp, sizeof(SecAsn1Item)); - if (dest != NULL) { - dest->Data = (unsigned char*)PORT_ArenaAlloc (poolp, len); - if (dest->Data == NULL) { - dest = NULL; - } - } - if (dest == NULL) { - /* one or both allocations failed; release everything */ - PORT_ArenaRelease (poolp, release); - } else { - /* everything okay; unmark the arena */ - PORT_ArenaUnmark (poolp, release); - } + void *release; + + release = PORT_ArenaMark(poolp); + if (dest == NULL) { + dest = (SecAsn1Item*)PORT_ArenaAlloc(poolp, sizeof(SecAsn1Item)); + } + if (dest != NULL) { + dest->Data = (unsigned char*)PORT_ArenaAlloc(poolp, len); + if (dest->Data == NULL) { + dest = NULL; + } + } + if (dest == NULL) { + /* one or both allocations failed; release everything */ + PORT_ArenaRelease(poolp, release); + } else { + /* everything okay; unmark the arena */ + PORT_ArenaUnmark(poolp, release); + } } else { - SecAsn1Item *indest; - - indest = dest; - if (dest == NULL) - dest = (SecAsn1Item*)PORT_Alloc (sizeof(SecAsn1Item)); - if (dest != NULL) { - #ifndef __APPLE__ - dest->type = siBuffer; - #endif - dest->Data = (unsigned char*)PORT_Alloc (len); - if (dest->Data == NULL) { - if (indest == NULL) - PORT_Free (dest); - dest = NULL; - } - } + SecAsn1Item *indest; + + indest = dest; + if (dest == NULL) { + dest = (SecAsn1Item*)PORT_Alloc(sizeof(SecAsn1Item)); + } + if (dest != NULL) { +#ifndef __APPLE__ + dest->type = siBuffer; +#endif + dest->Data = (unsigned char*)PORT_Alloc(len); + if (dest->Data == NULL) { + if (indest == NULL) { + PORT_Free(dest); + } + dest = NULL; + } + } } return dest; @@ -1553,40 +1589,43 @@ sec_asn1e_allocate_item (PRArenaPool *poolp, SecAsn1Item *dest, unsigned long le SecAsn1Item * -SEC_ASN1EncodeItem (PRArenaPool *poolp, SecAsn1Item *dest, const void *src, - const SecAsn1Template *theTemplate) +SEC_ASN1EncodeItem(PRArenaPool *poolp, SecAsn1Item *dest, const void *src, + const SecAsn1Template *theTemplate) { unsigned long encoding_length; SECStatus rv; - PORT_Assert (dest == NULL || dest->Data == NULL); + PORT_Assert(dest == NULL || dest->Data == NULL); encoding_length = 0; - rv = SEC_ASN1Encode (src, theTemplate, - sec_asn1e_encode_item_count, &encoding_length); - if (rv != SECSuccess) - return NULL; + rv = SEC_ASN1Encode(src, theTemplate, + sec_asn1e_encode_item_count, &encoding_length); + if (rv != SECSuccess) { + return NULL; + } - dest = sec_asn1e_allocate_item (poolp, dest, encoding_length); - if (dest == NULL) - return NULL; + dest = sec_asn1e_allocate_item(poolp, dest, encoding_length); + if (dest == NULL) { + return NULL; + } /* XXX necessary? This really just checks for a bug in the allocate fn */ - PORT_Assert (dest->Data != NULL); - if (dest->Data == NULL) - return NULL; + PORT_Assert(dest->Data != NULL); + if (dest->Data == NULL) { + return NULL; + } dest->Length = 0; - (void) SEC_ASN1Encode (src, theTemplate, sec_asn1e_encode_item_store, dest); + (void)SEC_ASN1Encode(src, theTemplate, sec_asn1e_encode_item_store, dest); - PORT_Assert (encoding_length == dest->Length); + PORT_Assert(encoding_length == dest->Length); return dest; } static SecAsn1Item * sec_asn1e_integer(PRArenaPool *poolp, SecAsn1Item *dest, unsigned long value, - PRBool make_unsigned) + PRBool make_unsigned) { unsigned long copy; unsigned char sign; @@ -1597,9 +1636,9 @@ sec_asn1e_integer(PRArenaPool *poolp, SecAsn1Item *dest, unsigned long value, */ copy = value; do { - len++; - sign = (unsigned char)(copy & 0x80); - copy >>= 8; + len++; + sign = (unsigned char)(copy & 0x80); + copy >>= 8; } while (copy); /* @@ -1607,25 +1646,27 @@ sec_asn1e_integer(PRArenaPool *poolp, SecAsn1Item *dest, unsigned long value, * byte we counted was set, we need to add one to the length so * we put a high-order zero byte in the encoding. */ - if (sign && make_unsigned) - len++; + if (sign && make_unsigned) { + len++; + } /* * Allocate the item (if necessary) and the data pointer within. */ - dest = sec_asn1e_allocate_item (poolp, dest, len); - if (dest == NULL) - return NULL; + dest = sec_asn1e_allocate_item(poolp, dest, len); + if (dest == NULL) { + return NULL; + } /* * Store the value, byte by byte, in the item. */ dest->Length = len; while (len) { - dest->Data[--len] = (unsigned char)value; - value >>= 8; + dest->Data[--len] = (unsigned char)value; + value >>= 8; } - PORT_Assert (value == 0); + PORT_Assert(value == 0); return dest; } @@ -1634,13 +1675,13 @@ sec_asn1e_integer(PRArenaPool *poolp, SecAsn1Item *dest, unsigned long value, SecAsn1Item * SEC_ASN1EncodeInteger(PRArenaPool *poolp, SecAsn1Item *dest, long value) { - return sec_asn1e_integer (poolp, dest, (unsigned long) value, PR_FALSE); + return sec_asn1e_integer(poolp, dest, (unsigned long) value, PR_FALSE); } extern SecAsn1Item * SEC_ASN1EncodeUnsignedInteger(PRArenaPool *poolp, - SecAsn1Item *dest, unsigned long value) + SecAsn1Item *dest, unsigned long value) { - return sec_asn1e_integer (poolp, dest, value, PR_TRUE); + return sec_asn1e_integer(poolp, dest, value, PR_TRUE); } diff --git a/OSX/libsecurity_authorization/lib/AuthSession.h b/OSX/libsecurity_authorization/lib/AuthSession.h index d8542ed80..53ef4855f 100644 --- a/OSX/libsecurity_authorization/lib/AuthSession.h +++ b/OSX/libsecurity_authorization/lib/AuthSession.h @@ -119,8 +119,8 @@ CF_ENUM(OSStatus) { errSessionAuthorizationDenied = -60502, /* you are not allowed to do this */ errSessionValueNotSet = -60503, /* the session attribute you requested has not been set */ - errSessionInternal = errAuthorizationInternal, /* internal error */ - errSessionInvalidFlags = errAuthorizationInvalidFlags /* invalid flags/options */ + errSessionInternal = -60008, /* internal error */ + errSessionInvalidFlags = -60011, /* invalid flags/options */ }; diff --git a/OSX/libsecurity_authorization/lib/Authorization.c b/OSX/libsecurity_authorization/lib/Authorization.c index 7b7095a73..92e1faf0c 100644 --- a/OSX/libsecurity_authorization/lib/Authorization.c +++ b/OSX/libsecurity_authorization/lib/Authorization.c @@ -9,12 +9,26 @@ #include #include #include +#include +#include #include #include #include #include #include #include +#include +#include +#include + +static os_log_t AUTH_LOG_DEFAULT() { + static dispatch_once_t once; + static os_log_t log; + dispatch_once(&once, ^{ log = os_log_create("com.apple.Authorization", "framework"); }); + return log; +}; + +#define AUTH_LOG AUTH_LOG_DEFAULT() static dispatch_queue_t get_authorization_dispatch_queue() @@ -107,7 +121,7 @@ OSStatus AuthorizationCreate(const AuthorizationRights *rights, // Reply reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); require_action_quiet(reply != NULL, done, status = errAuthorizationInternal); - require_action_quiet(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); + require_action_quiet(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal;); // Status status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS); @@ -338,6 +352,48 @@ OSStatus AuthorizationCopyRights(AuthorizationRef authorization, AuthorizationRights **authorizedRights) { OSStatus status = errAuthorizationInternal; + + if ((flags & kAuthorizationFlagSheet) && environment) { + // check if window ID is present in environment + CGWindowID window = 0; + for (UInt32 i = 0; i < environment->count; ++i) { + if (strncmp(environment->items[i].name, kAuthorizationEnvironmentWindowId, strlen(kAuthorizationEnvironmentWindowId)) == 0 + && (environment->items[i].valueLength = sizeof(window)) && environment->items[i].value) { + window = *(CGWindowID *)environment->items[i].value; + break; + } + } + if (window > 0) { + os_log_debug(AUTH_LOG, "Trying to use sheet version"); + static OSStatus (*sheetAuthorizationWorker)(CGWindowID windowID, AuthorizationRef authorization, + const AuthorizationRights *rights, + const AuthorizationEnvironment *environment, + AuthorizationFlags flags, + AuthorizationRights **authorizedRights, + Boolean *authorizationLaunched) = NULL; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + void *handle = dlopen("/System/Library/Frameworks/SecurityInterface.framework/SecurityInterface", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE); + if (handle) { + sheetAuthorizationWorker = dlsym(handle, "sheetAuthorizationWorker"); + } + }); + + if (sheetAuthorizationWorker) { + Boolean authorizationLaunched; + status = sheetAuthorizationWorker(window, authorization, rights, environment, flags, authorizedRights, &authorizationLaunched); + if (authorizationLaunched == true) { + os_log_debug(AUTH_LOG, "Returning sheet result %d", (int)status); + return status; + } + os_log(AUTH_LOG, "Sheet authorization cannot be used this time, falling back to the SecurityAgent UI"); + } else { + os_log_debug(AUTH_LOG, "Failed to find sheet support in SecurityInterface"); + } + // fall back to the standard (windowed) version if sheets are not available + } + } + xpc_object_t message = NULL; require_noerr(status = _AuthorizationCopyRights_prepare_message(authorization, rights, environment, flags, &message), done); diff --git a/OSX/libsecurity_authorization/lib/AuthorizationPlugin.h b/OSX/libsecurity_authorization/lib/AuthorizationPlugin.h index f34c23668..de083b3f0 100644 --- a/OSX/libsecurity_authorization/lib/AuthorizationPlugin.h +++ b/OSX/libsecurity_authorization/lib/AuthorizationPlugin.h @@ -153,7 +153,7 @@ typedef void *AuthorizationSessionId; @constant kAuthorizationResultUndefined the operation failed for some reason and should not be retried for this session. @constant kAuthorizationResultUserCanceled the user has requested that the evaluation be terminated. */ -typedef CF_ENUM(UInt32, AuthorizationResult) { +typedef CF_CLOSED_ENUM(UInt32, AuthorizationResult) { kAuthorizationResultAllow, kAuthorizationResultDeny, kAuthorizationResultUndefined, @@ -176,7 +176,7 @@ enum { interface. */ enum { - kAuthorizationCallbacksVersion = 2 + kAuthorizationCallbacksVersion = 4 }; @@ -194,9 +194,13 @@ enum { @field SetHintValue Write value to hints. AuthorizationValue and data are copied. @field GetArguments Read arguments passed. AuthorizationValueVector does not own data. @field GetSessionId Read SessionId. - @field GetLAContext Returns authenticated LAContext which can be used for operations with Tokens which would normally require PIN. Caller owns returned context and is responsible for release. - @field GetTokenIdentities Returns array of identities. Caller owns returned array and is reponsible for release. -*/ + @field GetLAContext Returns LAContext which will have LACredentialCTKPIN credential set if PIN is available otherwise context without credentials is returned. LAContext can be used for operations with Tokens which would normally require PIN. Caller owns returned context and is responsible for release. + @field GetTokenIdentities Returns array of identities. Caller owns returned array and is reponsible for release. + @field GetTKTokenWatcher Returns TKTokenWatcher object. Caller owns returned context and is responsible for release. + @field RemoveContextValue Removes value from context. + @field RemoveHintValue Removes value from hints. + + */ typedef struct AuthorizationCallbacks { /* Engine callback version. */ @@ -254,18 +258,32 @@ typedef struct AuthorizationCallbacks { userful for kSecUseAuthenticationContext for SecItem calls. Caller is responsible for outValue release */ OSStatus (*GetLAContext)(AuthorizationEngineRef inEngine, - CFTypeRef __nullable * __nullable outValue) __OSX_AVAILABLE_STARTING(__MAC_10_13, __PHONE_NA); + CFTypeRef __nullable * __nullable outValue) __OSX_AVAILABLE_STARTING(__MAC_10_13, __IPHONE_NA); /* Available only on systems with callback version 2 or higher Returns array of available identities available on tokens. Each array item consists of two elements. The first one is SecIdentityRef and the second one is textual description of that identity - context parameter may contain CFTypeRef returned by GetLAContext. Returned identities - will contain PIN in such case so crypto operations won't display PIN prompt. + context parameter may contain CFTypeRef returned by GetLAContext. Caller is responsible for outValue release */ OSStatus (*GetTokenIdentities)(AuthorizationEngineRef inEngine, CFTypeRef context, - CFArrayRef __nullable * __nullable outValue) __OSX_AVAILABLE_STARTING(__MAC_10_13, __PHONE_NA); + CFArrayRef __nullable * __nullable outValue) __OSX_AVAILABLE_STARTING(__MAC_10_13, __IPHONE_NA); + + /* + Available only on systems with callback version 3 or higher + Constructs TKTokenWatcher object. + Caller is responsible for outValue release */ + OSStatus (*GetTKTokenWatcher)(AuthorizationEngineRef inEngine, + CFTypeRef __nullable * __nullable outValue) __OSX_AVAILABLE_STARTING(__MAC_10_13_4, __IPHONE_NA); + + /* Remove value from hints. */ + OSStatus (*RemoveHintValue)(AuthorizationEngineRef inEngine, + AuthorizationString inKey); + + /* Write value to context. */ + OSStatus (*RemoveContextValue)(AuthorizationEngineRef inEngine, + AuthorizationString inKey); } AuthorizationCallbacks; diff --git a/OSX/libsecurity_authorization/lib/AuthorizationPriv.h b/OSX/libsecurity_authorization/lib/AuthorizationPriv.h index 332740ba1..bd9ec9365 100644 --- a/OSX/libsecurity_authorization/lib/AuthorizationPriv.h +++ b/OSX/libsecurity_authorization/lib/AuthorizationPriv.h @@ -53,7 +53,10 @@ extern "C" { @enum Private (for now) AuthorizationFlags */ enum { - kAuthorizationFlagLeastPrivileged = (1 << 5) + kAuthorizationFlagLeastPrivileged = (1 << 5), + kAuthorizationFlagSheet = (1 << 6), + kAuthorizationFlagIgnorePasswordOnly = (1 << 7), + kAuthorizationFlagIgnoreDarkWake = (1 << 8), }; /*! @@ -208,6 +211,63 @@ OSStatus SessionSetUserPreferences(SecuritySessionId session); */ OSStatus AuthorizationEnableSmartCard(AuthorizationRef _Nonnull authRef, Boolean enable); +/*! + @function AuthorizationExecuteWithPrivilegesInternal + Run an executable tool with enhanced privileges after passing + suitable authorization procedures. Allows better control and communication + with privileged tool. + + @param authorization An authorization reference that is used to authorize + access to the enhanced privileges. It is also passed to the tool for + further access control. + @param pathToTool Full pathname to the tool that should be executed + with enhanced privileges. + @param arguments An argv-style vector of strings to be passed to the tool. + @param newProcessPid (output, optional) PID of privileged process is stored here. + @param uid Desired UID under which privileged tool should be running. + @param stdOut File descriptor of the pipe which should be used to receive stdout from the privileged tool, use -1 if not needed. + @param stdErr File descriptor of the pipe which should be used to receive stderr from the privileged tool, use -1 if not needed. + @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, + const char * _Nonnull pathToTool, + const char * _Nonnull const * _Nonnull arguments, + pid_t * _Nullable newProcessPid, + const uid_t uid, + int stdOut, + int stdErr, + int stdIn, + void(^__nullable processFinished)(const int exitStatus)); + +/*! + @function AuthorizationExecuteWithPrivilegesExternalFormInternal + Run an executable tool with enhanced privileges after passing + suitable authorization procedures. Allows better control and communication + with privileged tool. + + @param extAuthorization authorization in external form that is used to authorize + access to the enhanced privileges. It is also passed to the tool for + further access control. + @param pathToTool Full pathname to the tool that should be executed + with enhanced privileges. + @param arguments An argv-style vector of strings to be passed to the tool. + @param newProcessPid (output, optional) PID of privileged process is stored here. + @param uid Desired UID under which privileged tool should be running. + @param stdOut File descriptor of the pipe which should be used to receive stdout from the privileged tool, use -1 if not needed. + @param stdErr File descriptor of the pipe which should be used to receive stderr from the privileged tool, use -1 if not needed. + @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, + const char * _Nonnull pathToTool, + const char * _Nullable const * _Nullable arguments, + pid_t * _Nullable newProcessPid, + const uid_t uid, + int stdOut, + int stdErr, + int stdIn, + void(^__nullable processFinished)(const int exitStatus)); #if defined(__cplusplus) } #endif diff --git a/OSX/libsecurity_authorization/lib/AuthorizationTags.h b/OSX/libsecurity_authorization/lib/AuthorizationTags.h index cfba3efa0..8f59881c5 100644 --- a/OSX/libsecurity_authorization/lib/AuthorizationTags.h +++ b/OSX/libsecurity_authorization/lib/AuthorizationTags.h @@ -76,5 +76,12 @@ */ #define kAuthorizationEnvironmentIcon "icon" +/*! + @define kAuthorizationPamResult + Return code provided by PAM module + */ +#define kAuthorizationPamResult "pam_result" + + #endif /* !_SECURITY_AUTHORIZATIONTAGS_H_ */ diff --git a/OSX/libsecurity_authorization/lib/AuthorizationTagsPriv.h b/OSX/libsecurity_authorization/lib/AuthorizationTagsPriv.h index f062a3210..8800d326f 100644 --- a/OSX/libsecurity_authorization/lib/AuthorizationTagsPriv.h +++ b/OSX/libsecurity_authorization/lib/AuthorizationTagsPriv.h @@ -356,4 +356,7 @@ /* LocalAuthentication specific */ #define AGENT_CONTEXT_LACONTEXT "la-context" +/* Sheet window ID */ +#define kAuthorizationEnvironmentWindowId "cgwindowid" + #endif /* !_SECURITY_AUTHORIZATIONTAGSPRIV_H_ */ diff --git a/OSX/libsecurity_authorization/lib/AuthorizationTrampolinePriv.h b/OSX/libsecurity_authorization/lib/AuthorizationTrampolinePriv.h new file mode 100644 index 000000000..cec647b3a --- /dev/null +++ b/OSX/libsecurity_authorization/lib/AuthorizationTrampolinePriv.h @@ -0,0 +1,59 @@ +/* + * 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@ + */ + + +/* + * AuthorizationTrampolinePriv.h -- Authorization defines for communication with + * authtrampoline. + * + */ + +#ifndef _SECURITY_AUTHORIZATIONTRAMPOLINEPRIV_H_ +#define _SECURITY_AUTHORIZATIONTRAMPOLINEPRIV_H_ + +#define XPC_REQUEST_CREATE_PROCESS "createp" +#define XPC_REPLY_MSG "rpl" +#define XPC_EVENT_MSG "evt" +#define XPC_REQUEST_ID "req" + +#define XPC_EVENT_TYPE "evtt" +#define XPC_EVENT_TYPE_CHILDEND "ce" + +#define PARAM_TOOL_PATH "tool" // path to the executable +#define PARAM_TOOL_PARAMS "params" // parameters passed to the executable +#define PARAM_ENV "env" // environment +#define PARAM_CWD "cwd" // current working directory +#define PARAM_EUID "requid" // uid under which executable should be running +#define PARAM_AUTHREF "auth" // authorization +#define PARAM_EXITCODE "ec" // exit code of that tool +#define PARAM_STDIN "in" // stdin FD +#define PARAM_STDOUT "out" // stdout FD +#define PARAM_STDERR "err" // stderr FD +#define PARAM_DATA "data" // data to be written to the executable's stdin +#define PARAM_CHILDEND_NEEDED "cen" // indicates client needs to be notified when executable finishes + +#define RETVAL_STATUS "status" +#define RETVAL_CHILD_PID "cpid" + + +#endif /* !_SECURITY_AUTHORIZATIONTRAMPOLINEPRIV_H_ */ diff --git a/OSX/libsecurity_authorization/lib/trampolineClient.cpp b/OSX/libsecurity_authorization/lib/trampolineClient.cpp index f544bb8c7..b7c5ee855 100644 --- a/OSX/libsecurity_authorization/lib/trampolineClient.cpp +++ b/OSX/libsecurity_authorization/lib/trampolineClient.cpp @@ -32,35 +32,51 @@ #include #include #include -#include -#include #include #include #include -// -// Where is the trampoline itself? -// -#if !defined(TRAMPOLINE) -# define TRAMPOLINE "/usr/libexec/security_authtrampoline" /* fallback */ -#endif - +#include "Security/Authorization.h" +#include "AuthorizationPriv.h" +#include "AuthorizationTrampolinePriv.h" +#include +#include +#include +#include +#include +#include // // A few names for clarity's sake // enum { - READ = 0, // read end of standard UNIX pipe - WRITE = 1 // write end of standard UNIX pipe + READ = 0, // read end of standard UNIX pipe + WRITE = 1 // write end of standard UNIX pipe +}; + +static os_log_t AUTH_LOG_DEFAULT() { + static dispatch_once_t once; + static os_log_t log; + dispatch_once(&once, ^{ log = os_log_create("com.apple.Authorization", "Trampoline"); }); + return log; }; +#define AUTH_LOG AUTH_LOG_DEFAULT() + +// +// Where is the trampoline itself? +// +#if !defined(TRAMPOLINE) +# define TRAMPOLINE "/usr/libexec/security_authtrampoline" /* fallback */ +#endif + // // Local (static) functions // static const char **argVector(const char *trampoline, - const char *tool, const char *commFd, - char *const *arguments); +const char *tool, const char *commFd, +char *const *arguments); OSStatus AuthorizationExecuteWithPrivileges(AuthorizationRef authorization, @@ -81,158 +97,180 @@ OSStatus AuthorizationExecuteWithPrivileges(AuthorizationRef authorization, // The public client API function. // OSStatus AuthorizationExecuteWithPrivilegesExternalForm(const AuthorizationExternalForm * extForm, - const char *pathToTool, - AuthorizationFlags flags, - char *const *arguments, - FILE **communicationsPipe) +const char *pathToTool, +AuthorizationFlags flags, +char *const *arguments, +FILE **communicationsPipe) { - if (extForm == NULL) + os_log(AUTH_LOG, "AuthorizationExecuteWithPrivileges and AuthorizationExecuteWithPrivilegesExternalForm are deprecated and functionality will be removed soon - please update your application"); + 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; - - // create the mailbox file - FILE *mbox = tmpfile(); - if (!mbox) - return errAuthorizationInternal; - if (fwrite(extForm, sizeof(*extForm), 1, mbox) != 1) { - fclose(mbox); - return errAuthorizationInternal; - } - fflush(mbox); + // 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); - // compute the argument vector here because we can't allocate memory once we fork. - - // make text representation of the temp-file descriptor - char mboxFdText[20]; - snprintf(mboxFdText, sizeof(mboxFdText), "auth %d", fileno(mbox)); - - // where is the trampoline? + // flags are currently reserved + if (flags != 0) + return errAuthorizationInvalidFlags; + + // compute the argument vector here because we can't allocate memory once we fork. + + // where is the trampoline? #if defined(NDEBUG) - const char *trampoline = TRAMPOLINE; + const char *trampoline = TRAMPOLINE; #else //!NDEBUG - const char *trampoline = getenv("AUTHORIZATIONTRAMPOLINE"); - if (!trampoline) - trampoline = TRAMPOLINE; + const char *trampoline = getenv("AUTHORIZATIONTRAMPOLINE"); + if (!trampoline) + trampoline = TRAMPOLINE; #endif //NDEBUG - - const char **argv = argVector(trampoline, pathToTool, mboxFdText, arguments); - - // make a notifier pipe - int notify[2]; - if (pipe(notify)) { - fclose(mbox); - if(argv) { free(argv); } - return errAuthorizationToolExecuteFailure; + + // make a data exchange pipe + int dataPipe[2]; + if (pipe(dataPipe)) { + os_log_error(AUTH_LOG, "data pipe failure"); + return errAuthorizationToolExecuteFailure; } - - // make the communications pipe if requested - int comm[2]; - if (communicationsPipe && socketpair(AF_UNIX, SOCK_STREAM, 0, comm)) { - close(notify[READ]); close(notify[WRITE]); - fclose(mbox); - if(argv) { free(argv); } - return errAuthorizationToolExecuteFailure; - } - - OSStatus status = errSecSuccess; - - // do the standard forking tango... - int delay = 1; - for (int n = 5;; n--, delay *= 2) { - switch (fork()) { - case -1: // error - if (errno == EAGAIN) { - // potentially recoverable resource shortage - if (n > 0) { - secinfo("authexec", "resource shortage (EAGAIN), delaying %d seconds", delay); - sleep(delay); - continue; - } - } - secinfo("authexec", "fork failed (errno=%d)", errno); - close(notify[READ]); close(notify[WRITE]); - status = errAuthorizationToolExecuteFailure; - goto exit_point; - - default: { // parent - // close foreign side of pipes - close(notify[WRITE]); - if (communicationsPipe) - close(comm[WRITE]); + + // make text representation of the pipe handle + char pipeFdText[20]; + snprintf(pipeFdText, sizeof(pipeFdText), "auth %d", dataPipe[READ]); + const char **argv = argVector(trampoline, pathToTool, pipeFdText, arguments); + + // make a notifier pipe + int notify[2]; + if (pipe(notify)) { + close(dataPipe[READ]); close(dataPipe[WRITE]); + if(argv) { + free(argv); + } + os_log_error(AUTH_LOG, "notify pipe failure"); + return errAuthorizationToolExecuteFailure; + } + + // make the communications pipe if requested + int comm[2]; + if (communicationsPipe && socketpair(AF_UNIX, SOCK_STREAM, 0, comm)) { + close(notify[READ]); close(notify[WRITE]); + close(dataPipe[READ]); close(dataPipe[WRITE]); + if(argv) { + free(argv); + } + os_log_error(AUTH_LOG, "comm pipe failure"); + return errAuthorizationToolExecuteFailure; + } + + OSStatus status = errSecSuccess; + + // do the standard forking tango... + int delay = 1; + for (int n = 5;; n--, delay *= 2) { + switch (fork()) { + case -1: // error + if (errno == EAGAIN) { + // potentially recoverable resource shortage + if (n > 0) { + os_log(AUTH_LOG, "resource shortage (EAGAIN), delaying %d seconds", delay); + sleep(delay); + continue; + } + } + os_log_error(AUTH_LOG, "fork failed (errno=%d)", errno); + close(notify[READ]); close(notify[WRITE]); + status = errAuthorizationToolExecuteFailure; + goto exit_point; + + default: { // parent + // close foreign side of pipes + close(notify[WRITE]); + if (communicationsPipe) + close(comm[WRITE]); + + close(dataPipe[READ]); + if (write(dataPipe[WRITE], extForm, sizeof(*extForm)) != sizeof(*extForm)) { + os_log_error(AUTH_LOG, "fwrite data failed (errno=%d)", errno); + status = errAuthorizationInternal; + close(notify[READ]); + close(dataPipe[WRITE]); + if (communicationsPipe) { + close(comm[READ]); + } + goto exit_point; + } + // get status notification from child + os_log_debug(AUTH_LOG, "parent waiting for status"); + ssize_t rc = read(notify[READ], &status, sizeof(status)); + status = n2h(status); + switch (rc) { + default: // weird result of read: post error + os_log_error(AUTH_LOG, "unexpected read return value %ld", long(rc)); + status = errAuthorizationToolEnvironmentError; + // fall through + case sizeof(status): // read succeeded: child reported an error + os_log_error(AUTH_LOG, "parent received status=%d", (int)status); + close(notify[READ]); + close(dataPipe[WRITE]); + if (communicationsPipe) { + close(comm[READ]); + close(comm[WRITE]); + } + goto exit_point; + case 0: // end of file: exec succeeded + close(notify[READ]); + close(dataPipe[WRITE]); + if (communicationsPipe) + *communicationsPipe = fdopen(comm[READ], "r+"); + os_log_debug(AUTH_LOG, "parent resumes (no error)"); + status = errSecSuccess; + goto exit_point; + } + } + + case 0: // child + // close foreign side of pipes + close(notify[READ]); + if (communicationsPipe) + close(comm[READ]); + + // close write end of the data PIPE + close(dataPipe[WRITE]); + + // fd 1 (stdout) holds the notify write end + dup2(notify[WRITE], 1); + close(notify[WRITE]); + + // fd 0 (stdin) holds either the comm-link write-end or /dev/null + if (communicationsPipe) { + dup2(comm[WRITE], 0); + close(comm[WRITE]); + } else { + close(0); + open("/dev/null", O_RDWR); + } + + // okay, execute the trampoline + if (argv) + execv(trampoline, (char *const*)argv); - // close mailbox file (child has it open now) - fclose(mbox); - - // get status notification from child - secinfo("authexec", "parent waiting for status"); - ssize_t rc = read(notify[READ], &status, sizeof(status)); - status = n2h(status); - switch (rc) { - default: // weird result of read: post error - secinfo("authexec", "unexpected read return value %ld", long(rc)); - status = errAuthorizationToolEnvironmentError; - // fall through - case sizeof(status): // read succeeded: child reported an error - secinfo("authexec", "parent received status=%d", (int)status); - close(notify[READ]); - if (communicationsPipe) { close(comm[READ]); close(comm[WRITE]); } - goto exit_point; - case 0: // end of file: exec succeeded - close(notify[READ]); - if (communicationsPipe) - *communicationsPipe = fdopen(comm[READ], "r+"); - secinfo("authexec", "parent resumes (no error)"); - status = errSecSuccess; - goto exit_point; - } + // execute failed - tell the parent + { + // in case of failure, close read end of the data pipe as well + close(dataPipe[WRITE]); + close(dataPipe[READ]); + OSStatus error = errAuthorizationToolExecuteFailure; + error = h2n(error); + write(1, &error, sizeof(error)); + _exit(1); + } } - - case 0: // child - // close foreign side of pipes - close(notify[READ]); - if (communicationsPipe) - close(comm[READ]); - - // fd 1 (stdout) holds the notify write end - dup2(notify[WRITE], 1); - close(notify[WRITE]); - - // fd 0 (stdin) holds either the comm-link write-end or /dev/null - if (communicationsPipe) { - dup2(comm[WRITE], 0); - close(comm[WRITE]); - } else { - close(0); - open("/dev/null", O_RDWR); - } - - // okay, execute the trampoline - if (argv) - execv(trampoline, (char *const*)argv); - - // execute failed - tell the parent - { - OSStatus error = errAuthorizationToolExecuteFailure; - error = h2n(error); - write(1, &error, sizeof(error)); - _exit(1); - } - } - } - + } + exit_point: - free(argv); - return status; + free(argv); + return status; } @@ -240,22 +278,212 @@ OSStatus AuthorizationExecuteWithPrivilegesExternalForm(const AuthorizationExter // Build an argv vector // static const char **argVector(const char *trampoline, const char *pathToTool, - const char *mboxFdText, char *const *arguments) +const char *mboxFdText, char *const *arguments) +{ + int length = 0; + if (arguments) { + for (char *const *p = arguments; *p; p++) + length++; + } + if (const char **args = (const char **)malloc(sizeof(const char *) * (length + 4))) { + args[0] = trampoline; + args[1] = pathToTool; + args[2] = mboxFdText; + if (arguments) + for (int n = 0; arguments[n]; n++) + args[n + 3] = arguments[n]; + args[length + 3] = NULL; + return args; + } + return NULL; +} + + + +OSStatus AuthorizationExecuteWithPrivilegesInternal(const AuthorizationRef authorization, + const char * _Nonnull pathToTool, + const char * _Nonnull const * arguments, + pid_t * newProcessPid, + const uid_t uid, + int stdOut, + int stdErr, + int stdIn, + void(^processFinished)(const int exitStatus)) { - int length = 0; - if (arguments) { - for (char *const *p = arguments; *p; p++) - length++; - } - if (const char **args = (const char **)malloc(sizeof(const char *) * (length + 4))) { - args[0] = trampoline; - args[1] = pathToTool; - args[2] = mboxFdText; - if (arguments) - for (int n = 0; arguments[n]; n++) - args[n + 3] = arguments[n]; - args[length + 3] = NULL; - return args; - } - return NULL; + // externalize the authorization + AuthorizationExternalForm extForm; + if (OSStatus err = AuthorizationMakeExternalForm(authorization, &extForm)) + return err; + + return AuthorizationExecuteWithPrivilegesExternalFormInternal(&extForm, pathToTool, arguments, newProcessPid, uid, stdOut, stdErr, stdIn, processFinished); +} + +OSStatus AuthorizationExecuteWithPrivilegesExternalFormInternal(const AuthorizationExternalForm *extAuthorization, + const char * _Nonnull pathToTool, + const char * _Nullable const * _Nullable arguments, + pid_t * newProcessPid, + const uid_t uid, + int stdOut, + int stdErr, + int stdIn, + void(^processFinished)(const int exitStatus)) +{ + xpc_object_t message; + __block OSStatus retval = errAuthorizationInternal; + dispatch_semaphore_t sema = dispatch_semaphore_create(0); + if (!sema) { + os_log_error(AUTH_LOG, "Unable to create trampoline semaphore"); + return retval; + } + __block xpc_connection_t trampolineConnection = xpc_connection_create_mach_service("com.apple.security.authtrampoline", NULL, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED); + + if (!trampolineConnection) { + os_log_error(AUTH_LOG, "Unable to create trampoline mach service"); + dispatch_release(sema); + return retval; + } + + xpc_connection_set_event_handler(trampolineConnection, ^(xpc_object_t event) { + xpc_type_t type = xpc_get_type(event); + + if (type == XPC_TYPE_ERROR) { + if (trampolineConnection) { + xpc_release(trampolineConnection); + trampolineConnection = NULL; + } + if (event == XPC_ERROR_CONNECTION_INTERRUPTED && processFinished) { + os_log_error(AUTH_LOG, "Connection with trampoline was interruped"); + processFinished(134); // simulate killed by SIGABRT + } + } else { + const char *requestId = xpc_dictionary_get_string(event, XPC_REQUEST_ID); + if (requestId && strncmp(XPC_EVENT_MSG, requestId, strlen(XPC_EVENT_MSG)) == 0) { + const char *eventType = xpc_dictionary_get_string(event, XPC_EVENT_TYPE); + if (eventType && strncmp(XPC_EVENT_TYPE_CHILDEND, eventType, strlen(XPC_EVENT_TYPE_CHILDEND)) == 0) { + int exitStatus = (int)xpc_dictionary_get_int64(event, RETVAL_STATUS); + os_log_debug(AUTH_LOG, "Child process ended with exit status %d", exitStatus); + + if (trampolineConnection) { + xpc_connection_cancel(trampolineConnection); + xpc_release(trampolineConnection); + trampolineConnection = NULL; + } + if (processFinished) { + processFinished(exitStatus); + }; + } else { + os_log_error(AUTH_LOG, "Unknown event type [%s] arrived from trampoline", eventType); + } + } else { + os_log_error(AUTH_LOG, "Unknown request [%s] arrived from trampoline", requestId); + } + } + }); + + xpc_connection_resume(trampolineConnection); + + message = xpc_dictionary_create(NULL, NULL, 0); + xpc_dictionary_set_string(message, XPC_REQUEST_ID, XPC_REQUEST_CREATE_PROCESS); + + Boolean waitForEndNeeded = (processFinished != NULL); + if (stdIn >= 0) { + xpc_object_t xpcInFd = xpc_fd_create(stdIn); + if (!xpcInFd) { + os_log_error(AUTH_LOG, "Unable to create XPC stdin FD"); + goto finish; + } + xpc_dictionary_set_value(message, PARAM_STDIN, xpcInFd); + xpc_release(xpcInFd); + waitForEndNeeded = true; + } + + if (stdOut >= 0) { + xpc_object_t xpcOutFd = xpc_fd_create(stdOut); + if (!xpcOutFd) { + os_log_error(AUTH_LOG, "Unable to create XPC stdout FD"); + goto finish; + } + xpc_dictionary_set_value(message, PARAM_STDOUT, xpcOutFd); + xpc_release(xpcOutFd); + waitForEndNeeded = true; + } + + if (stdErr >= 0) { + xpc_object_t xpcErrFd = xpc_fd_create(stdErr); + if (!xpcErrFd) { + os_log_error(AUTH_LOG, "Unable to create XPC stderr FD"); + goto finish; + } + xpc_dictionary_set_value(message, PARAM_STDERR, xpcErrFd); + xpc_release(xpcErrFd); + waitForEndNeeded = true; + } + + extern char** environ; + + if (environ) { + xpc_object_t envArray = xpc_array_create(NULL, 0); + char **ptr = environ; + + while (*ptr) { + xpc_object_t xpcString = xpc_string_create(*ptr++); + xpc_array_append_value(envArray, xpcString); + xpc_release(xpcString); + } + xpc_dictionary_set_value(message, PARAM_ENV, envArray); + xpc_release(envArray); + } + + xpc_dictionary_set_string(message, PARAM_TOOL_PATH, pathToTool); + xpc_dictionary_set_uint64(message, PARAM_EUID, uid); + { + const char *cwd = getcwd(NULL, 0); + if (cwd) { + xpc_dictionary_set_string(message, PARAM_CWD, cwd); + } + } + xpc_dictionary_set_bool(message, PARAM_CHILDEND_NEEDED, waitForEndNeeded); + + if (arguments) { + xpc_object_t paramsArray = xpc_array_create(NULL, 0); + int i = 0; + while (arguments[i] != NULL) { + xpc_object_t xpcString = xpc_string_create(arguments[i++]); + xpc_array_append_value(paramsArray, xpcString); + xpc_release(xpcString); + } + xpc_dictionary_set_value(message, PARAM_TOOL_PARAMS, paramsArray); + xpc_release(paramsArray); + } + xpc_dictionary_set_data(message, PARAM_AUTHREF, extAuthorization, sizeof(*extAuthorization)); + + retval = errAuthorizationToolExecuteFailure; + if (trampolineConnection) { + xpc_connection_send_message_with_reply(trampolineConnection, message, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(xpc_object_t event) { + xpc_type_t type = xpc_get_type(event); + const char *requestId = xpc_dictionary_get_string(event, XPC_REQUEST_ID); + if (type == XPC_TYPE_ERROR) { + os_log_error(AUTH_LOG, "Error when trying to communicate with the trampoline"); + } + else if (requestId && strncmp(XPC_REPLY_MSG, requestId, strlen(XPC_REPLY_MSG)) == 0) { + retval = (OSStatus)xpc_dictionary_get_int64(event, RETVAL_STATUS); + if (newProcessPid && retval == errAuthorizationSuccess) { + *newProcessPid = (OSStatus)xpc_dictionary_get_uint64(event, RETVAL_CHILD_PID); + } + } else { + os_log_error(AUTH_LOG, "Trampoline returned invalid data"); + } + dispatch_semaphore_signal(sema); + }); + dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); + } else { + os_log_error(AUTH_LOG, "Unable to establish connection to the trampoline"); + } + dispatch_release(sema); + +finish: + if (message) { + xpc_release(message); + } + return retval; } diff --git a/OSX/libsecurity_authorization/lib/trampolineServer.cpp b/OSX/libsecurity_authorization/lib/trampolineServer.cpp index bf25a801d..fc8c0ffdf 100644 --- a/OSX/libsecurity_authorization/lib/trampolineServer.cpp +++ b/OSX/libsecurity_authorization/lib/trampolineServer.cpp @@ -29,6 +29,8 @@ #include #include #include +#include +#include // // In a tool launched via AuthorizationCopyPrivilegedReference, retrieve a copy @@ -37,32 +39,46 @@ OSStatus AuthorizationCopyPrivilegedReference(AuthorizationRef *authorization, AuthorizationFlags flags) { + secalert("AuthorizationCopyPrivilegedReference is deprecated and functionality will be removed in macOS 10.14 - please update your application"); // flags are currently reserved if (flags != 0) return errAuthorizationInvalidFlags; // retrieve hex form of external form from environment const char *mboxFdText = getenv("__AUTHORIZATION"); - if (!mboxFdText) + if (!mboxFdText) { return errAuthorizationInvalidRef; + } - // retrieve mailbox file and read external form - AuthorizationExternalForm extForm; - int fd; - if (sscanf(mboxFdText, "auth %d", &fd) != 1) - return errAuthorizationInvalidRef; - if (lseek(fd, 0, SEEK_SET) || - read(fd, &extForm, sizeof(extForm)) != sizeof(extForm)) { - close(fd); - return errAuthorizationInvalidRef; - } + static AuthorizationExternalForm extForm; + static OSStatus result = errAuthorizationInvalidRef; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // retrieve the pipe and read external form + int fd; + if (sscanf(mboxFdText, "auth %d", &fd) != 1) { + return; + } + ssize_t numOfBytes = read(fd, &extForm, sizeof(extForm)); + close(fd); + if (numOfBytes == sizeof(extForm)) { + result = errAuthorizationSuccess; + } + }); + + if (result) { + // we had some trouble with reading the extform + return result; + } // internalize the authorization AuthorizationRef auth; if (OSStatus error = AuthorizationCreateFromExternalForm(&extForm, &auth)) return error; - // well, here you go - *authorization = auth; - return errSecSuccess; + if (authorization) { + *authorization = auth; + } + + return errAuthorizationSuccess; } diff --git a/OSX/libsecurity_cdsa_plugin/lib/CSPsession.cpp b/OSX/libsecurity_cdsa_plugin/lib/CSPsession.cpp index a66e068d3..c138fb5a8 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/CSPsession.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/CSPsession.cpp @@ -742,7 +742,11 @@ void CSPFullPluginSession::GenerateKeyPair(CSSM_CC_HANDLE ccHandle, // make data to be encrypted unsigned bytesInKey = encryptingKey->KeyHeader.LogicalKeySizeInBits / 8; - u_int8_t buffer[bytesInKey]; + u_int8_t *buffer = (u_int8_t*)malloc(bytesInKey); + if (buffer == NULL) { + CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR); + } + unsigned i; for (i = 0; i < bytesInKey; ++i) @@ -759,6 +763,7 @@ void CSPFullPluginSession::GenerateKeyPair(CSSM_CC_HANDLE ccHandle, CSSM_RETURN result = CSSM_CSP_CreateAsymmetricContext(moduleHandle, encryptingKey->KeyHeader.AlgorithmId, &nullCreds, encryptingKey, CSSM_PADDING_NONE, &encryptHandle); if (result != CSSM_OK) { + free(buffer); CssmError::throwMe(result); } @@ -769,6 +774,7 @@ void CSPFullPluginSession::GenerateKeyPair(CSSM_CC_HANDLE ccHandle, result = CSSM_QuerySize(encryptHandle, CSSM_TRUE, 1, &qsData); if (result == CSSMERR_CSP_INVALID_ALGORITHM) { + free(buffer); return; } @@ -780,6 +786,7 @@ void CSPFullPluginSession::GenerateKeyPair(CSSM_CC_HANDLE ccHandle, result = CSSM_EncryptData(encryptHandle, &clearBuf, 1, &cipherBuf, 1, &bytesEncrypted, &remData); if (result != CSSM_OK) { + free(buffer); CssmError::throwMe(result); } @@ -803,12 +810,14 @@ void CSPFullPluginSession::GenerateKeyPair(CSSM_CC_HANDLE ccHandle, if (result != CSSM_OK) { + free(buffer); CssmError::throwMe(result); } result = CSSM_DecryptData(decryptHandle, &cipherBuf, 1, &decryptedBuf, 1, &bytesEncrypted, &remData); if (result != CSSM_OK) { + free(buffer); CssmError::throwMe(result); } @@ -826,6 +835,8 @@ void CSPFullPluginSession::GenerateKeyPair(CSSM_CC_HANDLE ccHandle, { free(remData.Data); } + + free(buffer); } void CSPFullPluginSession::ObtainPrivateKeyFromPublicKey(const CssmKey &PublicKey, diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmaclpod.cpp b/OSX/libsecurity_cdsa_utilities/lib/cssmaclpod.cpp index 347971db7..e80d72135 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmaclpod.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmaclpod.cpp @@ -216,11 +216,12 @@ uint32 pinFromAclTag(const char *tag, const char *suffix /* = NULL */) if (tag) { char format[20]; snprintf(format, sizeof(format), "PIN%%d%s%%n", suffix ? suffix : ""); - uint32 pin; - unsigned consumed; - sscanf(tag, format, &pin, &consumed); - if (consumed == strlen(tag)) // complete and sufficient + uint32 pin = 0; + unsigned consumed = 0; + // sscanf does not count %n as a filled value so number of read variables should be just 1 + if (sscanf(tag, format, &pin, &consumed) == 1 && consumed == strlen(tag)) { // complete and sufficient return pin; + } } return 0; } diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmalloc.cpp b/OSX/libsecurity_cdsa_utilities/lib/cssmalloc.cpp index b2a476722..63d262b28 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmalloc.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmalloc.cpp @@ -30,6 +30,7 @@ #include #include #include +#include @@ -73,8 +74,12 @@ void *CssmAllocatorMemoryFunctions::relayRealloc(void *mem, size_t size, void *r void *CssmAllocatorMemoryFunctions::relayCalloc(uint32 count, size_t size, void *ref) throw(std::bad_alloc) { // Allocator doesn't have a calloc() method - void *mem = allocator(ref).malloc(size * count); - memset(mem, 0, size * count); + size_t alloc_size = 0; + if (os_mul_overflow(count, size, &alloc_size)) { + return NULL; + } + void *mem = allocator(ref).malloc(alloc_size); + memset(mem, 0, alloc_size); return mem; } diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmcred.cpp b/OSX/libsecurity_cdsa_utilities/lib/cssmcred.cpp index 5f877bbcc..ee66a633f 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmcred.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmcred.cpp @@ -30,20 +30,6 @@ namespace Security { - -// -// The null credential constant. -// -static const CSSM_ACCESS_CREDENTIALS null_credentials = { "" }; // and more nulls -#if BUG_GCC -const AccessCredentials &AccessCredentials::null = - *static_cast(&null_credentials); -#else -const AccessCredentials &AccessCredentials::null = - static_cast(null_credentials); -#endif - - // // Scan a SampleGroup for samples with a given CSSM_SAMPLE_TYPE. // Collect all matching samples into a list (which is cleared to begin with). @@ -67,6 +53,12 @@ bool SampleGroup::collect(CSSM_SAMPLE_TYPE sampleType, list &matches // // AccessCredentials // +const AccessCredentials& AccessCredentials::null_credential() +{ + static const CSSM_ACCESS_CREDENTIALS null_credentials = { "" }; // and more nulls + return AccessCredentials::overlay(null_credentials); +} + void AccessCredentials::tag(const char *tagString) { if (tagString == NULL) diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmcred.h b/OSX/libsecurity_cdsa_utilities/lib/cssmcred.h index 1b70b7675..2a827f187 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmcred.h +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmcred.h @@ -102,11 +102,11 @@ class AccessCredentials : public PodWrapper ObjectAcl::makers; -NormalMutex ObjectAcl::makersMutex; +ModuleNexus ObjectAcl::makersMutex; // @@ -579,7 +579,7 @@ void ObjectAcl::AclEntry::importBlob(Reader &pub, Reader &priv) AclSubject::Maker::Maker(CSSM_ACL_SUBJECT_TYPE type) : mType(type) { - StLock _(ObjectAcl::makersMutex); + StLock _(ObjectAcl::makersMutex()); ObjectAcl::makers()[type] = this; } @@ -598,7 +598,7 @@ AclSubject *ObjectAcl::make(uint32 typeAndVersion, Reader &pub, Reader &priv) AclSubject::Maker &ObjectAcl::makerFor(CSSM_ACL_SUBJECT_TYPE type) { - StLock _(ObjectAcl::makersMutex); + StLock _(ObjectAcl::makersMutex()); AclSubject::Maker *maker = makers()[type]; if (maker == NULL) CssmError::throwMe(CSSM_ERRCODE_ACL_SUBJECT_TYPE_NOT_SUPPORTED); diff --git a/OSX/libsecurity_cdsa_utilities/lib/objectacl.h b/OSX/libsecurity_cdsa_utilities/lib/objectacl.h index 67427cdf2..46cefc541 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/objectacl.h +++ b/OSX/libsecurity_cdsa_utilities/lib/objectacl.h @@ -242,7 +242,7 @@ class ObjectAcl { private: typedef map MakerMap; static ModuleNexus makers; // registered subject Makers - static NormalMutex makersMutex; + static ModuleNexus makersMutex; static AclSubject::Maker &makerFor(CSSM_ACL_SUBJECT_TYPE type); }; diff --git a/OSX/libsecurity_cdsa_utilities/lib/osxverifier.cpp b/OSX/libsecurity_cdsa_utilities/lib/osxverifier.cpp index 6075df06e..bd2b82999 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/osxverifier.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/osxverifier.cpp @@ -126,8 +126,8 @@ void OSXVerifier::makeLegacyHash(OSXCode *code, SHA1::Digest digest) { secinfo("codesign", "calculating legacy hash for %s", code->canonicalPath().c_str()); UnixPlusPlus::AutoFileDesc fd(code->executablePath(), O_RDONLY); - char buffer[legacyHashLimit]; - size_t size = fd.read(buffer, legacyHashLimit); + char buffer[LEGACY_HASH_LIMIT]; + size_t size = fd.read(buffer, LEGACY_HASH_LIMIT); SHA1 hash; hash(buffer, size); hash.finish(digest); diff --git a/OSX/libsecurity_cdsa_utilities/lib/osxverifier.h b/OSX/libsecurity_cdsa_utilities/lib/osxverifier.h index 0703c57d2..e2b9b1516 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/osxverifier.h +++ b/OSX/libsecurity_cdsa_utilities/lib/osxverifier.h @@ -25,11 +25,14 @@ #include #include #include +#include #include #include #include #include +#define LEGACY_HASH_LIMIT 16*1024 + namespace Security { @@ -42,7 +45,7 @@ namespace Security { // class OSXVerifier { public: - static const size_t legacyHashLimit = 16 * 1024; + static const size_t legacyHashLimit = LEGACY_HASH_LIMIT; static const uint32_t commentAlignment = 4; public: diff --git a/OSX/libsecurity_cdsa_utilities/lib/uniformrandom.cpp b/OSX/libsecurity_cdsa_utilities/lib/uniformrandom.cpp deleted file mode 100644 index 92c6f5079..000000000 --- a/OSX/libsecurity_cdsa_utilities/lib/uniformrandom.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2000-2001,2003-2004,2006,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@ - */ - - -// -// uniformrandom - uniformly distributed random number operators -// - -#include - - -namespace Security { - - - - -} // end namespace Security diff --git a/OSX/libsecurity_cdsa_utilities/lib/uniformrandom.h b/OSX/libsecurity_cdsa_utilities/lib/uniformrandom.h deleted file mode 100644 index ecbdae364..000000000 --- a/OSX/libsecurity_cdsa_utilities/lib/uniformrandom.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2000-2001,2003-2004,2006,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@ - */ - - -// -// uniformrandom - uniformly distributed random number operators -// -#ifndef _H_UNIFORMRANDOM -#define _H_UNIFORMRANDOM - -#include - - -namespace Security { - - -// -// Uniform binary blob generator. -// This operator deals exclusively in byte arrays. -// -template -class UniformRandomBlobs : public Generator { -public: - using Generator::random; - - template - void random(Object &obj) { random(&obj, sizeof(obj)); } - - void random(CssmData &data) { random(data.data(), data.length()); } -}; - - -}; // end namespace Security - - -#endif //_H_UNIFORMRANDOM diff --git a/OSX/libsecurity_cdsa_utils/lib/cuCdsaUtils.cpp b/OSX/libsecurity_cdsa_utils/lib/cuCdsaUtils.cpp index a516d3623..3171927a5 100644 --- a/OSX/libsecurity_cdsa_utils/lib/cuCdsaUtils.cpp +++ b/OSX/libsecurity_cdsa_utils/lib/cuCdsaUtils.cpp @@ -502,7 +502,7 @@ CSSM_RETURN cuCspGenKeyPair(CSSM_CSP_HANDLE cspHand, CSSM_CC_HANDLE ccHand; CSSM_DATA keyLabelData; - keyLabelData.Data = (uint8 *)keyLabel, + keyLabelData.Data = (uint8 *)keyLabel; keyLabelData.Length = keyLabelLen; memset(pubKey, 0, sizeof(CSSM_KEY)); memset(privKey, 0, sizeof(CSSM_KEY)); diff --git a/OSX/libsecurity_cdsa_utils/lib/cuTimeStr.cpp b/OSX/libsecurity_cdsa_utils/lib/cuTimeStr.cpp index fe246994e..4eccabc88 100644 --- a/OSX/libsecurity_cdsa_utils/lib/cuTimeStr.cpp +++ b/OSX/libsecurity_cdsa_utils/lib/cuTimeStr.cpp @@ -1,12 +1,12 @@ /* - * Copyright (c) 2002,2011-2012,2014 Apple Inc. All Rights Reserved. - * + * Copyright (c) 2002,2011-2012,2014-2019 Apple Inc. All Rights Reserved. + * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). * You may not use this file except in compliance with the License. Please obtain * a copy of the License at http://www.apple.com/publicsource and read it before * using this file. - * + * * This 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 @@ -14,11 +14,11 @@ * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the * specific language governing rights and limitations under the License. */ - + /* * cuTimeStr.cpp - time string routines */ -#include "cuTimeStr.h" +#include "cuTimeStr.h" #include "cuCdsaUtils.h" #include #include @@ -29,7 +29,7 @@ /* * Given a string containing either a UTC-style or "generalized time" * time string, convert to a struct tm (in GMT/UTC). Returns nonzero on - * error. + * error. */ int cuTimeStringToTm( const char *str, @@ -46,7 +46,7 @@ int cuTimeStringToTm( if((str == NULL) || (len == 0) || (tmp == NULL)) { return 1; } - + /* tolerate NULL terminated or not */ if(str[len - 1] == '\0') { len--; @@ -61,12 +61,12 @@ int cuTimeStringToTm( break; case GENERALIZED_TIME_STRLEN: // 4-digit year break; - default: // unknown format + default: // unknown format return 1; } - + cp = (char *)str; - + /* check that all characters except last are digits */ for(i=0; i<(len - 1); i++) { if ( !(isdigit(cp[i])) ) { @@ -88,13 +88,13 @@ int cuTimeStringToTm( szTemp[3] = *cp++; szTemp[4] = '\0'; } - else { + else { szTemp[2] = '\0'; } x = atoi( szTemp ); if(isUtc) { - /* - * 2-digit year. + /* + * 2-digit year. * 0 <= year < 50 : assume century 21 * 50 <= year < 70 : illegal per PKIX, though we tolerate * 70 < year <= 99 : assume century 20 @@ -109,7 +109,7 @@ int cuTimeStringToTm( */ else { /* century 20 */ - x += 1900; + x += 1900; } } /* by definition - tm_year is year - 1900 */ @@ -178,25 +178,37 @@ int cuTimeStringToTm( #define MAX_TIME_STR_LEN 30 /* protects time(), gmtime() */ -static pthread_mutex_t timeMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t timeMutex = PTHREAD_MUTEX_INITIALIZER; -char *cuTimeAtNowPlus(int secFromNow, +char *cuTimeAtNowPlus(int secFromNow, timeSpec spec) { struct tm utc; char *outStr; time_t baseTime; - + pthread_mutex_lock(&timeMutex); baseTime = time(NULL); baseTime += (time_t)secFromNow; utc = *gmtime(&baseTime); pthread_mutex_unlock(&timeMutex); - + outStr = (char *)APP_MALLOC(MAX_TIME_STR_LEN); - + + /* Check for legacy value of 1 */ + if (spec == CU_TIME_LEGACY) { +#if (TIME_UTC == 1) + /* time.h has defined TIME_UTC=1, so legacy caller + actually wants TIME_UTC, not TIME_CSSM. */ + spec = CU_TIME_UTC; +#else + spec = CU_TIME_CSSM; +#endif + } + switch(spec) { - case TIME_UTC: + case CU_TIME_UTC: + case CU_TIME_LEGACY: /* UTC - 2 year digits - code which parses this assumes that * (2-digit) years between 0 and 49 are in century 21 */ if(utc.tm_year >= 100) { @@ -206,16 +218,16 @@ char *cuTimeAtNowPlus(int secFromNow, utc.tm_year /* + 1900 */, utc.tm_mon + 1, utc.tm_mday, utc.tm_hour, utc.tm_min, utc.tm_sec); break; - case TIME_GEN: + case CU_TIME_GEN: sprintf(outStr, "%04d%02d%02d%02d%02d%02dZ", - /* note year is relative to 1900, hopefully it'll + /* note year is relative to 1900, hopefully it'll * have four valid digits! */ utc.tm_year + 1900, utc.tm_mon + 1, utc.tm_mday, utc.tm_hour, utc.tm_min, utc.tm_sec); break; - case TIME_CSSM: + case CU_TIME_CSSM: sprintf(outStr, "%04d%02d%02d%02d%02d%02d", - /* note year is relative to 1900, hopefully it'll have + /* note year is relative to 1900, hopefully it'll have * four valid digits! */ utc.tm_year + 1900, utc.tm_mon + 1, utc.tm_mday, utc.tm_hour, utc.tm_min, utc.tm_sec); @@ -227,17 +239,17 @@ char *cuTimeAtNowPlus(int secFromNow, /* * Convert a CSSM_X509_TIME, which can be in any of three forms (UTC, * generalized, or CSSM_TIMESTRING) into a CSSM_TIMESTRING. Caller - * must free() the result. Returns NULL if x509time is badly formed. + * must free() the result. Returns NULL if x509time is badly formed. */ char *cuX509TimeToCssmTimestring( const CSSM_X509_TIME *x509Time, unsigned *rtnLen) // for caller's convenience { int len = (int)x509Time->time.Length; - const char *inStr = (char *)x509Time->time.Data; + const char *inStr = (char *)x509Time->time.Data; // not NULL terminated! char *rtn; - + *rtnLen = 0; if((len == 0) || (inStr == NULL)) { return NULL; @@ -254,8 +266,8 @@ char *cuX509TimeToCssmTimestring( tmp[1] = inStr[1]; tmp[2] = '\0'; year = atoi(tmp); - - /* + + /* * 0 <= year < 50 : assume century 21 * 50 <= year < 70 : illegal per PKIX * 70 < year <= 99 : assume century 20 @@ -281,7 +293,7 @@ char *cuX509TimeToCssmTimestring( case GENERALIZED_TIME_STRLEN: memmove(rtn, inStr, len - 1); // don't copy the Z break; - + default: free(rtn); return NULL; diff --git a/OSX/libsecurity_cdsa_utils/lib/cuTimeStr.h b/OSX/libsecurity_cdsa_utils/lib/cuTimeStr.h index 0eefc56eb..77cef334f 100644 --- a/OSX/libsecurity_cdsa_utils/lib/cuTimeStr.h +++ b/OSX/libsecurity_cdsa_utils/lib/cuTimeStr.h @@ -1,25 +1,25 @@ /* - * Copyright (c) 2002,2011,2014 Apple Inc. All Rights Reserved. - * + * Copyright (c) 2002,2011,2014-2019 Apple Inc. All Rights Reserved. + * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). - * You may not use this file except in compliance with the License. + * You may not use this file except in compliance with the License. * Please obtain a copy of the License at http://www.apple.com/publicsource * and read it before using this file. - * + * * This 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, + * 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 + * Please see the License for the specific language governing rights * and limitations under the License. */ - + /* * cuTimeStr.h = Time string utilities. */ - + #ifndef _TIME_STR_H_ #define _TIME_STR_H_ @@ -38,7 +38,7 @@ extern "C" { /* * Given a string containing either a UTC-style or "generalized time" * time string, convert to a struct tm (in GMT/UTC). Returns nonzero on - * error. + * error. */ int cuTimeStringToTm( const char *str, @@ -46,23 +46,45 @@ int cuTimeStringToTm( struct tm *tmp); typedef enum { - TIME_UTC, - TIME_CSSM, - TIME_GEN + CU_TIME_UTC = 0, + CU_TIME_LEGACY = 1, /* do not use; see note below */ + CU_TIME_GEN = 2, + CU_TIME_CSSM = 3 } timeSpec; +/* TIME_UTC was formerly defined in this header with a value of 0. However, + * a newer version of may define it with a value of 1. Clients which + * specify the TIME_UTC constant for a timeSpec parameter will get a value + * of 0 under the old header, and a value of 1 under the newer header. + * The latter conflicts with the old definition of TIME_CSSM. To resolve this, + * we now treat 1 as a legacy value which maps to CU_TIME_UTC if TIME_UTC=1, + * otherwise to CU_TIME_CSSM. + * + * Important: any code which specifies the legacy TIME_CSSM constant must be + * recompiled against this header to ensure the correct timeSpec value is used. + */ +#ifndef TIME_UTC +#define TIME_UTC CU_TIME_UTC /* time.h has not defined TIME_UTC */ +#endif +#ifndef TIME_GEN +#define TIME_GEN CU_TIME_GEN +#endif +#ifndef TIME_CSSM +#define TIME_CSSM CU_TIME_CSSM +#endif + /* * Return an APP_MALLOCd time string, specified format and time relative * to 'now' in seconds. */ char *cuTimeAtNowPlus( - int secFromNow, + int secFromNow, timeSpec spec); /* * Convert a CSSM_X509_TIME, which can be in any of three forms (UTC, * generalized, or CSSM_TIMESTRING) into a CSSM_TIMESTRING. Caller - * must free() the result. Returns NULL if x509time is badly formed. + * must free() the result. Returns NULL if x509time is badly formed. */ char *cuX509TimeToCssmTimestring( const CSSM_X509_TIME *x509Time, diff --git a/OSX/libsecurity_cms/Info-security_cms.plist b/OSX/libsecurity_cms/Info-security_cms.plist deleted file mode 100644 index 0c67376eb..000000000 --- a/OSX/libsecurity_cms/Info-security_cms.plist +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/OSX/libsecurity_cms/lib/CMSDecoder.cpp b/OSX/libsecurity_cms/lib/CMSDecoder.cpp index 83775b23c..9fe2ecb96 100644 --- a/OSX/libsecurity_cms/lib/CMSDecoder.cpp +++ b/OSX/libsecurity_cms/lib/CMSDecoder.cpp @@ -25,8 +25,8 @@ * CMSDecoder.cpp - Interface for decoding CMS messages. */ -#include "CMSDecoder.h" -#include "CMSPrivate.h" +#include +#include #include "CMSUtils.h" #include <../libsecurity_codesigning/lib/csutilities.h> @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -311,7 +312,9 @@ OSStatus CMSDecoderFinalizeMessage( (SecCmsSignedDataRef)SecCmsContentInfoGetContent(ci); /* dig down one more layer for eContentType */ ci = SecCmsSignedDataGetContentInfo(cmsDecoder->signedData); - cmsDecoder->eContentType = SecCmsContentInfoGetContentTypeOID(ci); + if (ci) { + cmsDecoder->eContentType = SecCmsContentInfoGetContentTypeOID(ci); + } break; default: break; @@ -426,7 +429,7 @@ OSStatus CMSDecoderCopySignerStatus( SecTrustRef *secTrust, /* optional; RETURNED */ OSStatus *certVerifyResultCode) /* optional; RETURNED */ { - if((cmsDecoder == NULL) || (cmsDecoder->decState != DS_Final) || (!policyOrArray)) { + if((cmsDecoder == NULL) || (cmsDecoder->decState != DS_Final) || (!policyOrArray) || !signerStatus) { return errSecParam; } @@ -492,8 +495,7 @@ OSStatus CMSDecoderCopySignerStatus( if(secTrust != NULL) { *secTrust = theTrust; /* we'll release our reference at the end */ - if (theTrust) - CFRetain(theTrust); + CFRetainSafe(theTrust); } SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(cmsDecoder->signedData, (int)signerIndex); @@ -1003,8 +1005,8 @@ OSStatus CMSDecoderCopySignerAppleCodesigningHashAgility( int numContentInfos = 0; CFDataRef returnedValue = NULL; - require(cmsDecoder && hashAgilityAttrValue, xit); - require_noerr(CMSDecoderGetCmsMessage(cmsDecoder, &cmsg), xit); + require(cmsDecoder && hashAgilityAttrValue, exit); + require_noerr(CMSDecoderGetCmsMessage(cmsDecoder, &cmsg), exit); numContentInfos = SecCmsMessageContentLevelCount(cmsg); for (int dex = 0; !signedData && dex < numContentInfos; dex++) { @@ -1018,7 +1020,7 @@ OSStatus CMSDecoderCopySignerAppleCodesigningHashAgility( break; } } -xit: +exit: if (status == errSecSuccess && returnedValue) { *hashAgilityAttrValue = (CFDataRef) CFRetain(returnedValue); } else { @@ -1026,3 +1028,88 @@ OSStatus CMSDecoderCopySignerAppleCodesigningHashAgility( } return status; } + +/* + * Obtain the Hash Agility V2 attribute value of signer 'signerIndex' + * of a CMS message, if present. + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerAppleCodesigningHashAgilityV2( + CMSDecoderRef cmsDecoder, + size_t signerIndex, /* usually 0 */ + CFDictionaryRef CF_RETURNS_RETAINED *hashAgilityV2AttrValues) /* RETURNED */ +{ + OSStatus status = errSecParam; + SecCmsMessageRef cmsg; + SecCmsSignedDataRef signedData = NULL; + int numContentInfos = 0; + CFDictionaryRef returnedValue = NULL; + + require(cmsDecoder && hashAgilityV2AttrValues, exit); + require_noerr(CMSDecoderGetCmsMessage(cmsDecoder, &cmsg), exit); + numContentInfos = SecCmsMessageContentLevelCount(cmsg); + for (int dex = 0; !signedData && dex < numContentInfos; dex++) + { + SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsg, dex); + SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci); + if (tag == SEC_OID_PKCS7_SIGNED_DATA) + if ((signedData = (SecCmsSignedDataRef)SecCmsContentInfoGetContent(ci))) { + SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex); + if (signerInfo) + { + status = SecCmsSignerInfoGetAppleCodesigningHashAgilityV2(signerInfo, &returnedValue); + break; + } + } + } +exit: + if (status == errSecSuccess && returnedValue) { + *hashAgilityV2AttrValues = (CFDictionaryRef) CFRetain(returnedValue); + } else { + *hashAgilityV2AttrValues = NULL; + } + return status; +} + +/* + * Obtain the expiration time of signer 'signerIndex' of a CMS message, if + * present. This is part of the signed attributes of the message. + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerAppleExpirationTime( + CMSDecoderRef cmsDecoder, + size_t signerIndex, + CFAbsoluteTime *expirationTime) /* RETURNED */ +{ + OSStatus status = errSecParam; + SecCmsMessageRef cmsg = NULL; + int numContentInfos = 0; + SecCmsSignedDataRef signedData = NULL; + + require(cmsDecoder && expirationTime, xit); + require_noerr(CMSDecoderGetCmsMessage(cmsDecoder, &cmsg), xit); + numContentInfos = SecCmsMessageContentLevelCount(cmsg); + for (int dex = 0; !signedData && dex < numContentInfos; dex++) { + SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsg, dex); + SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci); + if (tag == SEC_OID_PKCS7_SIGNED_DATA) { + if ((signedData = (SecCmsSignedDataRef)SecCmsContentInfoGetContent(ci))) { + SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex); + if (signerInfo) { + status = SecCmsSignerInfoGetAppleExpirationTime(signerInfo, expirationTime); + break; + } + } + } + } +xit: + return status; +} diff --git a/OSX/libsecurity_cms/lib/CMSDecoder.h b/OSX/libsecurity_cms/lib/CMSDecoder.h deleted file mode 100644 index f0357bd03..000000000 --- a/OSX/libsecurity_cms/lib/CMSDecoder.h +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright (c) 2006-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@ - */ - -/* - * CMSDecoder.h - decode, decrypt, and/or verify signatures of messages in the - * Cryptographic Message Syntax (CMS), per RFC 3852. - * - * See CMSEncoder.h for general information about CMS messages. - */ - -#ifndef _CMS_DECODER_H_ -#define _CMS_DECODER_H_ - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -CF_ASSUME_NONNULL_BEGIN - -/* - * Opaque reference to a CMS decoder object. - * This is a CF object, with standard CF semantics; dispose of it - * with CFRelease(). - */ -typedef struct CF_BRIDGED_TYPE(id) _CMSDecoder *CMSDecoderRef; - -CFTypeID CMSDecoderGetTypeID(void); - -/* - * Status of signature and signer information in a signed message. - */ -typedef CF_ENUM(uint32_t, CMSSignerStatus) { - kCMSSignerUnsigned = 0, /* message was not signed */ - kCMSSignerValid, /* message was signed and signature verify OK */ - kCMSSignerNeedsDetachedContent, /* message was signed but needs detached content - * to verify */ - kCMSSignerInvalidSignature, /* message was signed but had a signature error */ - kCMSSignerInvalidCert, /* message was signed but an error occurred in verifying - * the signer's certificate */ - kCMSSignerInvalidIndex /* specified signer index out of range */ -}; - -/* - * Create a CMSDecoder. Result must eventually be freed via CFRelease(). - */ -OSStatus CMSDecoderCreate( - CMSDecoderRef * __nonnull CF_RETURNS_RETAINED cmsDecoderOut) /* RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Feed raw bytes of the message to be decoded into the decoder. Can be called - * multiple times. - * Returns errSecUnknownFormat upon detection of improperly formatted CMS - * message. - */ -OSStatus CMSDecoderUpdateMessage( - CMSDecoderRef cmsDecoder, - const void *msgBytes, - size_t msgBytesLen) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Indicate that no more CMSDecoderUpdateMessage() calls are forthcoming; - * finish decoding the message. - * Returns errSecUnknownFormat upon detection of improperly formatted CMS - * message. - */ -OSStatus CMSDecoderFinalizeMessage( - CMSDecoderRef cmsDecoder) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * A signed CMS message optionally includes the data which was signed. If the - * message does not include the signed data, caller specifies the signed data - * (the "detached content") here. - * - * This can be called either before or after the actual decoding of the message - * (via CMSDecoderUpdateMessage() and CMSDecoderFinalizeMessage()); the only - * restriction is that, if detached content is required, this function must - * be called befoere successfully ascertaining the signature status via - * CMSDecoderCopySignerStatus(). - */ -OSStatus CMSDecoderSetDetachedContent( - CMSDecoderRef cmsDecoder, - CFDataRef detachedContent) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Obtain the detached content specified in CMSDecoderSetDetachedContent(). - * Returns a NULL detachedContent if no detached content has been specified. - * Caller must CFRelease() the result. - */ -OSStatus CMSDecoderCopyDetachedContent( - CMSDecoderRef cmsDecoder, - CFDataRef * __nonnull CF_RETURNS_RETAINED detachedContentOut) /* RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * This function no longer affects the behavior of the CMS Decoder. Please - * discontinue use. - */ -OSStatus CMSDecoderSetSearchKeychain( - CMSDecoderRef cmsDecoder, - CFTypeRef keychainOrArray) - __OSX_AVAILABLE_BUT_DEPRECATED_MSG(__MAC_10_5, __MAC_10_13, __IPHONE_NA, __IPHONE_NA, - "To change the search keychains call SecKeychainSetSearchList."); - -/* - * Obtain the number of signers of a message. A result of zero indicates that - * the message was not signed. - * This cannot be called until after CMSDecoderFinalizeMessage() is called. - */ -OSStatus CMSDecoderGetNumSigners( - CMSDecoderRef cmsDecoder, - size_t *numSignersOut) /* RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Obtain the status of a CMS message's signature. A CMS message can - * be signed my multiple signers; this function returns the status - * associated with signer 'n' as indicated by the signerIndex parameter. - * - * This cannot be called until after CMSDecoderFinalizeMessage() is called. - * - * Note that signature and certificate verification of a decoded message - * does *not* occur until this routine is called. - * - * All returned values are optional - pass NULL if you don't need a - * particular parameter. - * - * Note that errors like "bad signature" and "bad cert" do NOT cause this - * routine to return a nonzero error status itself; such errors are reported - * in the various out parameters, listed below. - * - * Inputs: - * ------- - * cmsDecoder : a CMSDecoder which has successfully performed a - * CMSDecoderFinalizeMessage(). - * signerIndex : indicates which of 'n' signers is being examined. - * Range is 0...(numSigners-1). - * policyOrArray : Either a SecPolicyRef or a CFArray of them. - * These policies are used to verify the signer's certificate. - * evaluateSecTrust : When TRUE, causes the SecTrust oebject created for the - * evaluation of the signer cert to actually be evaluated - * via SecTrustEvaluate(). When FALSE, the caller performs - * the SecTrustEvaluate() operation on the SecTrust object - * returned via the secTrust out parameter. - * NOTE: it is hazardous and not recommended to pass in FALSE - * for the evaluateSecTrust parameter as well as NULL for the - * secTrust out parameter, since no evaluation of the signer - * cert can occur in that situation. - * - * Outputs: - * -------- - * signerStatusOut -- An enum indicating the overall status. - * kCMSSignerUnsigned : message was not signed. - * kCMSSignerValid : both signature and signer certificate verified OK. - * kCMSSignerNeedsDetachedContent : a call to CMSDecoderSetDetachedContent() - * is required to ascertain the signature status. - * kCMSSignerInvalidSignature : bad signature. - * kCMSSignerInvalidCert : an error occurred verifying the signer's certificate. - * Further information available via the secTrust and - * certVerifyResultCode parameters. This will never be - * returned if evaluateSecTrust is FALSE. - * kCMSSignerInvalidIndex : specified signerIndex is larger than the number of - * signers (minus 1). - * - * secTrustOut -- The SecTrust object used to verify the signer's - * certificate. Caller must CFRelease this. - * certVerifyResultCodeOut -- The result of the certificate verification. If - * the evaluateSecTrust argument is set to FALSE on - * input, this out parameter is undefined on return. - * - * The certVerifyResultCode value can indicate a large number of errors; some of - * the most common and interesting errors are: - * - * CSSMERR_TP_INVALID_ANCHOR_CERT : The cert was verified back to a - * self-signed (root) cert which was present in the message, but - * that root cert is not a known, trusted root cert. - * CSSMERR_TP_NOT_TRUSTED: The cert could not be verified back to - * a root cert. - * CSSMERR_TP_VERIFICATION_FAILURE: A root cert was found which does - * not self-verify. - * CSSMERR_TP_VERIFY_ACTION_FAILED: Indicates a failure of the requested - * policy action. - * CSSMERR_TP_INVALID_CERTIFICATE: Indicates a bad leaf cert. - * CSSMERR_TP_CERT_EXPIRED: A cert in the chain was expired at the time of - * verification. - * CSSMERR_TP_CERT_NOT_VALID_YET: A cert in the chain was not yet valie at - * the time of verification. - */ -OSStatus CMSDecoderCopySignerStatus( - CMSDecoderRef cmsDecoder, - size_t signerIndex, - CFTypeRef policyOrArray, - Boolean evaluateSecTrust, - CMSSignerStatus * __nullable signerStatusOut, /* optional; RETURNED */ - SecTrustRef * __nullable CF_RETURNS_RETAINED secTrustOut, /* optional; RETURNED */ - OSStatus * __nullable certVerifyResultCodeOut) /* optional; RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Obtain the email address of signer 'signerIndex' of a CMS message, if - * present. - * - * Returns errSecParam if the CMS message was not signed or if signerIndex - * is greater than the number of signers of the message minus one. - * - * This cannot be called until after CMSDecoderFinalizeMessage() is called. - */ -OSStatus CMSDecoderCopySignerEmailAddress( - CMSDecoderRef cmsDecoder, - size_t signerIndex, - CFStringRef * __nonnull CF_RETURNS_RETAINED signerEmailAddressOut) /* RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Obtain the certificate of signer 'signerIndex' of a CMS message, if - * present. - * - * Returns errSecParam if the CMS message was not signed or if signerIndex - * is greater than the number of signers of the message minus one. - * - * This cannot be called until after CMSDecoderFinalizeMessage() is called. - */ -OSStatus CMSDecoderCopySignerCert( - CMSDecoderRef cmsDecoder, - size_t signerIndex, - SecCertificateRef * __nonnull CF_RETURNS_RETAINED signerCertOut) /* RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Determine whether a CMS message was encrypted. Returns TRUE if so, FALSE if not. - * Note that if the message was encrypted, and the decoding succeeded, (i.e., - * CMSDecoderFinalizeMessage() returned errSecSuccess), then the message was successfully - * decrypted. - * This cannot be called until after CMSDecoderFinalizeMessage() is called. - */ -OSStatus CMSDecoderIsContentEncrypted( - CMSDecoderRef cmsDecoder, - Boolean *isEncryptedOut) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Obtain the eContentType OID for a SignedData's EncapsulatedContentType, if - * present. If the message was not signed this will return NULL. - * This cannot be called until after CMSDecoderFinalizeMessage() is called. - * The returned OID's data is in the same format as a CSSM_OID; i.e., it's - * the encoded content of the OID, not including the tag and length bytes. - */ -OSStatus CMSDecoderCopyEncapsulatedContentType( - CMSDecoderRef cmsDecoder, - CFDataRef * __nonnull CF_RETURNS_RETAINED eContentTypeOut) /* RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Obtain an array of all of the certificates in a message. Elements of the - * returned array are SecCertificateRefs. The caller must CFRelease the returned - * array. If a message does not contain any certificates (which is the case for - * a message which is encrypted but not signed), the returned *certs value - * is NULL. The function will return errSecSuccess in this case. - * This cannot be called until after CMSDecoderFinalizeMessage() is called. - */ -OSStatus CMSDecoderCopyAllCerts( - CMSDecoderRef cmsDecoder, - CFArrayRef * __nonnull CF_RETURNS_RETAINED certsOut) /* RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Obtain the actual message content (payload), if any. If the message was - * signed with detached content this will return NULL. - * Caller must CFRelease the result. - * This cannot be called until after CMSDecoderFinalizeMessage() is called. - */ -OSStatus CMSDecoderCopyContent( - CMSDecoderRef cmsDecoder, - CFDataRef * __nonnull CF_RETURNS_RETAINED contentOut) /* RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Obtain the signing time of signer 'signerIndex' of a CMS message, if - * present. This is an unauthenticate time, although it is part of the - * signed attributes of the message. - * - * Returns errSecParam if the CMS message was not signed or if signerIndex - * is greater than the number of signers of the message minus one. - * - * This cannot be called until after CMSDecoderFinalizeMessage() is called. - */ -OSStatus CMSDecoderCopySignerSigningTime( - CMSDecoderRef cmsDecoder, - size_t signerIndex, - CFAbsoluteTime *signingTime) /* RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_NA); - -/* - * Obtain the timestamp of signer 'signerIndex' of a CMS message, if - * present. This timestamp is an authenticated timestamp provided by - * a timestamping authority. - * - * Returns errSecParam if the CMS message was not signed or if signerIndex - * is greater than the number of signers of the message minus one. - * - * This cannot be called until after CMSDecoderFinalizeMessage() is called. - */ -OSStatus CMSDecoderCopySignerTimestamp( - CMSDecoderRef cmsDecoder, - size_t signerIndex, - CFAbsoluteTime *timestamp) /* RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_NA); - - /* - * Obtain the timestamp of signer 'signerIndex' of a CMS message, if - * present. This timestamp is an authenticated timestamp provided by - * a timestamping authority. Use the policy provided as a parameter - * - * Returns errSecParam if the CMS message was not signed or if signerIndex - * is greater than the number of signers of the message minus one. - * - * This cannot be called until after CMSDecoderFinalizeMessage() is called. - */ -OSStatus CMSDecoderCopySignerTimestampWithPolicy( - CMSDecoderRef cmsDecoder, - CFTypeRef __nullable timeStampPolicy, - size_t signerIndex, /* usually 0 */ - CFAbsoluteTime *timestamp) /* RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_NA); - -/* - * Obtain an array of the certificates in a timestamp response. Elements of the - * returned array are SecCertificateRefs. The caller must CFRelease the returned - * array. This timestamp is an authenticated timestamp provided by - * a timestamping authority. - * - * Returns errSecParam if the CMS message was not signed or if signerIndex - * is greater than the number of signers of the message minus one. It returns - * errSecItemNotFound if no certificates were found. - * - * This cannot be called until after CMSDecoderFinalizeMessage() is called. - */ -OSStatus CMSDecoderCopySignerTimestampCertificates( - CMSDecoderRef cmsDecoder, - size_t signerIndex, /* usually 0 */ - CFArrayRef * __nonnull CF_RETURNS_RETAINED certificateRefs) /* RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_NA); - -CF_ASSUME_NONNULL_END - -#ifdef __cplusplus -} -#endif - -#endif /* _CMS_DECODER_H_ */ - diff --git a/OSX/libsecurity_cms/lib/CMSEncoder.cpp b/OSX/libsecurity_cms/lib/CMSEncoder.cpp index c3f431477..27d6810da 100644 --- a/OSX/libsecurity_cms/lib/CMSEncoder.cpp +++ b/OSX/libsecurity_cms/lib/CMSEncoder.cpp @@ -25,8 +25,8 @@ * CMSEncoder.cpp - encode, sign, and/or encrypt CMS messages. */ -#include "CMSEncoder.h" -#include "CMSPrivate.h" +#include +#include #include "CMSUtils.h" #include #include @@ -98,6 +98,8 @@ struct _CMSEncoder { CMSCertificateChainMode chainMode; CFDataRef hashAgilityAttrValue; + CFDictionaryRef hashAgilityV2AttrValues; + CFAbsoluteTime expirationTime; }; static void cmsEncoderInit(CFTypeRef enc); @@ -279,12 +281,20 @@ static int convertOid( // CFStringRef: OID representation is a dotted-decimal string CFStringRef inStr = (CFStringRef)inRef; CFIndex max = CFStringGetLength(inStr) * 3; - char buf[max]; - if (!CFStringGetCString(inStr, buf, max-1, kCFStringEncodingASCII)) + char *buf = (char *)malloc(max); + if (!buf) { + return errSecMemoryError; + } + if (!CFStringGetCString(inStr, buf, max-1, kCFStringEncodingASCII)) { + free(buf); return errSecParam; + } - if(encodeOid((unsigned char *)buf, &oidData, &oidLen) != 0) + if (encodeOid((unsigned char *)buf, &oidData, &oidLen) != 0) { + free(buf); return errSecParam; + } + free(buf); } else if (CFGetTypeID(inRef) == CFDataGetTypeID()) { // CFDataRef: OID representation is in binary DER format @@ -458,6 +468,9 @@ static OSStatus cmsSetupForSignedData( case kCMSCertificateChainWithRoot: chainMode = SecCmsCMCertChainWithRoot; break; + case kCMSCertificateChainWithRootOrFail: + chainMode = SecCmsCMCertChainWithRootOrFail; + break; default: break; } @@ -532,6 +545,24 @@ static OSStatus cmsSetupForSignedData( break; } } + if(cmsEncoder->signedAttributes & kCMSAttrAppleCodesigningHashAgilityV2) { + ortn = SecCmsSignerInfoAddAppleCodesigningHashAgilityV2(signerInfo, cmsEncoder->hashAgilityV2AttrValues); + /* libsecurity_smime made a copy of the attribute value. We don't need it anymore. */ + CFReleaseNull(cmsEncoder->hashAgilityV2AttrValues); + if(ortn) { + ortn = cmsRtnToOSStatus(ortn); + CSSM_PERROR("SecCmsSignerInfoAddAppleCodesigningHashAgilityV2", ortn); + break; + } + } + if (cmsEncoder->signedAttributes & kCMSAttrAppleExpirationTime) { + ortn = SecCmsSignerInfoAddAppleExpirationTime(signerInfo, cmsEncoder->expirationTime); + if(ortn) { + ortn = cmsRtnToOSStatus(ortn); + CSSM_PERROR("SecCmsSignerInfoAddAppleExpirationTime", ortn); + break; + } + } ortn = SecCmsSignedDataAddSignerInfo(signedData, signerInfo); if(ortn) { @@ -1024,6 +1055,40 @@ OSStatus CMSEncoderSetAppleCodesigningHashAgility( return errSecSuccess; } +/* + * Set the hash agility attribute for a CMSEncoder. + * This is only used if the kCMSAttrAppleCodesigningHashAgilityV2 attribute + * is included. + */ +OSStatus CMSEncoderSetAppleCodesigningHashAgilityV2( + CMSEncoderRef cmsEncoder, + CFDictionaryRef hashAgilityV2AttrValues) +{ + if (cmsEncoder == NULL || cmsEncoder->encState != ES_Init) { + return errSecParam; + } + cmsEncoder->hashAgilityV2AttrValues = CFRetainSafe(hashAgilityV2AttrValues); + return errSecSuccess; +} + +/* + * Set the expiration time for a CMSEncoder. + * This is only used if the kCMSAttrAppleExpirationTime attribute is included. + */ +OSStatus CMSEncoderSetAppleExpirationTime( + CMSEncoderRef cmsEncoder, + CFAbsoluteTime time) +{ + if(cmsEncoder == NULL) { + return errSecParam; + } + if(cmsEncoder->encState != ES_Init) { + return errSecParam; + } + cmsEncoder->expirationTime = time; + return errSecSuccess; +} + OSStatus CMSEncoderSetCertificateChainMode( CMSEncoderRef cmsEncoder, CMSCertificateChainMode chainMode) @@ -1039,6 +1104,7 @@ OSStatus CMSEncoderSetCertificateChainMode( case kCMSCertificateSignerOnly: case kCMSCertificateChain: case kCMSCertificateChainWithRoot: + case kCMSCertificateChainWithRootOrFail: break; default: return errSecParam; diff --git a/OSX/libsecurity_cms/lib/CMSEncoder.h b/OSX/libsecurity_cms/lib/CMSEncoder.h deleted file mode 100644 index 7bb5596c7..000000000 --- a/OSX/libsecurity_cms/lib/CMSEncoder.h +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright (c) 2006-2012 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@ - */ - -/* - * CMSEncoder.h - encode, sign, and/or encrypt messages in the Cryptographic - * Message Syntax (CMS), per RFC 3852. - * - * A CMS message can be signed, encrypted, or both. A message can be signed by - * an arbitrary number of signers; in this module, signers are expressed as - * SecIdentityRefs. A message can be encrypted for an arbitrary number of - * recipients; recipients are expressed here as SecCertificateRefs. - * - * In CMS terminology, this module performs encryption using the EnvelopedData - * ContentType and signing using the SignedData ContentType. - * - * If the message is both signed and encrypted, it uses "nested ContentInfos" - * in CMS terminology; in this implementation, signed & encrypted messages - * are implemented as an EnvelopedData containing a SignedData. - */ - -#ifndef _CMS_ENCODER_H_ -#define _CMS_ENCODER_H_ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -CF_ASSUME_NONNULL_BEGIN - -/* - * Opaque reference to a CMS encoder object. - * This is a CF object, with standard CF semantics; dispose of it - * with CFRelease(). - */ -typedef struct CF_BRIDGED_TYPE(id) _CMSEncoder *CMSEncoderRef; - -CFTypeID CMSEncoderGetTypeID(void) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Create a CMSEncoder. Result must eventually be freed via CFRelease(). - */ -OSStatus CMSEncoderCreate( - CMSEncoderRef * __nonnull CF_RETURNS_RETAINED cmsEncoderOut) /* RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -extern const CFStringRef kCMSEncoderDigestAlgorithmSHA1; -extern const CFStringRef kCMSEncoderDigestAlgorithmSHA256; - -OSStatus CMSEncoderSetSignerAlgorithm( - CMSEncoderRef cmsEncoder, - CFStringRef digestAlgorithm) - __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_NA); - -/* - * Specify signers of the CMS message; implies that the message will be signed. - * - * -- Caller can pass in one signer, as a SecIdentityRef, or an array of - * signers, as a CFArray of SecIdentityRefs. - * -- Can be called multiple times. - * -- If the message is not to be signed, don't call this. - * -- If this is called, it must be called before the first call to - * CMSEncoderUpdateContent(). - */ -OSStatus CMSEncoderAddSigners( - CMSEncoderRef cmsEncoder, - CFTypeRef signerOrArray) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Obtain an array of signers as specified in CMSEncoderSetSigners(). - * Returns a NULL signers array if CMSEncoderSetSigners() has not been called. - * Caller must CFRelease the result. - */ -OSStatus CMSEncoderCopySigners( - CMSEncoderRef cmsEncoder, - CFArrayRef * __nonnull CF_RETURNS_RETAINED signersOut) /* RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Specify recipients of the message. Implies that the message will - * be encrypted. - * - * -- Caller can pass in one recipient, as a SecCertificateRef, or an - * array of recipients, as a CFArray of SecCertificateRefs. - * -- Can be called multiple times. - * -- If the message is not to be encrypted, don't call this. - * -- If this is called, it must be called before the first call to - * CMSEncoderUpdateContent(). - */ -OSStatus CMSEncoderAddRecipients( - CMSEncoderRef cmsEncoder, - CFTypeRef recipientOrArray) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Obtain an array of recipients as specified in CMSEncoderSetRecipients(). - * Returns a NULL recipients array if CMSEncoderSetRecipients() has not been - * called. - * Caller must CFRelease the result. - */ -OSStatus CMSEncoderCopyRecipients( - CMSEncoderRef cmsEncoder, - CFArrayRef * __nonnull CF_RETURNS_RETAINED recipientsOut) /* RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * A signed message optionally includes the data to be signed. If the message - * is *not* to include the data to be signed, call this function with a value - * of TRUE for detachedContent. The default, if this function is not called, - * is detachedContent=FALSE, i.e., the message contains the data to be signed. - * - * -- Encrypted messages can not use detached content. (This restriction - * also applies to messages that are both signed and encrypted.) - * -- If this is called, it must be called before the first call to - * CMSEncoderUpdateContent(). - */ -OSStatus CMSEncoderSetHasDetachedContent( - CMSEncoderRef cmsEncoder, - Boolean detachedContent) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Obtain a Boolean indicating whether the current message will have detached - * content. - * Returns the value specified in CMSEncoderHasDetachedContent() if that - * function has been called; else returns the default FALSE. - */ -OSStatus CMSEncoderGetHasDetachedContent( - CMSEncoderRef cmsEncoder, - Boolean *detachedContentOut) /* RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Optionally specify an eContentType OID for the inner EncapsulatedData for - * a signed message. The default eContentType, used if this function is not - * called, is id-data (which is the normal eContentType for applications such - * as SMIME). - * - * If this is called, it must be called before the first call to - * CMSEncoderUpdateContent(). - * - * NOTE: This function is deprecated in Mac OS X 10.7 and later; - * please use CMSEncoderSetEncapsulatedContentTypeOID() instead. - */ -OSStatus CMSEncoderSetEncapsulatedContentType( - CMSEncoderRef cmsEncoder, - const CSSM_OID *eContentType) - /* DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; */ - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Optionally specify an eContentType OID for the inner EncapsulatedData for - * a signed message. The default eContentTypeOID, used if this function is not - * called, is id-data (which is the normal eContentType for applications such - * as SMIME). - * - * The eContentTypeOID parameter may be specified as a CF string, e.g.: - * CFSTR("1.2.840.113549.1.7.1") - * - * If this is called, it must be called before the first call to - * CMSEncoderUpdateContent(). - */ -OSStatus CMSEncoderSetEncapsulatedContentTypeOID( - CMSEncoderRef cmsEncoder, - CFTypeRef eContentTypeOID) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -/* - * Obtain the eContentType OID specified in CMSEncoderSetEncapsulatedContentType(). - * If CMSEncoderSetEncapsulatedContentType() has not been called this returns a - * NULL pointer. - * The returned OID's data is in the same format as the data provided to - * CMSEncoderSetEncapsulatedContentType;, i.e., it's the encoded content of - * the OID, not including the tag and length bytes. - */ -OSStatus CMSEncoderCopyEncapsulatedContentType( - CMSEncoderRef cmsEncoder, - CFDataRef * __nonnull CF_RETURNS_RETAINED eContentTypeOut) /* RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Signed CMS messages can contain arbitrary sets of certificates beyond those - * indicating the identity of the signer(s). This function provides a means of - * adding these other certs. For normal signed messages it is not necessary to - * call this; the signer cert(s) and the intermediate certs needed to verify the - * signer(s) will be included in the message implicitly. - * - * -- Caller can pass in one cert, as a SecCertificateRef, or an array of certs, - * as a CFArray of SecCertificateRefs. - * -- If this is called, it must be called before the first call to - * CMSEncoderUpdateContent(). - * -- There is a "special case" use of CMS messages which involves neither - * signing nor encryption, but does include certificates. This is commonly - * used to transport "bags" of certificates. When constructing such a - * message, all an application needs to do is to create a CMSEncoderRef, - * call CMSEncoderAddSupportingCerts() one or more times, and then call - * CMSEncoderCopyEncodedContent() to get the resulting cert bag. No 'content' - * need be specified. (This is in fact the primary intended use for - * this function.) - */ -OSStatus CMSEncoderAddSupportingCerts( - CMSEncoderRef cmsEncoder, - CFTypeRef certOrArray) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Obtain the SecCertificates provided in CMSEncoderAddSupportingCerts(). - * If CMSEncoderAddSupportingCerts() has not been called this will return a - * NULL value for *certs. - * Caller must CFRelease the result. - */ -OSStatus CMSEncoderCopySupportingCerts( - CMSEncoderRef cmsEncoder, - CFArrayRef * __nonnull CF_RETURNS_RETAINED certsOut) /* RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Standard signed attributes, optionally specified in - * CMSEncoderAddSignedAttributes(). - */ -typedef CF_OPTIONS(uint32_t, CMSSignedAttributes) { - kCMSAttrNone = 0x0000, - /* - * S/MIME Capabilities - identifies supported signature, encryption, and - * digest algorithms. - */ - kCMSAttrSmimeCapabilities = 0x0001, - /* - * Indicates that a cert is the preferred cert for S/MIME encryption. - */ - kCMSAttrSmimeEncryptionKeyPrefs = 0x0002, - /* - * Same as kCMSSmimeEncryptionKeyPrefs, using an attribute OID preferred - * by Microsoft. - */ - kCMSAttrSmimeMSEncryptionKeyPrefs = 0x0004, - /* - * Include the signing time. - */ - kCMSAttrSigningTime = 0x0008, - /* - * Include the Apple Codesigning Hash Agility. - */ - kCMSAttrAppleCodesigningHashAgility = 0x0010 -}; - -/* - * Optionally specify signed attributes. Only meaningful when creating a - * signed message. If this is called, it must be called before - * CMSEncoderUpdateContent(). - */ -OSStatus CMSEncoderAddSignedAttributes( - CMSEncoderRef cmsEncoder, - CMSSignedAttributes signedAttributes) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Specification of what certificates to include in a signed message. - */ -typedef CF_ENUM(uint32_t, CMSCertificateChainMode) { - kCMSCertificateNone = 0, /* don't include any certificates */ - kCMSCertificateSignerOnly, /* only include signer certificate(s) */ - kCMSCertificateChain, /* signer certificate chain up to but not - * including root certiticate */ - kCMSCertificateChainWithRoot /* signer certificate chain including root */ -}; - -/* - * Optionally specify which certificates, if any, to include in a - * signed CMS message. The default, if this is not called, is - * kCMSCertificateChain, in which case the signer cert plus all CA - * certs needed to verify the signer cert, except for the root - * cert, are included. - * If this is called, it must be called before - * CMSEncoderUpdateContent(). - */ -OSStatus CMSEncoderSetCertificateChainMode( - CMSEncoderRef cmsEncoder, - CMSCertificateChainMode chainMode) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Obtain indication of which signer certs are to be included - * in a signed CMS message. - */ -OSStatus CMSEncoderGetCertificateChainMode( - CMSEncoderRef cmsEncoder, - CMSCertificateChainMode *chainModeOut) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Feed content bytes into the encoder. - * Can be called multiple times. - * No 'setter' routines can be called after this function has been called. - */ -OSStatus CMSEncoderUpdateContent( - CMSEncoderRef cmsEncoder, - const void *content, - size_t contentLen) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * Finish encoding the message and obtain the encoded result. - * Caller must CFRelease the result. - */ -OSStatus CMSEncoderCopyEncodedContent( - CMSEncoderRef cmsEncoder, - CFDataRef * __nonnull CF_RETURNS_RETAINED encodedContentOut) /* RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - -/* - * High-level, one-shot encoder function. - * - * Inputs (all except for content optional, though at least one - * of {signers, recipients} must be non-NULL) - * ------------------------------------------------------------ - * signers : signer identities. Either a SecIdentityRef, or a - * CFArray of them. - * recipients : recipient certificates. Either a SecCertificateRef, - * or a CFArray of them. - * eContentType : contentType for inner EncapsulatedData. - * detachedContent : when true, do not include the signed data in the message. - * signedAttributes : Specifies which standard signed attributes are to be - * included in the message. - * content : raw content to be signed and/or encrypted. - * - * Output - * ------ - * encodedContent : the result of the encoding. - * - * NOTE: This function is deprecated in Mac OS X 10.7 and later; - * please use CMSEncodeContent() instead. - */ -OSStatus CMSEncode( - CFTypeRef __nullable signers, - CFTypeRef __nullable recipients, - const CSSM_OID * __nullable eContentType, - Boolean detachedContent, - CMSSignedAttributes signedAttributes, - const void * content, - size_t contentLen, - CFDataRef * __nonnull CF_RETURNS_RETAINED encodedContentOut) /* RETURNED */ - /* DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; */ - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - - -/* - * High-level, one-shot encoder function. - * - * Inputs (all except for content optional, though at least one - * of {signers, recipients} must be non-NULL) - * ------------------------------------------------------------ - * signers : signer identities. Either a SecIdentityRef, or a - * CFArray of them. - * recipients : recipient certificates. Either a SecCertificateRef, - * or a CFArray of them. - * eContentTypeOID : contentType OID for inner EncapsulatedData, e.g.: - * CFSTR("1.2.840.113549.1.7.1") - * detachedContent : when true, do not include the signed data in the message. - * signedAttributes : Specifies which standard signed attributes are to be - * included in the message. - * content : raw content to be signed and/or encrypted. - * - * Output - * ------ - * encodedContent : the result of the encoding. - */ -OSStatus CMSEncodeContent( - CFTypeRef __nullable signers, - CFTypeRef __nullable recipients, - CFTypeRef __nullable eContentTypeOID, - Boolean detachedContent, - CMSSignedAttributes signedAttributes, - const void *content, - size_t contentLen, - CFDataRef * __nullable CF_RETURNS_RETAINED encodedContentOut) /* RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -OSStatus CMSEncoderCopySignerTimestamp( - CMSEncoderRef cmsEncoder, - size_t signerIndex, /* usually 0 */ - CFAbsoluteTime *timestamp) /* RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_NA); - -OSStatus CMSEncoderCopySignerTimestampWithPolicy( - CMSEncoderRef cmsEncoder, - CFTypeRef __nullable timeStampPolicy, - size_t signerIndex, /* usually 0 */ - CFAbsoluteTime *timestamp) /* RETURNED */ - __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_NA); - -CF_ASSUME_NONNULL_END - -#ifdef __cplusplus -} -#endif - -#endif /* _CMS_ENCODER_H_ */ - diff --git a/OSX/libsecurity_cms/lib/CMSPrivate.h b/OSX/libsecurity_cms/lib/CMSPrivate.h deleted file mode 100644 index b61296b24..000000000 --- a/OSX/libsecurity_cms/lib/CMSPrivate.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2006,2011-2012,2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* - * CMSPrivate.h - access to low-level CMS objects used by CMSDecoder and CMSEncoder. - */ -#ifndef _CMS_PRIVATE_H_ -#define _CMS_PRIVATE_H_ - -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/*** - *** Private CMSEncoder routines - ***/ - -/* - * Obtain the SecCmsMessageRef associated with a CMSEncoderRef. Intended - * to be called after (optionally) setting the encoder's various attributes - * via CMSEncoderAddSigners(), CMSEncoderAddRecipients(), etc. and before - * the first call to CMSEncoderUpdateContent(). The returned SecCmsMessageRef - * will be initialized per the previously specified attributes; the caller - * can manipulate the SecCmsMessageRef prior to proceeding with - * CMSEncoderUpdateContent() calls. - */ -OSStatus CMSEncoderGetCmsMessage( - CMSEncoderRef cmsEncoder, - SecCmsMessageRef *cmsMessage); /* RETURNED */ - -/* - * Optionally specify a SecCmsEncoderRef to use with a CMSEncoderRef. - * If this is called, it must be called before the first call to - * CMSEncoderUpdateContent(). The CMSEncoderRef takes ownership of the - * incoming SecCmsEncoderRef. - */ -OSStatus CMSEncoderSetEncoder( - CMSEncoderRef cmsEncoder, - SecCmsEncoderRef encoder); - -/* - * Obtain the SecCmsEncoderRef associated with a CMSEncoderRef. - * Returns a NULL SecCmsEncoderRef if neither CMSEncoderSetEncoder nor - * CMSEncoderUpdateContent() has been called. - * The CMSEncoderRef retains ownership of the SecCmsEncoderRef. - */ -OSStatus CMSEncoderGetEncoder( - CMSEncoderRef cmsEncoder, - SecCmsEncoderRef *encoder); /* RETURNED */ - -/* - * Set the signing time for a CMSEncoder. - * This is only used if the kCMSAttrSigningTime attribute is included. - */ -OSStatus CMSEncoderSetSigningTime( - CMSEncoderRef cmsEncoder, - CFAbsoluteTime time); - -/* - * Set the hash agility attribute for a CMSEncoder. - * This is only used if the kCMSAttrAppleCodesigningHashAgility attribute - * is included. - */ -OSStatus CMSEncoderSetAppleCodesigningHashAgility( - CMSEncoderRef cmsEncoder, - CFDataRef hashAgilityAttrValue); - -void -CmsMessageSetTSAContext(CMSEncoderRef cmsEncoder, CFTypeRef tsaContext); - -/*** - *** Private CMSDecoder routines - ***/ - -/* - * Obtain the SecCmsMessageRef associated with a CMSDecoderRef. Intended - * to be called after decoding the message (i.e., after - * CMSDecoderFinalizeMessage() to gain finer access to the contents of the - * SecCmsMessageRef than is otherwise available via the CMSDecoder interface. - * Returns a NULL SecCmsMessageRef if CMSDecoderFinalizeMessage() has not been - * called. - * - * The CMSDecoder retains ownership of the returned SecCmsMessageRef. - */ -OSStatus CMSDecoderGetCmsMessage( - CMSDecoderRef cmsDecoder, - SecCmsMessageRef *cmsMessage); /* RETURNED */ - - -/* - * Optionally specify a SecCmsDecoderRef to use with a CMSDecoderRef. - * If this is called, it must be called before the first call to - * CMSDecoderUpdateMessage(). The CMSDecoderRef takes ownership of the - * incoming SecCmsDecoderRef. - */ -OSStatus CMSDecoderSetDecoder( - CMSDecoderRef cmsDecoder, - SecCmsDecoderRef decoder); - -/* - * Obtain the SecCmsDecoderRef associated with a CMSDecoderRef. - * Returns a NULL SecCmsDecoderRef if neither CMSDecoderSetDecoder() nor - * CMSDecoderUpdateMessage() has been called. - * The CMSDecoderRef retains ownership of the SecCmsDecoderRef. - */ -OSStatus CMSDecoderGetDecoder( - CMSDecoderRef cmsDecoder, - SecCmsDecoderRef *decoder); /* RETURNED */ - -/* - * Obtain the Hash Agility attribute value of signer 'signerIndex' - * of a CMS message, if present. - * - * Returns errSecParam if the CMS message was not signed or if signerIndex - * is greater than the number of signers of the message minus one. - * - * This cannot be called until after CMSDecoderFinalizeMessage() is called. - */ -OSStatus CMSDecoderCopySignerAppleCodesigningHashAgility( - CMSDecoderRef cmsDecoder, - size_t signerIndex, /* usually 0 */ - CFDataRef CF_RETURNS_RETAINED *hashAgilityAttrValue); /* RETURNED */ - -#ifdef __cplusplus -} -#endif - -#endif /* _CMS_PRIVATE_H_ */ - diff --git a/OSX/libsecurity_cms/libsecurity_cms.xcodeproj/project.pbxproj b/OSX/libsecurity_cms/libsecurity_cms.xcodeproj/project.pbxproj deleted file mode 100644 index 85031b839..000000000 --- a/OSX/libsecurity_cms/libsecurity_cms.xcodeproj/project.pbxproj +++ /dev/null @@ -1,397 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 052C07EA09894ADA00E7641D /* CMSDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 052C07E609894ADA00E7641D /* CMSDecoder.h */; settings = {ATTRIBUTES = (); }; }; - 052C07EB09894ADA00E7641D /* CMSEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 052C07E709894ADA00E7641D /* CMSEncoder.h */; settings = {ATTRIBUTES = (); }; }; - 052C07EC09894ADA00E7641D /* CMSPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 052C07E809894ADA00E7641D /* CMSPrivate.h */; settings = {ATTRIBUTES = (); }; }; - 052C07ED09894ADA00E7641D /* CMSUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 052C07E909894ADA00E7641D /* CMSUtils.h */; }; - 052C07F709894AF300E7641D /* CMSDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 052C07F409894AF300E7641D /* CMSDecoder.cpp */; }; - 052C07F809894AF300E7641D /* CMSEncoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 052C07F509894AF300E7641D /* CMSEncoder.cpp */; }; - 052C07F909894AF300E7641D /* CMSUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 052C07F609894AF300E7641D /* CMSUtils.cpp */; }; - D43B9E7E1D064F0B00B9DDDA /* cms-trust-settings-test.c in Sources */ = {isa = PBXBuildFile; fileRef = D43B9E7C1D064F0B00B9DDDA /* cms-trust-settings-test.c */; }; - D43B9E7F1D064F0B00B9DDDA /* cms-trust-settings-test.h in Headers */ = {isa = PBXBuildFile; fileRef = D43B9E7D1D064F0B00B9DDDA /* cms-trust-settings-test.h */; }; - D4C334601BE2A2B900D8C1EF /* cms_regressions.h in Headers */ = {isa = PBXBuildFile; fileRef = D4C334571BE29F5200D8C1EF /* cms_regressions.h */; }; - D4C334631BE2A31200D8C1EF /* cms-hashagility-test.c in Sources */ = {isa = PBXBuildFile; fileRef = D4C334611BE2A31200D8C1EF /* cms-hashagility-test.c */; }; - D4C334641BE2A31200D8C1EF /* cms-hashagility-test.h in Headers */ = {isa = PBXBuildFile; fileRef = D4C334621BE2A31200D8C1EF /* cms-hashagility-test.h */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 052C07E609894ADA00E7641D /* CMSDecoder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CMSDecoder.h; sourceTree = ""; }; - 052C07E709894ADA00E7641D /* CMSEncoder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CMSEncoder.h; sourceTree = ""; }; - 052C07E809894ADA00E7641D /* CMSPrivate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CMSPrivate.h; sourceTree = ""; }; - 052C07E909894ADA00E7641D /* CMSUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CMSUtils.h; sourceTree = ""; }; - 052C07F409894AF300E7641D /* CMSDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CMSDecoder.cpp; sourceTree = ""; }; - 052C07F509894AF300E7641D /* CMSEncoder.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CMSEncoder.cpp; sourceTree = ""; }; - 052C07F609894AF300E7641D /* CMSUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CMSUtils.cpp; sourceTree = ""; }; - 18446177146E984400B12992 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; - 18446178146E984400B12992 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; - 18446179146E984400B12992 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; - 1844617A146E984400B12992 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; - 4CA1FEBE052A3C8100F22E42 /* libsecurity_cms.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_cms.a; sourceTree = BUILT_PRODUCTS_DIR; }; - D43B9E7C1D064F0B00B9DDDA /* cms-trust-settings-test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "cms-trust-settings-test.c"; path = "regressions/cms-trust-settings-test.c"; sourceTree = ""; }; - D43B9E7D1D064F0B00B9DDDA /* cms-trust-settings-test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "cms-trust-settings-test.h"; path = "regressions/cms-trust-settings-test.h"; sourceTree = ""; }; - D4C334571BE29F5200D8C1EF /* cms_regressions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = cms_regressions.h; path = regressions/cms_regressions.h; sourceTree = ""; }; - D4C3345C1BE2A2B100D8C1EF /* libsecurity_cms_regressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecurity_cms_regressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; - D4C334611BE2A31200D8C1EF /* cms-hashagility-test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "cms-hashagility-test.c"; path = "regressions/cms-hashagility-test.c"; sourceTree = ""; }; - D4C334621BE2A31200D8C1EF /* cms-hashagility-test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "cms-hashagility-test.h"; path = "regressions/cms-hashagility-test.h"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 4CA1FEBB052A3C8100F22E42 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - D4C334591BE2A2B100D8C1EF /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 18446176146E984400B12992 /* config */ = { - isa = PBXGroup; - children = ( - 18446177146E984400B12992 /* base.xcconfig */, - 18446178146E984400B12992 /* debug.xcconfig */, - 18446179146E984400B12992 /* lib.xcconfig */, - 1844617A146E984400B12992 /* release.xcconfig */, - ); - name = config; - path = ../config; - sourceTree = ""; - }; - 4C308388053237100028A8C6 /* lib */ = { - isa = PBXGroup; - children = ( - 052C07F409894AF300E7641D /* CMSDecoder.cpp */, - 052C07F509894AF300E7641D /* CMSEncoder.cpp */, - 052C07F609894AF300E7641D /* CMSUtils.cpp */, - 052C07E609894ADA00E7641D /* CMSDecoder.h */, - 052C07E709894ADA00E7641D /* CMSEncoder.h */, - 052C07E809894ADA00E7641D /* CMSPrivate.h */, - 052C07E909894ADA00E7641D /* CMSUtils.h */, - ); - path = lib; - sourceTree = ""; - }; - 4CA1FEA7052A3C3800F22E42 = { - isa = PBXGroup; - children = ( - D4C334561BE29F1700D8C1EF /* regressions */, - 4C308388053237100028A8C6 /* lib */, - 18446176146E984400B12992 /* config */, - 4CA1FEBF052A3C8100F22E42 /* Products */, - ); - sourceTree = ""; - }; - 4CA1FEBF052A3C8100F22E42 /* Products */ = { - isa = PBXGroup; - children = ( - 4CA1FEBE052A3C8100F22E42 /* libsecurity_cms.a */, - D4C3345C1BE2A2B100D8C1EF /* libsecurity_cms_regressions.a */, - ); - name = Products; - sourceTree = ""; - }; - D4C334561BE29F1700D8C1EF /* regressions */ = { - isa = PBXGroup; - children = ( - D4C334571BE29F5200D8C1EF /* cms_regressions.h */, - D43B9E7C1D064F0B00B9DDDA /* cms-trust-settings-test.c */, - D43B9E7D1D064F0B00B9DDDA /* cms-trust-settings-test.h */, - D4C334611BE2A31200D8C1EF /* cms-hashagility-test.c */, - D4C334621BE2A31200D8C1EF /* cms-hashagility-test.h */, - ); - name = regressions; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 4CA1FEB9052A3C8100F22E42 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 052C07ED09894ADA00E7641D /* CMSUtils.h in Headers */, - 052C07EC09894ADA00E7641D /* CMSPrivate.h in Headers */, - 052C07EA09894ADA00E7641D /* CMSDecoder.h in Headers */, - 052C07EB09894ADA00E7641D /* CMSEncoder.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - D4C3345A1BE2A2B100D8C1EF /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - D43B9E7F1D064F0B00B9DDDA /* cms-trust-settings-test.h in Headers */, - D4C334641BE2A31200D8C1EF /* cms-hashagility-test.h in Headers */, - D4C334601BE2A2B900D8C1EF /* cms_regressions.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 4CA1FEBD052A3C8100F22E42 /* libsecurity_cms */ = { - isa = PBXNativeTarget; - buildConfigurationList = C263E67509A2971B000043F1 /* Build configuration list for PBXNativeTarget "libsecurity_cms" */; - buildPhases = ( - 4CA1FEB9052A3C8100F22E42 /* Headers */, - 4CA1FEBA052A3C8100F22E42 /* Sources */, - 4CA1FEBB052A3C8100F22E42 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libsecurity_cms; - productName = libsecurity_cms; - productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_cms.a */; - productType = "com.apple.product-type.library.static"; - }; - D4C3345B1BE2A2B100D8C1EF /* libsecurity_cms_regressions */ = { - isa = PBXNativeTarget; - buildConfigurationList = D4C3345D1BE2A2B100D8C1EF /* Build configuration list for PBXNativeTarget "libsecurity_cms_regressions" */; - buildPhases = ( - D4C334581BE2A2B100D8C1EF /* Sources */, - D4C334591BE2A2B100D8C1EF /* Frameworks */, - D4C3345A1BE2A2B100D8C1EF /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = libsecurity_cms_regressions; - productName = libsecurity_cms_regressions; - productReference = D4C3345C1BE2A2B100D8C1EF /* libsecurity_cms_regressions.a */; - productType = "com.apple.product-type.library.static"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 4CA1FEAB052A3C3800F22E42 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0810; - TargetAttributes = { - D4C3345B1BE2A2B100D8C1EF = { - CreatedOnToolsVersion = 7.1; - }; - }; - }; - buildConfigurationList = C263E67909A2971B000043F1 /* Build configuration list for PBXProject "libsecurity_cms" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 1; - knownRegions = ( - en, - ); - mainGroup = 4CA1FEA7052A3C3800F22E42; - productRefGroup = 4CA1FEBF052A3C8100F22E42 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 4CA1FEBD052A3C8100F22E42 /* libsecurity_cms */, - D4C3345B1BE2A2B100D8C1EF /* libsecurity_cms_regressions */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - 4CA1FEBA052A3C8100F22E42 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 052C07F709894AF300E7641D /* CMSDecoder.cpp in Sources */, - 052C07F809894AF300E7641D /* CMSEncoder.cpp in Sources */, - 052C07F909894AF300E7641D /* CMSUtils.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - D4C334581BE2A2B100D8C1EF /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - D4C334631BE2A31200D8C1EF /* cms-hashagility-test.c in Sources */, - D43B9E7E1D064F0B00B9DDDA /* cms-trust-settings-test.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - C263E67609A2971B000043F1 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18446178146E984400B12992 /* debug.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Debug; - }; - C263E67809A2971B000043F1 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1844617A146E984400B12992 /* release.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - }; - name = Release; - }; - C263E67A09A2971B000043F1 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18446179146E984400B12992 /* lib.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPRESSION = lossless; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_TREAT_WARNINGS_AS_ERRORS = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - ONLY_ACTIVE_ARCH = YES; - }; - name = Debug; - }; - C263E67C09A2971B000043F1 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18446179146E984400B12992 /* lib.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_TREAT_WARNINGS_AS_ERRORS = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - }; - name = Release; - }; - D4C3345E1BE2A2B100D8C1EF /* Debug */ = { - 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_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = "-"; - COMBINE_HIDPI_IMAGES = YES; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx.internal; - }; - name = Debug; - }; - D4C3345F1BE2A2B100D8C1EF /* 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; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = "-"; - COMBINE_HIDPI_IMAGES = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx.internal; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - C263E67509A2971B000043F1 /* Build configuration list for PBXNativeTarget "libsecurity_cms" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C263E67609A2971B000043F1 /* Debug */, - C263E67809A2971B000043F1 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C263E67909A2971B000043F1 /* Build configuration list for PBXProject "libsecurity_cms" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C263E67A09A2971B000043F1 /* Debug */, - C263E67C09A2971B000043F1 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - D4C3345D1BE2A2B100D8C1EF /* Build configuration list for PBXNativeTarget "libsecurity_cms_regressions" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - D4C3345E1BE2A2B100D8C1EF /* Debug */, - D4C3345F1BE2A2B100D8C1EF /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; -} diff --git a/OSX/libsecurity_cms/regressions/cms-hashagility-test.c b/OSX/libsecurity_cms/regressions/cms-hashagility-test.c deleted file mode 100644 index 80e9779a7..000000000 --- a/OSX/libsecurity_cms/regressions/cms-hashagility-test.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (c) 2015 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include "cms-hashagility-test.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define TMP_KEYCHAIN_PATH "/tmp/cms_signer.keychain" - -/* encode test */ -static void encode_test(void) -{ - CMSEncoderRef encoder = NULL; - CFDataRef attributeData = NULL, message = NULL, p12Data = NULL; - CFArrayRef imported_items = NULL; - SecIdentityRef identity = NULL; - SecKeychainRef keychain = NULL; - SecExternalFormat sef = kSecFormatPKCS12; - SecItemImportExportKeyParameters keyParams = { - .passphrase = CFSTR("password") - }; - - /* Create encoder */ - ok_status(CMSEncoderCreate(&encoder), "Create CMS encoder"); - ok_status(CMSEncoderSetSignerAlgorithm(encoder, kCMSEncoderDigestAlgorithmSHA256), - "Set digest algorithm to SHA256"); - - /* Load identity and set as signer */ - unlink(TMP_KEYCHAIN_PATH); - ok_status(SecKeychainCreate(TMP_KEYCHAIN_PATH, 8, "password", false, NULL, &keychain), - "Create keychain for identity"); - ok(p12Data = CFDataCreate(NULL, signing_identity_p12, sizeof(signing_identity_p12)), - "Create p12 data"); - ok_status(SecItemImport(p12Data, NULL, &sef, NULL, 0, &keyParams, keychain, &imported_items), - "Import identity"); - is(CFArrayGetCount(imported_items),1,"Imported 1 items"); - is(CFGetTypeID(CFArrayGetValueAtIndex(imported_items, 0)), SecIdentityGetTypeID(), - "Got back an identity"); - ok(identity = (SecIdentityRef) CFRetainSafe(CFArrayGetValueAtIndex(imported_items, 0)), - "Retrieve identity"); - ok_status(CMSEncoderAddSigners(encoder, identity), "Set Signer identity"); - - /* Add signing time attribute for 3 November 2015 */ - ok_status(CMSEncoderAddSignedAttributes(encoder, kCMSAttrSigningTime), - "Set signing time flag"); - ok_status(CMSEncoderSetSigningTime(encoder, 468295000.0), "Set Signing time"); - - /* Add hash agility attribute */ - ok_status(CMSEncoderAddSignedAttributes(encoder, kCMSAttrAppleCodesigningHashAgility), - "Set hash agility flag"); - ok(attributeData = CFDataCreate(NULL, attribute, sizeof(attribute)), - "Create atttribute object"); - ok_status(CMSEncoderSetAppleCodesigningHashAgility(encoder, attributeData), - "Set hash agility data"); - - /* Load content */ - ok_status(CMSEncoderSetHasDetachedContent(encoder, true), "Set detached content"); - ok_status(CMSEncoderUpdateContent(encoder, content, sizeof(content)), "Set content"); - - /* output cms message */ - ok_status(CMSEncoderCopyEncodedContent(encoder, &message), "Finish encoding and output message"); - - /* decode message */ - CMSDecoderRef decoder = NULL; - CFDataRef contentData = NULL; - isnt(message, NULL, "Encoded message exists"); - ok_status(CMSDecoderCreate(&decoder), "Create CMS decoder"); - ok_status(CMSDecoderUpdateMessage(decoder, CFDataGetBytePtr(message), CFDataGetLength(message)), - "Update decoder with CMS message"); - ok(contentData = CFDataCreate(NULL, content, sizeof(content)), "Create detached content"); - ok_status(CMSDecoderSetDetachedContent(decoder, contentData), "Set detached content"); - ok_status(CMSDecoderFinalizeMessage(decoder), "Finalize decoder"); - - /* Cleanup */ - ok_status(SecKeychainDelete(keychain), "Delete temporary keychain"); - - CFReleaseNull(encoder); - CFReleaseNull(keychain); - CFReleaseNull(p12Data); - CFReleaseNull(imported_items); - CFReleaseNull(identity); - CFReleaseNull(attributeData); - CFReleaseNull(message); - CFReleaseNull(decoder); - CFReleaseNull(contentData); -} - -static void decode_positive_test(void) -{ - CMSDecoderRef decoder = NULL; - CFDataRef contentData = NULL, attrValue = NULL; - SecPolicyRef policy = NULL; - SecTrustRef trust = NULL; - CMSSignerStatus signerStatus; - CFAbsoluteTime signingTime = 0.0; - - /* Create decoder and decode */ - ok_status(CMSDecoderCreate(&decoder), "Create CMS decoder"); - ok_status(CMSDecoderUpdateMessage(decoder, valid_message, sizeof(valid_message)), - "Update decoder with CMS message"); - ok(contentData = CFDataCreate(NULL, content, sizeof(content)), "Create detached content"); - ok_status(CMSDecoderSetDetachedContent(decoder, contentData), "Set detached content"); - ok_status(CMSDecoderFinalizeMessage(decoder), "Finalize decoder"); - - /* Get signer status */ - ok(policy = SecPolicyCreateBasicX509(), "Create policy"); - ok_status(CMSDecoderCopySignerStatus(decoder, 0, policy, false, &signerStatus, &trust, NULL), - "Copy Signer status"); - is(signerStatus, kCMSSignerValid, "Valid signature"); - - /* Get Hash Agility Attribute value */ - ok_status(CMSDecoderCopySignerAppleCodesigningHashAgility(decoder, 0, &attrValue), - "Copy hash agility attribute value"); - is(CFDataGetLength(attrValue), sizeof(attribute), "Decoded attribute size"); - is(memcmp(attribute, CFDataGetBytePtr(attrValue), sizeof(attribute)), 0, - "Decoded value same as input value"); - - /* Get Signing Time Attribute value */ - ok_status(CMSDecoderCopySignerSigningTime(decoder, 0, &signingTime), - "Copy signing time attribute value"); - is(signingTime, 468295000.0, "Decoded date same as input date"); - - CFReleaseNull(decoder); - CFReleaseNull(contentData); - CFReleaseNull(policy); - CFReleaseNull(trust); - CFReleaseNull(attrValue); -} - -static void decode_negative_test(void) -{ - CMSDecoderRef decoder = NULL; - CFDataRef contentData = NULL; - SecPolicyRef policy = NULL; - SecTrustRef trust = NULL; - CMSSignerStatus signerStatus; - - /* Create decoder and decode */ - ok_status(CMSDecoderCreate(&decoder), "Create CMS decoder"); - ok_status(CMSDecoderUpdateMessage(decoder, invalid_message, sizeof(invalid_message)), - "Update decoder with CMS message"); - ok(contentData = CFDataCreate(NULL, content, sizeof(content)), "Create detached content"); - ok_status(CMSDecoderSetDetachedContent(decoder, contentData), "Set detached content"); - ok_status(CMSDecoderFinalizeMessage(decoder), "Finalize decoder"); - - /* Get signer status */ - ok(policy = SecPolicyCreateBasicX509(), "Create policy"); - ok_status(CMSDecoderCopySignerStatus(decoder, 0, policy, false, &signerStatus, &trust, NULL), - "Copy Signer status"); - is(signerStatus, kCMSSignerInvalidSignature, "Invalid signature"); - - CFReleaseNull(decoder); - CFReleaseNull(contentData); - CFReleaseNull(policy); - CFReleaseNull(trust); -} - -static void decode_no_attr_test(void) -{ - CMSDecoderRef decoder = NULL; - CFDataRef contentData = NULL, attrValue = NULL; - SecPolicyRef policy = NULL; - SecTrustRef trust = NULL; - CMSSignerStatus signerStatus; - - /* Create decoder and decode */ - ok_status(CMSDecoderCreate(&decoder), "Create CMS decoder"); - ok_status(CMSDecoderUpdateMessage(decoder, valid_no_attr, sizeof(valid_no_attr)), - "Update decoder with CMS message"); - ok(contentData = CFDataCreate(NULL, content, sizeof(content)), "Create detached content"); - ok_status(CMSDecoderSetDetachedContent(decoder, contentData), "Set detached content"); - ok_status(CMSDecoderFinalizeMessage(decoder), "Finalize decoder"); - - /* Get signer status */ - ok(policy = SecPolicyCreateBasicX509(), "Create policy"); - ok_status(CMSDecoderCopySignerStatus(decoder, 0, policy, false, &signerStatus, &trust, NULL), - "Copy Signer status"); - is(signerStatus, kCMSSignerValid, "Valid signature"); - - /* Get Hash Agility Attribute value */ - ok_status(CMSDecoderCopySignerAppleCodesigningHashAgility(decoder, 0, &attrValue), - "Copy empty hash agility attribute value"); - is(attrValue, NULL, "NULL attribute value"); - - CFReleaseNull(decoder); - CFReleaseNull(contentData); - CFReleaseNull(policy); - CFReleaseNull(trust); - CFReleaseNull(attrValue); -} - -int cms_hash_agility_test(int argc, char *const *argv) -{ - plan_tests(24+13+8+10); - - encode_test(); - decode_positive_test(); - decode_negative_test(); - decode_no_attr_test(); - - return 0; -} diff --git a/OSX/libsecurity_cms/regressions/cms-hashagility-test.h b/OSX/libsecurity_cms/regressions/cms-hashagility-test.h deleted file mode 100644 index 27bf5ee3c..000000000 --- a/OSX/libsecurity_cms/regressions/cms-hashagility-test.h +++ /dev/null @@ -1,840 +0,0 @@ -/* - * Copyright (c) 2015 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef cms_hashagility_test_h -#define cms_hashagility_test_h - -#include -#include - -int cms_hash_agility_test(int argc, char *const *argv); - -/* - * password: "password" - * localKeyID: 01 AE 1A 61 75 AE 23 D9 11 5C 28 93 A9 E2 49 5E 74 28 4C 08 - * subject=/C=US/ST=California/L=Cupertino/O=Apple, Inc./OU=Security Engineering and Architecture/CN=CMS Test Signer - * issuer=/C=US/ST=California/L=Cupertino/O=Apple, Inc./OU=Security Engineering and Architecture/CN=CMS Test Signer - */ -unsigned char signing_identity_p12[4477] = { - 0x30, 0x82, 0x11, 0x79, 0x02, 0x01, 0x03, 0x30, 0x82, 0x11, 0x3f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x07, 0x01, 0xa0, 0x82, 0x11, 0x30, 0x04, 0x82, 0x11, 0x2c, 0x30, 0x82, 0x11, 0x28, 0x30, 0x82, 0x07, 0x57, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x06, 0xa0, 0x82, 0x07, 0x48, 0x30, 0x82, 0x07, 0x44, 0x02, 0x01, 0x00, - 0x30, 0x82, 0x07, 0x3d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x1c, 0x06, 0x0a, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x06, 0x30, 0x0e, 0x04, 0x08, 0xed, 0xd8, 0x65, 0x57, 0xbb, 0xca, 0x25, - 0x46, 0x02, 0x02, 0x08, 0x00, 0x80, 0x82, 0x07, 0x10, 0xc0, 0x1d, 0x0d, 0x5c, 0x7f, 0x3b, 0xbe, 0x20, 0xd4, 0x9a, 0x0d, - 0xaf, 0xb6, 0x4b, 0xc7, 0x7f, 0xa8, 0xa8, 0x3f, 0x6c, 0x96, 0x1c, 0xea, 0x90, 0xd2, 0x79, 0x9f, 0x56, 0x3a, 0x5a, 0x29, - 0x93, 0xff, 0x72, 0x39, 0x9e, 0x41, 0xd9, 0x5a, 0xfc, 0xb5, 0x54, 0x2d, 0x89, 0x60, 0x18, 0xf2, 0xea, 0x8c, 0xeb, 0x7f, - 0xba, 0x87, 0xc6, 0x70, 0x42, 0x25, 0x55, 0x24, 0xc5, 0x4f, 0x26, 0x66, 0x8d, 0x78, 0x44, 0x47, 0x85, 0x36, 0x53, 0x86, - 0xc9, 0x18, 0x83, 0x33, 0x4b, 0x4b, 0x08, 0x2d, 0x7b, 0x68, 0x37, 0x29, 0x4c, 0x20, 0x74, 0xd4, 0x4f, 0xbb, 0x6e, 0x97, - 0x7a, 0xf4, 0xbf, 0xcb, 0x40, 0x26, 0x2d, 0xac, 0x95, 0x82, 0xe0, 0x88, 0xfe, 0x54, 0x80, 0xe9, 0xf5, 0xda, 0x8e, 0x6e, - 0x3a, 0x47, 0x2d, 0xc8, 0xd4, 0xe7, 0x2e, 0xff, 0xec, 0xfa, 0xa5, 0x70, 0xcd, 0x2e, 0x99, 0x26, 0x32, 0xc8, 0x1d, 0x53, - 0x60, 0x1e, 0x6f, 0x68, 0xcb, 0x49, 0xd0, 0xa2, 0xf8, 0x47, 0x70, 0x1b, 0x9e, 0x85, 0xbe, 0x4e, 0x56, 0xb5, 0x8b, 0x66, - 0x45, 0x57, 0xe3, 0xbd, 0x57, 0xed, 0x94, 0x53, 0xf6, 0x72, 0xd7, 0xb7, 0xc6, 0x9f, 0x05, 0xf5, 0x98, 0xb4, 0x13, 0x35, - 0x69, 0x24, 0x94, 0xd9, 0x3d, 0x80, 0xbc, 0xa8, 0xea, 0x78, 0x0c, 0xe0, 0xa2, 0xfe, 0x1b, 0xd2, 0x82, 0x3d, 0x83, 0x34, - 0x76, 0xb4, 0x45, 0xf8, 0x14, 0x09, 0x66, 0x02, 0x68, 0xc3, 0x1b, 0xcb, 0x6c, 0x91, 0x6b, 0x3e, 0xdc, 0x35, 0x68, 0xab, - 0x49, 0x47, 0x6c, 0x60, 0xea, 0xe3, 0xd5, 0x59, 0x82, 0x9c, 0x18, 0xb0, 0x6d, 0x45, 0xc0, 0x2f, 0x58, 0xf1, 0x44, 0x79, - 0xe3, 0xd2, 0xd6, 0x16, 0xbc, 0xde, 0x17, 0xae, 0xf7, 0xea, 0x3c, 0xe4, 0xb4, 0x7b, 0xdf, 0xba, 0x9b, 0xf1, 0xb8, 0xa8, - 0xb0, 0x51, 0xeb, 0xe8, 0xc3, 0xe9, 0x9c, 0x1b, 0x06, 0xdd, 0x89, 0x07, 0x98, 0xf8, 0x01, 0x7f, 0xde, 0x7e, 0x05, 0xa6, - 0x72, 0x0b, 0x3f, 0xf4, 0x7d, 0xca, 0x74, 0x7b, 0xc9, 0x87, 0x0d, 0x35, 0x8b, 0x05, 0x3a, 0x73, 0x04, 0x08, 0x7a, 0x51, - 0x34, 0x29, 0x5b, 0xd8, 0x90, 0x0f, 0xa7, 0xf0, 0x48, 0xfc, 0x9c, 0x74, 0xca, 0xe9, 0x34, 0x75, 0x1c, 0xd1, 0xa6, 0xd1, - 0xfb, 0x9f, 0xc7, 0x82, 0x40, 0x75, 0x87, 0xdd, 0xa2, 0x22, 0xeb, 0x91, 0xd7, 0x85, 0x1a, 0x2c, 0xa7, 0x3d, 0xd5, 0xe4, - 0xca, 0x85, 0x00, 0x33, 0x11, 0x6d, 0x62, 0xa8, 0xb7, 0xd3, 0x45, 0x46, 0xdc, 0xb4, 0xa3, 0xeb, 0xae, 0x5e, 0x8c, 0xc2, - 0x7a, 0x0b, 0x83, 0x98, 0x5a, 0x94, 0x0f, 0x68, 0x61, 0x36, 0x57, 0x6e, 0x94, 0xe0, 0x6d, 0x93, 0x76, 0xa0, 0x5d, 0x3f, - 0x25, 0x8b, 0x3b, 0x46, 0x1e, 0x0c, 0x15, 0x6b, 0x9f, 0x1d, 0xc3, 0x5f, 0x61, 0x42, 0xd5, 0xf8, 0x79, 0xcd, 0xd1, 0x0a, - 0x96, 0xce, 0x49, 0x8a, 0xff, 0x54, 0x46, 0x77, 0x65, 0x37, 0x70, 0xcd, 0x65, 0x6f, 0x3d, 0x49, 0xc1, 0x29, 0x8d, 0x16, - 0xbd, 0x36, 0x47, 0x54, 0xa5, 0x4d, 0x06, 0xfb, 0x33, 0x00, 0x29, 0xd8, 0x31, 0x09, 0x58, 0x12, 0x4c, 0xfe, 0xef, 0x8e, - 0xf9, 0x1e, 0x30, 0xf7, 0x05, 0xb2, 0xd8, 0xd4, 0x7d, 0xae, 0xab, 0x57, 0xb7, 0x46, 0x09, 0xff, 0xca, 0xc7, 0x7b, 0xca, - 0x73, 0xfa, 0xf9, 0x50, 0xa0, 0xb8, 0x09, 0xc2, 0x80, 0x43, 0x0d, 0x99, 0x7f, 0x4e, 0xdf, 0xd5, 0x6c, 0xc4, 0x42, 0x1a, - 0x05, 0xbd, 0x65, 0xf4, 0x57, 0x2a, 0xe5, 0xc4, 0xcb, 0x79, 0x3f, 0x8f, 0x74, 0x93, 0x66, 0x8d, 0x93, 0xda, 0xba, 0x23, - 0x77, 0x3f, 0xad, 0xd3, 0x8b, 0xae, 0xf5, 0xf1, 0x5c, 0xc1, 0xd2, 0x00, 0x3a, 0x60, 0x8e, 0xc3, 0x32, 0xd6, 0x8e, 0xce, - 0x95, 0x24, 0x03, 0x79, 0x03, 0xf2, 0xb8, 0x2a, 0x94, 0xeb, 0x15, 0x97, 0xdc, 0x18, 0x8d, 0xc7, 0xd9, 0xc2, 0x63, 0x69, - 0xfb, 0xf9, 0x8f, 0x05, 0xd3, 0x7c, 0x60, 0x5a, 0x57, 0xe4, 0xa5, 0xc1, 0xdf, 0x1d, 0x11, 0x84, 0x69, 0xba, 0x20, 0xd8, - 0x79, 0xc3, 0x34, 0x3a, 0xb1, 0x63, 0x4c, 0xd2, 0x91, 0x2d, 0x87, 0x1e, 0xec, 0x06, 0xea, 0x35, 0x97, 0x0e, 0x59, 0x54, - 0x83, 0x50, 0x3e, 0xac, 0xf2, 0xea, 0x6c, 0x0c, 0xa0, 0x57, 0xfb, 0xe8, 0x6b, 0xf9, 0xd1, 0x25, 0xc0, 0xa2, 0xb0, 0xa2, - 0xcd, 0xde, 0x2b, 0xa7, 0xb3, 0x40, 0x75, 0x36, 0xf7, 0x20, 0xbe, 0xd7, 0xd1, 0x2e, 0x66, 0xc5, 0x3c, 0xf8, 0x6e, 0xce, - 0xcb, 0x76, 0x7f, 0x1d, 0x32, 0x3b, 0x14, 0x27, 0x9c, 0x9e, 0xa3, 0xeb, 0x0c, 0x2f, 0x71, 0xba, 0x0d, 0xca, 0x27, 0x90, - 0x42, 0xfd, 0xd4, 0x34, 0xb9, 0x96, 0xae, 0xcb, 0xd8, 0xfe, 0x31, 0x62, 0xe8, 0x4c, 0x07, 0x71, 0xb9, 0x0c, 0x9f, 0xe2, - 0x8e, 0x66, 0xc2, 0x39, 0xc5, 0xc3, 0x1c, 0xfd, 0x5e, 0x18, 0x0b, 0xd4, 0x93, 0x3d, 0x98, 0x33, 0xaf, 0x6d, 0xb4, 0x6f, - 0xe6, 0x75, 0x67, 0x62, 0xe7, 0x42, 0xee, 0xc6, 0xf2, 0x2e, 0x21, 0xa9, 0x75, 0xde, 0x0a, 0x8c, 0x39, 0xb7, 0x4b, 0x54, - 0x01, 0xa7, 0xeb, 0x5a, 0x88, 0x79, 0xa8, 0xb3, 0x3f, 0x31, 0x8c, 0x47, 0x08, 0x94, 0x47, 0x52, 0xcf, 0x3c, 0xac, 0xd9, - 0x32, 0x57, 0x4a, 0x18, 0x55, 0x5b, 0x66, 0xdc, 0x89, 0xd2, 0xc6, 0xa1, 0x11, 0x40, 0x19, 0x9c, 0x46, 0x88, 0x21, 0x77, - 0xc1, 0x7f, 0x09, 0xc7, 0xfb, 0x52, 0x92, 0xec, 0x1a, 0xe0, 0xdd, 0x76, 0xb9, 0xfd, 0xa7, 0x8f, 0x61, 0xe3, 0xf0, 0x1b, - 0x4e, 0xdb, 0xa0, 0xde, 0x90, 0xd6, 0x49, 0xea, 0xe9, 0x86, 0xc6, 0x5d, 0xac, 0xd0, 0xc2, 0xc5, 0x01, 0xcb, 0x3f, 0xcb, - 0xf0, 0x62, 0x90, 0xa1, 0x17, 0x4b, 0x72, 0x5c, 0xc8, 0xe9, 0x24, 0x93, 0xda, 0x5c, 0x75, 0x24, 0x96, 0x35, 0x54, 0xf4, - 0xfa, 0xc8, 0x27, 0xe1, 0xdd, 0x32, 0xda, 0x2f, 0x2b, 0x7d, 0xf6, 0xd8, 0x0b, 0xf2, 0xca, 0xb5, 0xee, 0x8a, 0xcf, 0xb6, - 0x26, 0x71, 0x65, 0x85, 0xfe, 0x8c, 0x37, 0xf1, 0x17, 0x6b, 0x5e, 0x8a, 0xee, 0xb4, 0xc7, 0x0a, 0xff, 0xb2, 0x9a, 0x72, - 0xe5, 0x85, 0xf3, 0xc0, 0xf9, 0x84, 0xbc, 0xe0, 0x18, 0x3c, 0x12, 0x0c, 0xa1, 0xe9, 0x10, 0xd4, 0x3b, 0x1a, 0x21, 0x35, - 0xc6, 0x06, 0x93, 0xa0, 0xdf, 0x0d, 0x68, 0xa3, 0xf1, 0x06, 0xd9, 0xed, 0xb7, 0xa7, 0xba, 0xb0, 0x22, 0xc2, 0x0b, 0x6b, - 0x70, 0x50, 0xf5, 0x49, 0x9a, 0x4f, 0x99, 0xaa, 0x1e, 0x9c, 0xa6, 0xf3, 0x99, 0x3a, 0xfd, 0x3b, 0xd2, 0xeb, 0xce, 0x1e, - 0x72, 0x62, 0x99, 0xc0, 0x1e, 0x2b, 0x09, 0x75, 0x4a, 0xfb, 0xc8, 0x26, 0xcf, 0x76, 0xa2, 0x0e, 0xef, 0xf4, 0xa8, 0x70, - 0x31, 0xd8, 0xa1, 0x22, 0x62, 0xcc, 0x9f, 0xd5, 0xa3, 0x55, 0xc2, 0x78, 0xd7, 0x27, 0xfc, 0x3c, 0x53, 0xe8, 0xeb, 0x7e, - 0x7a, 0x27, 0xcf, 0x6d, 0x52, 0xb5, 0x9a, 0x2b, 0x49, 0x8d, 0x3f, 0x89, 0x80, 0x1a, 0x5c, 0x39, 0xe7, 0x53, 0xb3, 0xf3, - 0x33, 0x97, 0xcf, 0x7d, 0xfb, 0x8e, 0x19, 0xf4, 0x72, 0xeb, 0xe7, 0xdf, 0xb1, 0xe3, 0xc1, 0x6c, 0x7f, 0x17, 0x89, 0x34, - 0x4f, 0x45, 0x0f, 0xc5, 0xfc, 0x15, 0xb3, 0x3f, 0xc6, 0xdc, 0x25, 0xa6, 0xda, 0x28, 0x85, 0x5d, 0x25, 0x02, 0x78, 0x74, - 0xd9, 0x74, 0xb8, 0x65, 0x48, 0x3a, 0x8a, 0x2a, 0xd5, 0xa9, 0xb8, 0x7f, 0xaa, 0x9d, 0xe7, 0xaf, 0xbd, 0xdf, 0xfd, 0x00, - 0x67, 0xab, 0x39, 0xe1, 0x2c, 0x3d, 0xd1, 0x5c, 0x9b, 0x61, 0x2b, 0x51, 0xdc, 0x87, 0x19, 0x6c, 0xa0, 0x12, 0xd4, 0x60, - 0xed, 0x94, 0xe9, 0xeb, 0x4e, 0x51, 0xd8, 0x50, 0xcb, 0x97, 0x8a, 0x20, 0x21, 0xdf, 0xe9, 0x2c, 0xd2, 0xe2, 0x04, 0x14, - 0xaf, 0x7b, 0x7e, 0xd6, 0xeb, 0x1d, 0x25, 0x09, 0x98, 0x8e, 0x9e, 0x56, 0xf8, 0x7d, 0xfc, 0x0f, 0xbf, 0xd2, 0x6b, 0xbc, - 0xab, 0xed, 0xca, 0x43, 0x6d, 0x28, 0xbe, 0xd5, 0x20, 0x44, 0xcb, 0x6b, 0xbc, 0x80, 0x5a, 0x82, 0x13, 0x50, 0xbd, 0xda, - 0x18, 0x10, 0xac, 0xae, 0x56, 0xb9, 0x46, 0xc5, 0xa2, 0xca, 0xb2, 0x03, 0xf0, 0x57, 0xfe, 0xcd, 0x9a, 0x1b, 0x81, 0x6a, - 0x10, 0x51, 0x2e, 0x88, 0x30, 0x57, 0x3c, 0xfe, 0x7c, 0x56, 0x0c, 0x00, 0x89, 0x5c, 0x21, 0x57, 0x19, 0x96, 0x85, 0x98, - 0xeb, 0x43, 0x71, 0x0d, 0x8a, 0x35, 0xc3, 0xae, 0x36, 0x59, 0x72, 0x97, 0x12, 0x6d, 0xcd, 0x28, 0x64, 0x17, 0x9e, 0xe7, - 0x2c, 0x28, 0xfd, 0x32, 0xa8, 0x10, 0x67, 0x4e, 0xc0, 0x14, 0x21, 0x7c, 0x36, 0x20, 0xe9, 0x46, 0x68, 0x62, 0xc1, 0xff, - 0xb0, 0xdf, 0xaa, 0x87, 0xff, 0x94, 0xa4, 0xf3, 0xb3, 0xc8, 0x53, 0x57, 0x18, 0x92, 0x15, 0xc7, 0x78, 0x2d, 0x91, 0xba, - 0xb3, 0x1f, 0x06, 0x13, 0x79, 0x21, 0x86, 0x1d, 0xa2, 0x38, 0x2c, 0xda, 0x35, 0x31, 0xbb, 0x04, 0x65, 0xa3, 0x01, 0xa6, - 0x63, 0xa4, 0x4a, 0xa2, 0xc1, 0xad, 0x04, 0xc1, 0xfa, 0x78, 0xe1, 0xb6, 0x50, 0x46, 0xab, 0xad, 0x1c, 0xcf, 0xf4, 0xe5, - 0xba, 0xa5, 0xe2, 0x91, 0x29, 0x4b, 0xa1, 0xc6, 0x4b, 0x30, 0xa5, 0x31, 0x02, 0xe9, 0xd0, 0x50, 0x72, 0x2c, 0x8e, 0xbd, - 0xb2, 0x12, 0xd9, 0x4f, 0x7c, 0x87, 0x4b, 0xa0, 0x45, 0x71, 0x0c, 0x23, 0x37, 0x6b, 0x60, 0xd7, 0x9f, 0x19, 0xe8, 0x0b, - 0x85, 0x57, 0x72, 0xb6, 0xbb, 0x20, 0x23, 0xd3, 0x7d, 0x9a, 0x9b, 0x9a, 0x05, 0x46, 0x5c, 0xf5, 0x02, 0xf1, 0x56, 0x00, - 0xc2, 0x05, 0x85, 0x48, 0xd3, 0x8d, 0x8e, 0xe1, 0xcb, 0xc5, 0x83, 0x1f, 0x78, 0xd0, 0xc5, 0xb1, 0xdf, 0x80, 0x9d, 0x04, - 0xe7, 0xac, 0xd1, 0x68, 0x1a, 0x19, 0x18, 0x16, 0xfa, 0x3a, 0xe2, 0xd2, 0x30, 0x08, 0x17, 0x4d, 0x50, 0x2b, 0xd4, 0xa3, - 0xbe, 0x98, 0x5f, 0xe0, 0xcf, 0xed, 0x7d, 0x74, 0x94, 0xd1, 0xb2, 0x77, 0xbc, 0x72, 0xbc, 0xf5, 0xc7, 0x82, 0x26, 0x53, - 0x14, 0xcc, 0xf9, 0xf7, 0x71, 0xea, 0x97, 0xaa, 0xbf, 0x21, 0x46, 0x59, 0x2c, 0x9a, 0xc4, 0xeb, 0xa3, 0x4a, 0x97, 0x91, - 0x11, 0xf1, 0x01, 0x19, 0x7e, 0xb1, 0xb2, 0x63, 0x0d, 0xf0, 0x5d, 0xaf, 0x53, 0xdf, 0x4d, 0xa1, 0x90, 0xe5, 0x12, 0x82, - 0x33, 0x6f, 0x1d, 0x73, 0xdf, 0xdb, 0x1f, 0x18, 0xa0, 0x72, 0xc1, 0xd6, 0xa7, 0x4d, 0xb2, 0x3e, 0x24, 0xb7, 0xa7, 0x76, - 0x15, 0x46, 0x22, 0x48, 0x49, 0x55, 0xd1, 0xfb, 0x66, 0x32, 0x02, 0xa9, 0xfc, 0xbe, 0x7e, 0x16, 0xcf, 0xac, 0x32, 0xbc, - 0xdb, 0xd5, 0xd8, 0xa3, 0x23, 0x6a, 0x10, 0xa6, 0x37, 0x03, 0xf6, 0x2a, 0xde, 0xba, 0xde, 0x2d, 0x7d, 0xef, 0x1d, 0xb9, - 0xf3, 0x93, 0xd4, 0xf2, 0x13, 0xf4, 0x9c, 0x5a, 0x32, 0xba, 0x5f, 0xef, 0x7b, 0xd0, 0x6b, 0xd7, 0x91, 0x6d, 0x7b, 0xe1, - 0x4d, 0xf2, 0x8c, 0xe7, 0xf1, 0x66, 0xb9, 0xad, 0xc6, 0x30, 0x08, 0x9e, 0x51, 0xd4, 0x39, 0x87, 0x09, 0xfa, 0x6b, 0x7a, - 0xa7, 0x5f, 0x1a, 0x9c, 0x98, 0xc5, 0x76, 0xb0, 0x71, 0x76, 0xf5, 0xfc, 0x56, 0x88, 0x1c, 0xca, 0xee, 0x76, 0xd4, 0x2c, - 0xa6, 0x64, 0x80, 0x59, 0x12, 0x8c, 0x08, 0xce, 0x83, 0xb3, 0xd9, 0x68, 0x59, 0xc1, 0x26, 0x86, 0xa7, 0x80, 0x10, 0xbc, - 0x41, 0x28, 0x6c, 0x45, 0xd4, 0x6d, 0x15, 0xd0, 0x76, 0x44, 0x0e, 0xcf, 0xc1, 0xde, 0xef, 0x7a, 0x97, 0x36, 0x8f, 0x0d, - 0x8a, 0xf5, 0x45, 0xde, 0xae, 0x61, 0xd0, 0x55, 0xe9, 0x8d, 0x62, 0xfd, 0xa3, 0x0d, 0x44, 0x0f, 0x49, 0xb6, 0x5a, 0xa4, - 0xaa, 0x03, 0x4e, 0x60, 0x35, 0x53, 0x86, 0x9e, 0xec, 0x75, 0xd9, 0x0a, 0xca, 0x14, 0xe3, 0x1b, 0x06, 0x05, 0xd6, 0x8f, - 0x4f, 0x11, 0xb3, 0x13, 0xdd, 0x26, 0x35, 0xbd, 0x56, 0x55, 0xf1, 0x43, 0x89, 0x5e, 0x5b, 0x25, 0x4d, 0xa8, 0x09, 0xdd, - 0xf2, 0x6d, 0x9e, 0x8c, 0xcd, 0xa2, 0xde, 0x84, 0x00, 0x6a, 0x0a, 0xc6, 0x92, 0x30, 0x82, 0xcf, 0xa4, 0x31, 0x67, 0xbd, - 0xd4, 0x36, 0x6a, 0x8b, 0xc6, 0x33, 0xdf, 0x8b, 0xde, 0x33, 0x01, 0x7b, 0x9d, 0xbf, 0xe9, 0x12, 0x35, 0x8a, 0x97, 0x07, - 0x72, 0x0b, 0x6b, 0x60, 0xe6, 0x1e, 0x7d, 0x78, 0x22, 0x9f, 0xbf, 0x66, 0x8e, 0x02, 0xf4, 0xdc, 0xa1, 0xb0, 0x42, 0x73, - 0x86, 0xca, 0x34, 0xf0, 0xa7, 0x2e, 0x15, 0x84, 0xa4, 0x60, 0xa8, 0x47, 0x05, 0x80, 0x03, 0x27, 0xa8, 0x04, 0x03, 0xfe, - 0x47, 0xd4, 0xeb, 0x33, 0x27, 0xbf, 0x89, 0xff, 0x4c, 0xd9, 0x27, 0x0e, 0xd0, 0xa9, 0x41, 0x8b, 0xd5, 0x7c, 0xc4, 0x14, - 0x7a, 0x9c, 0xb3, 0xaa, 0x13, 0x32, 0xa4, 0x67, 0xd5, 0x95, 0xdc, 0x4a, 0x3d, 0xf2, 0x54, 0xd7, 0x02, 0xf8, 0x06, 0x7b, - 0x1d, 0x9a, 0xa4, 0x53, 0xa0, 0x9c, 0x76, 0x7d, 0xf4, 0x01, 0xa3, 0x4b, 0xb2, 0x8b, 0x44, 0x85, 0xf6, 0x80, 0x99, 0x2f, - 0x77, 0x08, 0x20, 0xea, 0x08, 0xf8, 0x14, 0x76, 0xfe, 0xa0, 0x5a, 0xf9, 0x1f, 0x87, 0x03, 0xff, 0x8d, 0x1f, 0x5d, 0x02, - 0x64, 0x8a, 0xf4, 0xa5, 0x8c, 0xb7, 0x0a, 0x34, 0x68, 0xaa, 0xca, 0xc8, 0xe1, 0x78, 0x9b, 0xd3, 0x6c, 0x5c, 0x07, 0x99, - 0xc1, 0x10, 0x3f, 0x77, 0x0c, 0x45, 0xa2, 0xda, 0xda, 0xab, 0x7c, 0xf0, 0x90, 0x12, 0xa2, 0x7c, 0x84, 0x30, 0x82, 0x09, - 0xc9, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x09, 0xba, 0x04, 0x82, 0x09, 0xb6, - 0x30, 0x82, 0x09, 0xb2, 0x30, 0x82, 0x09, 0xae, 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, - 0x02, 0xa0, 0x82, 0x09, 0x76, 0x30, 0x82, 0x09, 0x72, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x0c, 0x01, 0x03, 0x30, 0x0e, 0x04, 0x08, 0xd3, 0x5d, 0xa8, 0x14, 0xbc, 0x7a, 0xaa, 0x5f, 0x02, 0x02, 0x08, 0x00, 0x04, - 0x82, 0x09, 0x50, 0xaf, 0xe9, 0x63, 0xb6, 0x05, 0x8b, 0x48, 0xe1, 0x11, 0xd0, 0x37, 0x1d, 0x48, 0x71, 0x22, 0x70, 0xdc, - 0xbd, 0xca, 0x98, 0x5d, 0x72, 0xca, 0x38, 0xdc, 0x2e, 0x4f, 0xd4, 0x71, 0xd3, 0xac, 0xf3, 0x0c, 0xcf, 0x78, 0x4e, 0x5c, - 0x63, 0x35, 0xaa, 0xac, 0x5a, 0xf0, 0xef, 0x6c, 0xc0, 0x89, 0x28, 0xc4, 0x64, 0xec, 0x5c, 0x92, 0x72, 0xbc, 0xe5, 0x30, - 0xe9, 0x5c, 0x35, 0xff, 0xe0, 0xb1, 0x1f, 0xc6, 0x37, 0x50, 0xb7, 0x3d, 0x94, 0x28, 0xbd, 0x3b, 0xf0, 0xd9, 0x5c, 0xb1, - 0x45, 0x93, 0xde, 0x41, 0x5b, 0x12, 0xba, 0xfa, 0x27, 0x49, 0x6b, 0xb7, 0x9a, 0xa6, 0x46, 0x8e, 0xe3, 0x15, 0x1b, 0x7f, - 0x2c, 0x91, 0x2e, 0x33, 0xf3, 0xef, 0x7a, 0x9b, 0x9d, 0xa8, 0x82, 0x95, 0xa0, 0x7e, 0x43, 0xd6, 0x9d, 0xe2, 0xfb, 0xb1, - 0xb0, 0xcf, 0xbd, 0xb6, 0x9b, 0x55, 0x4c, 0xc8, 0x4a, 0xc7, 0x82, 0xeb, 0x3d, 0x09, 0x8d, 0x85, 0x6f, 0x8c, 0x42, 0x6d, - 0x10, 0x7d, 0x77, 0x57, 0x29, 0x00, 0xe2, 0xd8, 0x2f, 0xed, 0x7c, 0x10, 0x5b, 0x03, 0xfa, 0x60, 0x34, 0xc9, 0x63, 0x25, - 0x4d, 0x02, 0x77, 0x8f, 0x7f, 0x4b, 0x53, 0xe4, 0x8d, 0x1e, 0x4e, 0x2c, 0x0c, 0x7f, 0x0e, 0x48, 0x4b, 0xcd, 0xc8, 0x6a, - 0xfa, 0xd3, 0x9f, 0x6f, 0x20, 0x4e, 0x2c, 0x77, 0x2a, 0x84, 0x5e, 0x6c, 0xc3, 0x57, 0xba, 0x97, 0xa7, 0xa8, 0xcb, 0x6f, - 0x22, 0xc1, 0xa7, 0x61, 0xf7, 0x7e, 0x7a, 0xae, 0xda, 0xbd, 0x3a, 0xea, 0xb3, 0x46, 0x54, 0x8d, 0x46, 0x48, 0x1f, 0xf3, - 0x5c, 0xaa, 0x2e, 0x44, 0xe1, 0x83, 0x69, 0x45, 0x30, 0x02, 0x49, 0x63, 0xa6, 0xdd, 0xf0, 0x25, 0xce, 0x81, 0xab, 0x66, - 0x20, 0x04, 0x12, 0x2f, 0x94, 0x2f, 0x8f, 0xf9, 0x88, 0xea, 0x5b, 0xba, 0x87, 0xd7, 0xbe, 0x63, 0x2e, 0xb4, 0xa4, 0x15, - 0xe8, 0x56, 0x9e, 0xb5, 0x7b, 0x27, 0xf8, 0x06, 0xfd, 0xf5, 0x21, 0x93, 0x2b, 0x64, 0xb0, 0xe2, 0x31, 0xb3, 0x19, 0xe0, - 0x6b, 0x10, 0x8c, 0xa5, 0xa5, 0x38, 0x27, 0x78, 0xc9, 0x9c, 0x01, 0xa7, 0x42, 0x22, 0x3d, 0xf8, 0x8c, 0x23, 0x46, 0xc5, - 0x4e, 0x47, 0xa5, 0x9e, 0xd7, 0xa5, 0x50, 0x24, 0x02, 0x30, 0xe9, 0x15, 0x3e, 0x17, 0xba, 0x2c, 0xf2, 0x5e, 0xc7, 0x01, - 0x25, 0x9a, 0x74, 0x73, 0x5c, 0x5e, 0xca, 0x01, 0xe2, 0x58, 0x96, 0x47, 0x3e, 0x4c, 0xb9, 0x0f, 0x95, 0xbf, 0xf3, 0xc4, - 0x24, 0x98, 0x6c, 0xc5, 0x40, 0xd2, 0xf3, 0x88, 0x62, 0xb0, 0x25, 0x54, 0xb5, 0xf6, 0x2b, 0xfd, 0xf5, 0x6a, 0x6d, 0x15, - 0xb2, 0x18, 0x7d, 0xef, 0x3e, 0x66, 0x7d, 0x38, 0x4c, 0xda, 0xc9, 0x1a, 0xcd, 0x40, 0x2a, 0xc6, 0x7b, 0x2e, 0x8a, 0x15, - 0xa7, 0xae, 0x99, 0xf5, 0x93, 0x39, 0x20, 0xd2, 0xd8, 0xfd, 0x1f, 0x87, 0x2e, 0xa0, 0xcd, 0x95, 0xa2, 0xd7, 0xd0, 0x48, - 0xf7, 0x6e, 0x81, 0x91, 0x1c, 0x37, 0x8a, 0x28, 0x6f, 0x22, 0x7b, 0x37, 0x69, 0x30, 0x3a, 0x64, 0x6e, 0x4a, 0x5f, 0x0a, - 0xa6, 0xd7, 0x53, 0xce, 0x1d, 0x60, 0x88, 0xa5, 0x0b, 0xde, 0xf5, 0x01, 0x3a, 0x20, 0xfa, 0xd6, 0x08, 0xdf, 0x83, 0x39, - 0x2e, 0xb8, 0x3a, 0x91, 0xec, 0x39, 0x47, 0xaa, 0x66, 0x8a, 0xb4, 0x35, 0x70, 0xaf, 0x88, 0x24, 0xb2, 0xc3, 0xdc, 0x7c, - 0xd0, 0x8f, 0x93, 0x0d, 0xa4, 0x53, 0xf1, 0x55, 0x92, 0xae, 0xd9, 0xeb, 0x31, 0xa0, 0x68, 0x29, 0xf5, 0xdb, 0x2f, 0xd1, - 0xa3, 0xfe, 0x34, 0x2f, 0xcd, 0x64, 0x0c, 0x11, 0x13, 0x14, 0x50, 0xeb, 0x27, 0x56, 0xda, 0xc0, 0x30, 0x3a, 0x8c, 0x92, - 0xb3, 0xb8, 0xc8, 0xb7, 0x19, 0xea, 0x4c, 0x74, 0xb9, 0x95, 0x46, 0x9f, 0xc0, 0x63, 0xfd, 0x72, 0x35, 0x0b, 0xb9, 0x1d, - 0x1e, 0x85, 0xf8, 0xf9, 0x23, 0xf7, 0x42, 0xe2, 0xf4, 0x67, 0xbf, 0x3d, 0x30, 0x4b, 0x6a, 0xf2, 0x44, 0x2f, 0xcb, 0x6f, - 0xe9, 0x73, 0x4b, 0x8f, 0x09, 0x29, 0x69, 0xcd, 0x8d, 0xcd, 0xc7, 0xd4, 0xa2, 0x0c, 0x6a, 0xc4, 0x9a, 0x33, 0xe2, 0x64, - 0x5f, 0x07, 0xf2, 0xb6, 0xf8, 0x86, 0x7f, 0x05, 0x04, 0xf1, 0x1d, 0x9d, 0xd1, 0xc8, 0x3c, 0x16, 0x6e, 0x18, 0x96, 0x15, - 0x33, 0xda, 0x84, 0xb6, 0xfd, 0x13, 0x29, 0x2f, 0x5e, 0xa0, 0x0e, 0xaa, 0xf6, 0x24, 0xb4, 0xa5, 0x48, 0x01, 0x02, 0x07, - 0x31, 0x98, 0x0d, 0x9c, 0x65, 0x59, 0x68, 0x61, 0x22, 0xdb, 0x64, 0x16, 0x05, 0xae, 0xd8, 0x64, 0x5f, 0xba, 0x51, 0xab, - 0x5e, 0xe0, 0xbe, 0x3d, 0x29, 0x67, 0x20, 0x94, 0x63, 0xfe, 0xc7, 0x90, 0x30, 0xc9, 0x43, 0xf1, 0xce, 0x9c, 0x53, 0x01, - 0x2c, 0x64, 0x56, 0x85, 0xb7, 0x3b, 0xa4, 0x05, 0x5d, 0x88, 0xdf, 0x44, 0xda, 0x18, 0xf3, 0x8c, 0xdb, 0xae, 0xd2, 0x9f, - 0xee, 0x4e, 0x08, 0x17, 0xf9, 0xd8, 0xe0, 0xc9, 0x7d, 0xa5, 0xad, 0x79, 0x06, 0x1b, 0x8c, 0x92, 0xe7, 0x53, 0xdf, 0xde, - 0xa3, 0xa5, 0x84, 0x1d, 0xd8, 0x75, 0x35, 0x78, 0x32, 0x55, 0x6f, 0x4f, 0x29, 0x34, 0x4e, 0x6f, 0x32, 0x16, 0xe4, 0xfd, - 0xbc, 0xf5, 0x76, 0x99, 0xf3, 0x48, 0x5b, 0xa0, 0x65, 0xb2, 0xef, 0xeb, 0x58, 0x6c, 0xf4, 0x1e, 0x97, 0x34, 0xee, 0xf9, - 0x74, 0xe2, 0x94, 0xc0, 0xf2, 0xf5, 0x0b, 0x97, 0x40, 0xce, 0x25, 0xd6, 0xe5, 0xdf, 0x0b, 0x3b, 0x6b, 0xf3, 0x38, 0x28, - 0xc3, 0xa6, 0x30, 0xa5, 0x22, 0x3c, 0xb0, 0xbd, 0x4d, 0xd5, 0x79, 0x25, 0xb9, 0xb2, 0xb4, 0xc4, 0x31, 0x62, 0x0b, 0xe7, - 0x73, 0x4e, 0xf9, 0xa7, 0x57, 0xdf, 0x33, 0x0e, 0xf0, 0xb9, 0x3b, 0x6d, 0xff, 0x6b, 0x11, 0xb0, 0x90, 0x10, 0x2a, 0x7b, - 0xb5, 0x0b, 0x41, 0x17, 0x0b, 0x12, 0xc7, 0x61, 0xef, 0xb1, 0x9b, 0x57, 0x3a, 0x01, 0x55, 0x91, 0xe3, 0xd5, 0xc8, 0xd5, - 0xeb, 0x26, 0x90, 0x2b, 0x67, 0x5b, 0xc2, 0x0b, 0xad, 0x6f, 0x26, 0x3a, 0xf5, 0x45, 0xb2, 0xd7, 0x6a, 0x78, 0xaa, 0x43, - 0xd0, 0xdb, 0x53, 0x6f, 0x1a, 0x7a, 0x5c, 0x92, 0xe1, 0xb7, 0xe5, 0xad, 0xda, 0xac, 0x3b, 0x5a, 0x20, 0x06, 0xe1, 0x56, - 0xf0, 0x55, 0x66, 0x64, 0x42, 0xd4, 0xe4, 0x77, 0x3b, 0xa5, 0x60, 0x8d, 0x5b, 0x24, 0x7a, 0x2a, 0xb9, 0xe2, 0x2f, 0xc6, - 0x02, 0xd1, 0x21, 0xf3, 0x08, 0xbd, 0x7b, 0xf4, 0x44, 0x47, 0x00, 0xd2, 0xca, 0x3c, 0x80, 0x37, 0xb0, 0xf2, 0x3d, 0x07, - 0x87, 0xbd, 0xe8, 0x59, 0x01, 0x17, 0x7b, 0xb3, 0x1b, 0xc3, 0xce, 0x45, 0x77, 0x3c, 0x0e, 0xdd, 0xac, 0x38, 0xf1, 0x5e, - 0xde, 0x5e, 0xdd, 0xad, 0xf2, 0xc9, 0x0f, 0xed, 0xec, 0xe5, 0x00, 0x8b, 0x61, 0xf4, 0x62, 0xd5, 0x58, 0x37, 0xec, 0xbf, - 0x36, 0xcf, 0x7a, 0x6a, 0x55, 0x1f, 0x25, 0x53, 0xba, 0xcd, 0x76, 0xc3, 0x07, 0x5e, 0x12, 0xf0, 0xc3, 0x82, 0x52, 0x5f, - 0xc6, 0x24, 0x54, 0x76, 0x49, 0xa3, 0xf1, 0xdd, 0x67, 0x29, 0x81, 0x19, 0x5f, 0x7b, 0xcd, 0xc6, 0x60, 0x3e, 0x80, 0x02, - 0xb3, 0xd9, 0xb6, 0x9d, 0x29, 0x59, 0xdc, 0x79, 0x90, 0xab, 0x53, 0xf4, 0xe6, 0x23, 0xb4, 0x77, 0x0f, 0xc8, 0xf2, 0x88, - 0xb3, 0x1c, 0x70, 0xb4, 0xeb, 0xa8, 0xdf, 0x25, 0x5b, 0x94, 0xa6, 0xce, 0x80, 0xbd, 0x46, 0xe6, 0x26, 0x8c, 0x4f, 0xee, - 0x37, 0x81, 0x84, 0xc6, 0xff, 0x0a, 0x37, 0x2e, 0xa4, 0xcb, 0xdf, 0x62, 0x81, 0x79, 0x3b, 0xa2, 0xdb, 0x07, 0x14, 0x0c, - 0xf7, 0x44, 0x1e, 0xda, 0xe0, 0x6c, 0x1a, 0xb6, 0x52, 0x7f, 0xd8, 0xce, 0xe7, 0x29, 0x98, 0xc1, 0x69, 0x40, 0xb9, 0x2a, - 0xe7, 0xb4, 0xee, 0x04, 0x67, 0xf7, 0x54, 0xac, 0x94, 0x12, 0x5c, 0x67, 0xb4, 0x51, 0x9c, 0xf6, 0xfa, 0x9b, 0x10, 0xd3, - 0x7e, 0xce, 0x78, 0xd5, 0x88, 0x80, 0xd7, 0x88, 0xea, 0x16, 0x51, 0x0c, 0xc9, 0xf2, 0x55, 0xda, 0xbd, 0x22, 0x34, 0x1a, - 0x65, 0x8f, 0xd7, 0x52, 0x00, 0x98, 0xc3, 0x76, 0xff, 0x3e, 0xfc, 0x44, 0x4b, 0x7e, 0xc2, 0x40, 0x00, 0x94, 0xf3, 0xc6, - 0xd5, 0xa3, 0x0f, 0x95, 0x9a, 0x96, 0xbb, 0x50, 0xcd, 0xd0, 0x6f, 0x75, 0xd7, 0xcc, 0x89, 0xb4, 0xc2, 0x85, 0x7f, 0x5f, - 0x06, 0xc1, 0xdf, 0x3c, 0xdd, 0x32, 0xdb, 0x44, 0xae, 0x1e, 0xd8, 0x56, 0xde, 0x93, 0xb0, 0xbd, 0xed, 0x8c, 0xb6, 0xcc, - 0x15, 0xe7, 0x81, 0x98, 0x36, 0x36, 0xd6, 0x91, 0x61, 0xd8, 0x65, 0x57, 0x5d, 0xcd, 0xbf, 0xf1, 0x3b, 0x31, 0xb6, 0xdd, - 0x6e, 0xc6, 0xd3, 0x1b, 0xc9, 0x47, 0x8c, 0x09, 0x03, 0x81, 0x7d, 0xbd, 0x64, 0xa9, 0x09, 0x66, 0x81, 0x2d, 0x56, 0x43, - 0xe8, 0x3c, 0x3e, 0xaa, 0xf8, 0x28, 0x92, 0x13, 0xea, 0x1f, 0xc1, 0x81, 0x4f, 0xb1, 0x1e, 0x88, 0xd2, 0x47, 0xdb, 0xb4, - 0x7e, 0xcb, 0xac, 0xc4, 0xbc, 0x07, 0x68, 0x83, 0x7d, 0xd2, 0x90, 0x90, 0x01, 0xa7, 0x0b, 0xac, 0x60, 0x67, 0x0f, 0xf4, - 0x1b, 0x2c, 0x1e, 0x93, 0x93, 0x6a, 0x16, 0x63, 0x78, 0x36, 0x7d, 0xc5, 0xa5, 0x04, 0xf4, 0x96, 0x1d, 0xae, 0x1a, 0xdf, - 0x1d, 0xba, 0xfc, 0x00, 0x21, 0x07, 0x8c, 0xa7, 0x9d, 0x00, 0x60, 0xb7, 0xa4, 0x05, 0xdd, 0xcd, 0x05, 0xee, 0x70, 0x5e, - 0xc5, 0x79, 0x6c, 0xc1, 0x22, 0x57, 0xfb, 0x5a, 0x25, 0x3e, 0xb9, 0x37, 0x76, 0x61, 0xc2, 0x7d, 0x14, 0x3c, 0xd3, 0x3a, - 0x13, 0xb9, 0x33, 0x07, 0xf6, 0x53, 0xc9, 0x5b, 0xb9, 0x97, 0x03, 0xd0, 0x76, 0xb8, 0xd1, 0xf1, 0x43, 0x9d, 0x7f, 0x37, - 0x46, 0x1a, 0xda, 0xdf, 0xd7, 0x4a, 0xb7, 0x79, 0x84, 0x9e, 0x47, 0x73, 0xac, 0x26, 0xf7, 0xd7, 0x54, 0x16, 0xad, 0x49, - 0x5e, 0x5d, 0x77, 0x61, 0x79, 0xdd, 0x52, 0x13, 0x2f, 0x20, 0xce, 0x26, 0x35, 0xa3, 0x60, 0x28, 0x3f, 0xc5, 0x67, 0xce, - 0x43, 0xa0, 0x86, 0x28, 0xf7, 0xa6, 0xf9, 0x6a, 0xbf, 0x25, 0x41, 0xb7, 0x7d, 0xbc, 0x04, 0x02, 0xd1, 0xe5, 0xed, 0x74, - 0xf5, 0xf5, 0x39, 0xf5, 0x18, 0x42, 0x9f, 0xdc, 0xaf, 0x46, 0xb6, 0x55, 0x48, 0x72, 0xa6, 0x66, 0x94, 0xef, 0x4a, 0x45, - 0x92, 0xf8, 0x31, 0x7a, 0x19, 0x69, 0xcb, 0xcf, 0xf3, 0x10, 0x4a, 0x65, 0x53, 0x18, 0xf4, 0x7f, 0x47, 0xe8, 0xe5, 0x07, - 0xb1, 0x8b, 0x3c, 0x3b, 0xb1, 0x1f, 0xdb, 0xb8, 0x5d, 0x53, 0xcb, 0xad, 0xf7, 0x38, 0x91, 0x8a, 0x1e, 0xa6, 0x76, 0x05, - 0x48, 0x89, 0xcc, 0xff, 0x51, 0x59, 0x53, 0xe9, 0xd7, 0x6e, 0x1a, 0x6e, 0xad, 0xf2, 0xcb, 0xf5, 0xfd, 0x48, 0xbe, 0xa8, - 0x70, 0xae, 0x5e, 0xc1, 0x7e, 0x1e, 0x07, 0x8e, 0x64, 0x0d, 0x70, 0xb7, 0x92, 0xda, 0x6f, 0x45, 0xb0, 0xe3, 0x8a, 0x30, - 0xbc, 0x45, 0xd1, 0x65, 0xf2, 0xb7, 0xab, 0x4e, 0x16, 0x5c, 0xa2, 0xb2, 0x9a, 0x4d, 0x2f, 0x76, 0x26, 0x62, 0x92, 0x7a, - 0x3c, 0x47, 0xf6, 0x87, 0x04, 0x0f, 0x7b, 0xda, 0x4b, 0x02, 0x6b, 0xd6, 0x16, 0x79, 0xbd, 0x16, 0x24, 0x42, 0x7a, 0xf4, - 0x44, 0x58, 0xb4, 0x68, 0x71, 0xce, 0xb3, 0x28, 0xba, 0x84, 0x6c, 0x26, 0x82, 0x1e, 0xba, 0x19, 0x83, 0xb7, 0x75, 0x1b, - 0xde, 0x09, 0xf6, 0x1b, 0x4f, 0x31, 0x65, 0xae, 0xb6, 0x45, 0xc2, 0xa7, 0x35, 0x2d, 0x9f, 0x14, 0x10, 0xe0, 0x3e, 0x43, - 0xa7, 0x82, 0x01, 0x06, 0x95, 0x2c, 0x19, 0x43, 0x8c, 0x94, 0xd4, 0x8c, 0x85, 0x6d, 0x88, 0x33, 0xff, 0x19, 0x51, 0xd3, - 0x7c, 0xf2, 0xa7, 0x5b, 0x05, 0xd1, 0x2b, 0x56, 0x18, 0x5e, 0xa6, 0xb9, 0x66, 0x3c, 0xf7, 0x4d, 0xbd, 0xa9, 0x95, 0x75, - 0xa9, 0xa1, 0x87, 0x24, 0x87, 0xf0, 0x60, 0xbb, 0x39, 0xec, 0xd1, 0xe5, 0x67, 0x51, 0x76, 0x99, 0xbc, 0x64, 0x7b, 0x5a, - 0xd5, 0xa6, 0x54, 0x4f, 0x16, 0x10, 0xb2, 0xe9, 0x43, 0x1c, 0x3a, 0x4c, 0x88, 0x51, 0xf4, 0xc2, 0x95, 0x16, 0x8e, 0xbf, - 0x79, 0x19, 0x22, 0x95, 0xd1, 0x76, 0x99, 0xb8, 0x68, 0xf3, 0x6a, 0x1a, 0x4e, 0x43, 0xf8, 0x9c, 0x6b, 0x75, 0x8c, 0xa5, - 0xbd, 0x65, 0x3a, 0x83, 0x0b, 0x47, 0xcf, 0x08, 0xf7, 0x22, 0x86, 0xad, 0xd5, 0x89, 0xd0, 0x6f, 0x4e, 0xbe, 0x2a, 0x81, - 0x1d, 0x1c, 0xf1, 0xc8, 0xf3, 0x18, 0x44, 0x40, 0xf3, 0x99, 0xfd, 0x18, 0xe3, 0x1a, 0xc9, 0x7f, 0x3b, 0x93, 0x68, 0x84, - 0xe2, 0x49, 0xb9, 0xcf, 0x00, 0x5c, 0x76, 0xc4, 0xcc, 0x4b, 0x7e, 0x86, 0x7e, 0x3f, 0x4b, 0x23, 0x61, 0x92, 0x7c, 0xcb, - 0x0c, 0x0c, 0x3e, 0x97, 0x34, 0xcc, 0xfd, 0x34, 0xa9, 0xcc, 0xf0, 0x83, 0xb1, 0xbc, 0x50, 0x4c, 0x84, 0x6f, 0xba, 0x68, - 0x01, 0x4f, 0x71, 0x57, 0x05, 0x7f, 0x01, 0xe2, 0x18, 0x23, 0xe9, 0x44, 0xa8, 0x4d, 0x93, 0x11, 0xee, 0xc0, 0x79, 0x5a, - 0x94, 0x13, 0x81, 0xf4, 0x67, 0xa0, 0x50, 0x79, 0x83, 0xa1, 0x13, 0x5f, 0x0e, 0x82, 0x9a, 0x72, 0x90, 0xba, 0x43, 0x21, - 0x28, 0xa9, 0x65, 0x1c, 0x16, 0x97, 0x6f, 0xdb, 0xc3, 0x1e, 0x23, 0xc5, 0x4a, 0xdb, 0x3b, 0x3c, 0x42, 0x4a, 0xc4, 0xb5, - 0x7f, 0x6b, 0x5d, 0xfc, 0x09, 0x08, 0x43, 0x2f, 0xf8, 0x11, 0x27, 0x6f, 0x1d, 0xc0, 0x12, 0x59, 0x04, 0xa4, 0x5b, 0xe9, - 0x9f, 0x25, 0xd1, 0x58, 0x3a, 0x1f, 0xac, 0x05, 0x15, 0x18, 0xea, 0xbd, 0x4b, 0xd2, 0xba, 0x67, 0xf3, 0x1d, 0x89, 0x09, - 0x52, 0xe5, 0x0e, 0x15, 0xd6, 0x5b, 0x87, 0xf5, 0xc3, 0x3c, 0x98, 0xbc, 0x46, 0x4e, 0x19, 0x8d, 0xbb, 0x3e, 0xe0, 0xde, - 0x19, 0x59, 0x53, 0x32, 0x62, 0x31, 0x16, 0xd4, 0xea, 0x63, 0xda, 0xf4, 0xcc, 0x94, 0xd0, 0x18, 0x98, 0xbc, 0x00, 0xd3, - 0x6c, 0xe2, 0xa5, 0xac, 0x30, 0x08, 0x9d, 0x68, 0x82, 0x8e, 0xbb, 0xdf, 0x9a, 0xa1, 0x13, 0xa5, 0x98, 0x18, 0xa9, 0x11, - 0xde, 0x49, 0x18, 0x88, 0xab, 0xff, 0xc6, 0x2c, 0xa8, 0xe1, 0xf7, 0x49, 0xba, 0x17, 0x93, 0x1c, 0x6c, 0x7f, 0x2c, 0xa9, - 0x3a, 0xee, 0x77, 0x9d, 0x46, 0x0c, 0xf9, 0x1c, 0x24, 0x33, 0x6f, 0x9b, 0xf8, 0x47, 0x9d, 0xc9, 0x7f, 0x9c, 0x80, 0xa0, - 0x2c, 0x96, 0x63, 0xe1, 0x97, 0x75, 0x75, 0x1f, 0xb3, 0xc6, 0x0d, 0xa9, 0x49, 0x82, 0x66, 0x86, 0x13, 0xa4, 0x62, 0x4c, - 0x56, 0x89, 0x73, 0x03, 0x1b, 0x61, 0xff, 0xfa, 0x0f, 0xf4, 0x84, 0xe3, 0xad, 0x89, 0xc0, 0x8e, 0x03, 0x91, 0x1c, 0x99, - 0x9f, 0x99, 0x92, 0x7e, 0xb5, 0xd8, 0xe3, 0xee, 0x6c, 0x21, 0x27, 0x5d, 0xa2, 0xa5, 0x90, 0xf2, 0x67, 0xed, 0xf3, 0xca, - 0x51, 0x56, 0x28, 0x7d, 0xa9, 0xd0, 0x4a, 0x4b, 0x76, 0x2b, 0xa8, 0x95, 0x8a, 0x37, 0xb4, 0x72, 0x96, 0xb2, 0xa0, 0xbe, - 0x90, 0x4f, 0x4e, 0x37, 0xbb, 0x14, 0xf8, 0xd2, 0x76, 0x7c, 0x79, 0xf3, 0xd2, 0xbf, 0x35, 0xad, 0x64, 0xbc, 0x98, 0x73, - 0xe5, 0xb9, 0xb3, 0xa2, 0x9b, 0x54, 0x17, 0x9b, 0x99, 0xa1, 0xeb, 0xfd, 0xc2, 0x8b, 0xbd, 0xac, 0x6d, 0x14, 0x35, 0xc2, - 0x3b, 0xc9, 0x88, 0x57, 0x64, 0xaa, 0x52, 0x3d, 0xf1, 0x80, 0x9c, 0xb2, 0xfc, 0xe9, 0x53, 0x7c, 0x12, 0x81, 0xe6, 0x07, - 0xa1, 0x0b, 0x2b, 0xb3, 0x88, 0xa6, 0x07, 0xb8, 0x10, 0x7e, 0xc4, 0x55, 0x14, 0xa2, 0x66, 0xf1, 0xcc, 0xff, 0x49, 0x84, - 0xbc, 0x54, 0x15, 0x41, 0x26, 0x15, 0x44, 0xf1, 0xe4, 0x4e, 0x8a, 0xf4, 0x02, 0xb1, 0x87, 0x51, 0xa7, 0xa4, 0xe6, 0x4f, - 0xbb, 0xff, 0xfe, 0x94, 0x51, 0x54, 0x20, 0x7e, 0x16, 0x60, 0x23, 0xfe, 0x05, 0x8c, 0x1a, 0xe1, 0x12, 0x7c, 0xd4, 0xc0, - 0xae, 0x3a, 0x96, 0x13, 0x5d, 0x83, 0x89, 0x49, 0x99, 0x2c, 0x3e, 0x19, 0x8b, 0xa8, 0xf0, 0x0d, 0x65, 0x5d, 0x35, 0x37, - 0xa1, 0x2d, 0xdd, 0xe2, 0x6b, 0x0d, 0xa9, 0x47, 0x9e, 0xf0, 0x22, 0xb5, 0x8e, 0xab, 0xc1, 0x34, 0x93, 0x4c, 0xff, 0x89, - 0x9b, 0x24, 0xd4, 0x01, 0x24, 0xbc, 0xf5, 0x42, 0xd8, 0xee, 0xc2, 0xbc, 0x78, 0x03, 0xc1, 0x24, 0xa8, 0x88, 0xba, 0x3f, - 0x71, 0x58, 0x3d, 0xdd, 0xef, 0xa8, 0xf8, 0x15, 0x4c, 0xb0, 0x68, 0x7c, 0xbc, 0x41, 0x66, 0x72, 0xc4, 0x4d, 0x9f, 0xd0, - 0xdb, 0x9a, 0xd0, 0x65, 0xde, 0xf1, 0x25, 0x02, 0x35, 0xff, 0x49, 0x4a, 0xd8, 0xa4, 0x19, 0x49, 0xb4, 0x51, 0xda, 0x4b, - 0x75, 0x81, 0x17, 0xa7, 0x84, 0x80, 0x70, 0x3f, 0xc7, 0x0d, 0xb2, 0x79, 0x24, 0x25, 0x7c, 0xe2, 0x30, 0x67, 0x15, 0x00, - 0x80, 0x68, 0x1e, 0xde, 0xf0, 0x3e, 0xda, 0xc6, 0x31, 0x4d, 0xa7, 0xf0, 0x53, 0x0d, 0x88, 0x08, 0xe1, 0xd8, 0xe2, 0x8b, - 0x01, 0xdb, 0x9f, 0x5b, 0x7c, 0xd4, 0x68, 0x89, 0xb1, 0xeb, 0xdb, 0x4e, 0x6f, 0xac, 0x21, 0xad, 0xf2, 0xed, 0x6f, 0x61, - 0x4d, 0x1f, 0x2f, 0x64, 0x0b, 0xdb, 0x07, 0x54, 0x65, 0xd7, 0xf0, 0xf8, 0x40, 0xdb, 0xd9, 0x5e, 0x2d, 0xaf, 0x4f, 0x14, - 0x9f, 0x5b, 0x0b, 0x74, 0x4e, 0xad, 0x07, 0x60, 0xac, 0x24, 0x04, 0x5b, 0xc8, 0xf4, 0xc9, 0x6f, 0x28, 0xb0, 0x2b, 0xb3, - 0xd9, 0x43, 0xf1, 0x55, 0xc9, 0x25, 0x01, 0xb7, 0xab, 0x8f, 0xd8, 0x0f, 0x78, 0x6a, 0xbf, 0xa0, 0x4e, 0x80, 0x22, 0xc6, - 0x8a, 0x42, 0x37, 0x6d, 0x3a, 0xbd, 0xf3, 0x66, 0xbe, 0x84, 0x87, 0xf6, 0xa1, 0xa0, 0x99, 0x7f, 0x13, 0x66, 0x40, 0x39, - 0xce, 0x43, 0x8f, 0xe5, 0x83, 0x48, 0x94, 0xc6, 0x59, 0xc2, 0xce, 0x55, 0x35, 0x44, 0x74, 0xa6, 0x37, 0x0c, 0x3c, 0x69, - 0xdc, 0xdb, 0x2b, 0x3a, 0xd8, 0x32, 0x4d, 0x31, 0x25, 0x30, 0x23, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x09, 0x15, 0x31, 0x16, 0x04, 0x14, 0x01, 0xae, 0x1a, 0x61, 0x75, 0xae, 0x23, 0xd9, 0x11, 0x5c, 0x28, 0x93, 0xa9, 0xe2, - 0x49, 0x5e, 0x74, 0x28, 0x4c, 0x08, 0x30, 0x31, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, - 0x00, 0x04, 0x14, 0x3d, 0xc6, 0xb0, 0x07, 0xf5, 0xd4, 0xa7, 0x42, 0x90, 0xa1, 0x2f, 0x4d, 0x1e, 0x43, 0x09, 0x7d, 0xd5, - 0xfe, 0x15, 0xb1, 0x04, 0x08, 0xdd, 0xee, 0x2c, 0x8a, 0x3d, 0x65, 0x41, 0x94, 0x02, 0x02, 0x08, 0x00 -}; - -/* Random data for content */ -uint8_t content[1024] = { - 0x2a, 0xb1, 0x8c, 0xf1, 0x66, 0x52, 0xd5, 0x3c, 0xdd, 0x53, 0xc0, 0x07, 0x6a, 0x13, 0xda, 0x25, 0x9c, 0x04, 0x64, 0x5c, - 0x97, 0xb8, 0xb3, 0xb5, 0xcf, 0xf8, 0xe1, 0x8f, 0xdd, 0x49, 0x64, 0x55, 0x97, 0xad, 0xbc, 0xad, 0xff, 0xd1, 0xd9, 0xdf, - 0x0f, 0x26, 0x96, 0x27, 0x78, 0x1b, 0x13, 0xf6, 0x2e, 0x75, 0xb2, 0x6a, 0xf1, 0x04, 0x71, 0xa3, 0x51, 0x8d, 0x9c, 0xe8, - 0xab, 0xee, 0xf4, 0xf4, 0xfa, 0x75, 0x16, 0xbe, 0x08, 0xaf, 0xdf, 0x23, 0xc2, 0x17, 0x75, 0x80, 0xad, 0x0e, 0x68, 0xc1, - 0x37, 0xd9, 0x49, 0x0b, 0xea, 0x8a, 0x29, 0x3a, 0x2d, 0xff, 0x45, 0xe9, 0x13, 0x93, 0xac, 0x2e, 0x25, 0x3d, 0x5f, 0xd1, - 0x36, 0x66, 0x61, 0x14, 0xa9, 0xf1, 0xae, 0x83, 0x3a, 0x96, 0xe3, 0xcd, 0xe1, 0xdd, 0xb8, 0x8b, 0x85, 0xe7, 0xd9, 0x1b, - 0x76, 0xf9, 0x55, 0xf7, 0xd8, 0xb6, 0xca, 0x5b, 0x0f, 0xb8, 0x40, 0x1b, 0x69, 0x54, 0x07, 0xde, 0xd5, 0x26, 0x85, 0x9b, - 0xd1, 0x4a, 0xce, 0x2b, 0xe1, 0xd8, 0xe7, 0x6a, 0x06, 0x28, 0x4b, 0x05, 0xa9, 0x0b, 0x65, 0x07, 0x3d, 0xf5, 0xca, 0x31, - 0xd0, 0xfb, 0x5b, 0xf8, 0x1e, 0x19, 0x5f, 0x69, 0x64, 0x1b, 0xe1, 0x6d, 0x15, 0x88, 0x9c, 0xd1, 0x25, 0x4d, 0xf2, 0xa5, - 0x74, 0x82, 0xa4, 0xd3, 0x21, 0xc2, 0x4f, 0x78, 0xcf, 0x37, 0xdd, 0x3c, 0xe5, 0x69, 0x27, 0x82, 0xf1, 0xc8, 0xe9, 0x2f, - 0x7a, 0x7d, 0xd4, 0x65, 0x78, 0xad, 0x4c, 0xfc, 0xa5, 0x29, 0x51, 0xe2, 0x67, 0xac, 0x29, 0xa4, 0x23, 0x46, 0xe0, 0x10, - 0x55, 0x2a, 0x7e, 0xef, 0x04, 0xd4, 0x9f, 0xe3, 0x65, 0x09, 0x2d, 0x33, 0x07, 0xa5, 0x6c, 0x3d, 0x6e, 0xf5, 0x3e, 0xda, - 0x92, 0xb3, 0x47, 0x89, 0xa8, 0xda, 0x04, 0xe0, 0xa6, 0xcd, 0xd5, 0x84, 0xd6, 0xd5, 0x6f, 0xa5, 0x30, 0x3f, 0xcc, 0x9e, - 0xfe, 0xd5, 0xd6, 0xb8, 0x61, 0xf6, 0xb0, 0x10, 0x9d, 0x4d, 0x5c, 0x90, 0xc8, 0x05, 0x4d, 0xba, 0x99, 0x8e, 0xa7, 0xc8, - 0x53, 0xe7, 0x5d, 0xd7, 0x37, 0xf3, 0x0b, 0xc9, 0x0f, 0x97, 0x2d, 0x3e, 0x22, 0xed, 0xdc, 0x28, 0x22, 0x32, 0x04, 0xc0, - 0x6a, 0x38, 0xd8, 0xc8, 0x85, 0xef, 0x57, 0x9c, 0xa1, 0xe0, 0x0b, 0x7e, 0x6a, 0xb4, 0x5a, 0x76, 0x7c, 0xaf, 0x6f, 0x5d, - 0xcc, 0x56, 0xef, 0x60, 0x3c, 0xce, 0x0f, 0x0a, 0x5e, 0xfa, 0xbb, 0xb6, 0xd8, 0xba, 0xda, 0x9d, 0xf5, 0x86, 0x55, 0xc2, - 0x84, 0x9b, 0x3d, 0xc2, 0x54, 0x5b, 0xa9, 0x23, 0x57, 0xe1, 0x0a, 0x84, 0x7e, 0x3c, 0x52, 0x9c, 0x3d, 0x02, 0x9b, 0xb5, - 0x9c, 0x50, 0xfb, 0xfc, 0x43, 0xf9, 0x07, 0x34, 0xd9, 0xad, 0x3f, 0x59, 0x44, 0x6b, 0x47, 0xa0, 0xb9, 0x29, 0x63, 0xfb, - 0xd9, 0xd7, 0xfc, 0x62, 0xda, 0x23, 0x7e, 0x2b, 0xb6, 0x09, 0xfc, 0x52, 0x70, 0x77, 0xb9, 0x4d, 0x92, 0xdd, 0xf2, 0x82, - 0x8c, 0xa3, 0xf5, 0x79, 0xf9, 0x21, 0xe8, 0x36, 0xea, 0xf5, 0xa7, 0x8c, 0x3c, 0x46, 0xab, 0x29, 0xdc, 0x91, 0xa8, 0x8e, - 0xc5, 0xe7, 0xe5, 0x95, 0xd5, 0xca, 0xed, 0xad, 0x54, 0x24, 0xf2, 0xee, 0x40, 0x9c, 0x06, 0x08, 0x03, 0x36, 0x0a, 0x73, - 0xa4, 0xcb, 0xbb, 0x28, 0x83, 0x28, 0x66, 0xc3, 0x79, 0xba, 0x7a, 0x76, 0x90, 0x10, 0x88, 0x04, 0x3f, 0x0f, 0x67, 0xd2, - 0x53, 0xab, 0x63, 0xc7, 0x83, 0xc9, 0x2b, 0xdd, 0x9c, 0x61, 0x99, 0xe4, 0x12, 0x18, 0xc6, 0x9a, 0x9d, 0x3c, 0xea, 0x13, - 0x87, 0x32, 0x57, 0x8d, 0x01, 0x11, 0x39, 0x56, 0x94, 0xb2, 0x4d, 0x73, 0xc0, 0xdc, 0x2d, 0x4c, 0xb3, 0xd1, 0x90, 0x36, - 0xd8, 0xae, 0xd3, 0x06, 0xd7, 0x70, 0xa5, 0xd6, 0x0e, 0x64, 0xf8, 0x80, 0xb6, 0x36, 0x0c, 0x31, 0xd3, 0xcc, 0x46, 0xba, - 0xb4, 0x14, 0xb4, 0xcb, 0x43, 0x68, 0x0f, 0x8d, 0xf7, 0x2c, 0x61, 0xf4, 0xfb, 0xce, 0xf1, 0xaf, 0xe9, 0x2e, 0x52, 0x02, - 0x29, 0x5e, 0xd7, 0xc6, 0xed, 0xf6, 0x22, 0xb9, 0x7b, 0xe8, 0x1a, 0xe6, 0x59, 0xdb, 0x43, 0xdd, 0x58, 0xe2, 0x50, 0xab, - 0x57, 0x01, 0xf0, 0x61, 0xb0, 0x83, 0xa9, 0x40, 0x0c, 0x24, 0x08, 0x6e, 0x95, 0x45, 0xba, 0xb3, 0x02, 0xa9, 0x41, 0xde, - 0xaf, 0xc2, 0x4c, 0xc2, 0x71, 0x1e, 0x86, 0xe4, 0xe9, 0x81, 0x9e, 0xdf, 0xea, 0x11, 0x66, 0x91, 0x02, 0x8c, 0xf5, 0xa3, - 0x05, 0xe3, 0xe9, 0x6e, 0x7f, 0x34, 0xb5, 0x0a, 0x3f, 0xc3, 0x70, 0x18, 0x33, 0x33, 0x7e, 0x85, 0x81, 0x04, 0x1f, 0xaa, - 0x14, 0x0c, 0x57, 0xca, 0x41, 0x97, 0x79, 0x62, 0x2e, 0x99, 0xbc, 0x6f, 0xce, 0x21, 0xad, 0xde, 0x7d, 0x74, 0x73, 0x3f, - 0x75, 0x00, 0x65, 0xc2, 0x40, 0x5e, 0xda, 0xce, 0x41, 0x4e, 0x8b, 0xd0, 0x32, 0x4f, 0x7f, 0xee, 0xbe, 0xc9, 0x41, 0xb2, - 0x42, 0xe9, 0x5a, 0xe5, 0xee, 0x18, 0x0c, 0x70, 0x93, 0xec, 0xb2, 0x46, 0xcd, 0x11, 0x16, 0x31, 0x81, 0x33, 0x5e, 0x82, - 0x20, 0x85, 0x1b, 0x02, 0x76, 0xeb, 0x13, 0xb9, 0xd4, 0xbd, 0xf9, 0xe7, 0xb5, 0x5e, 0x5e, 0x05, 0x48, 0x74, 0x27, 0xf2, - 0xdc, 0x3e, 0x87, 0x8b, 0x33, 0x3f, 0x50, 0xb6, 0xc6, 0x52, 0xf8, 0x61, 0x69, 0x7e, 0x6b, 0x30, 0xef, 0x2c, 0x6c, 0x5e, - 0x69, 0xc8, 0xba, 0x1e, 0x3d, 0x2a, 0x0c, 0x74, 0xbd, 0x93, 0xc9, 0x36, 0xcc, 0x72, 0x15, 0xe6, 0xbb, 0xd0, 0xc0, 0xe3, - 0xaf, 0x60, 0xcd, 0x83, 0x54, 0x50, 0x67, 0xbb, 0x70, 0x2a, 0xa1, 0x51, 0x87, 0x9b, 0xc5, 0xe0, 0xbb, 0xa3, 0xb1, 0x6f, - 0x3a, 0x1a, 0x62, 0x72, 0x6f, 0x89, 0x8a, 0x1d, 0xc4, 0x09, 0x55, 0xac, 0x67, 0x7b, 0xa3, 0xe6, 0xed, 0x4e, 0xbb, 0xf2, - 0x5f, 0x42, 0x95, 0x7b, 0x95, 0x7a, 0xbe, 0x3e, 0xf5, 0x2f, 0xee, 0x5f, 0x30, 0x57, 0x51, 0x94, 0x7d, 0x45, 0xd5, 0xd7, - 0x6e, 0xcc, 0xf6, 0x4d, 0xac, 0x7b, 0x51, 0x70, 0x32, 0x07, 0x1c, 0xaf, 0x97, 0xdd, 0x92, 0x0d, 0x9d, 0xba, 0x53, 0xf5, - 0x49, 0xc7, 0xa5, 0x6a, 0x7a, 0x3b, 0xb0, 0x3f, 0x0c, 0x01, 0xa5, 0x00, 0x4a, 0x33, 0x90, 0xf7, 0xee, 0x0a, 0x12, 0x5d, - 0xc0, 0x5d, 0xb1, 0x85, 0x63, 0xed, 0xcf, 0xb8, 0x84, 0xde, 0x51, 0x8f, 0xd9, 0xf4, 0x15, 0x76, 0x43, 0xc4, 0xfe, 0x89, - 0x16, 0xfe, 0x13, 0x92, 0xbd, 0x25, 0x66, 0xb9, 0x56, 0x60, 0x1f, 0x85, 0x3d, 0xc6, 0x9a, 0x02, 0xc4, 0x2a, 0xbf, 0x8b, - 0x1b, 0xf1, 0x41, 0xbb, 0x37, 0x77, 0xe1, 0x18, 0xa7, 0x5f, 0x2a, 0x30, 0x37, 0xf6, 0xf4, 0x2a, 0x4b, 0x77, 0xf8, 0x15, - 0xc5, 0xb9, 0xb5, 0xdd, 0x93, 0x4f, 0x59, 0x97, 0x6b, 0xf2, 0xe8, 0x6e, 0xf5, 0x7e, 0x21, 0x20, 0x64, 0xac, 0xe8, 0x8d, - 0x60, 0xcb, 0xd2, 0xdc, 0xa7, 0xc8, 0x16, 0xb2, 0x7c, 0xf3, 0xbe, 0x88, 0x5b, 0x75, 0xcb, 0xf7, 0x38, 0x79, 0xa5, 0x32, - 0x5f, 0xa7, 0xf2, 0xfd, 0x6a, 0x21, 0x71, 0x16, 0x1b, 0xe9, 0xde, 0xd9, 0x88, 0xf2, 0x89, 0xef, 0x4f, 0x9a, 0xc4, 0x9b, - 0x04, 0xa0, 0x16, 0xab, 0x39, 0x62, 0x3f, 0x1f, 0x06, 0x2a, 0x88, 0x04, 0x68, 0x63, 0xb1, 0x21, 0x87, 0x25, 0xfb, 0xc3, - 0xb5, 0xe0, 0xc8, 0x48, 0x42, 0x4e, 0x3a, 0xc9, 0x90, 0x4c, 0xc1, 0xa5, 0x69, 0x62, 0xd6, 0x25, 0xdc, 0xc9, 0x51, 0xeb, - 0x6f, 0x00, 0x70, 0x91, 0x86, 0x57, 0x36, 0x23, 0x1f, 0x29, 0x8b, 0x52, 0xb2, 0x31, 0xd5, 0x8d, 0xc5, 0xa3, 0x5f, 0xd3, - 0x7a, 0xe4, 0x2e, 0x3a -}; - -/* Random data for hash agility attribute */ -uint8_t attribute[32] = { - 0x2e, 0xd0, 0xd3, 0x8f, 0xfd, 0xab, 0xc6, 0x13, 0xc8, 0x7c, 0x7b, 0x3c, 0x05, 0x16, 0xfb, 0x44, 0x66, 0x40, 0xaf, 0xe3, - 0x87, 0xa0, 0x4e, 0x80, 0xf4, 0xf3, 0x5d, 0xd2, 0x68, 0x08, 0x58, 0xe6 -}; - -/* Valid CMS message on content with hash agility attribute */ -uint8_t valid_message[] = { - 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, 0x00, 0x00, 0xa0, 0x82, 0x06, 0xb4, 0x30, 0x82, 0x06, 0xb0, 0x30, 0x82, 0x04, 0x98, - 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, - 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, - 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 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, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, - 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, - 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 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, 0x18, - 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, - 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x31, 0x30, - 0x32, 0x39, 0x32, 0x31, 0x35, 0x35, 0x35, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x30, 0x32, - 0x38, 0x32, 0x31, 0x35, 0x35, 0x35, 0x38, 0x5a, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, - 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, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, - 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, - 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, - 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, - 0x72, 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, 0xc4, 0x2a, 0x38, 0x4b, 0xdd, 0x1c, 0xc7, 0x39, 0x47, 0xba, 0xbc, 0x5d, 0xd2, 0xcc, - 0x6e, 0x9e, 0x2c, 0x81, 0x26, 0x18, 0x59, 0x18, 0xb8, 0x45, 0x0c, 0xde, 0x5b, 0xbc, 0x25, 0xa4, - 0x78, 0x0b, 0x16, 0x3d, 0x3d, 0x10, 0x34, 0x48, 0xcf, 0x1f, 0x40, 0xaa, 0x4b, 0xb5, 0xbc, 0xf0, - 0x81, 0x5e, 0xa8, 0x72, 0xed, 0x6a, 0x8c, 0xf0, 0x4a, 0x9a, 0x80, 0x09, 0x3b, 0x89, 0xed, 0xad, - 0x2b, 0xb5, 0x5b, 0x0f, 0xe4, 0x3f, 0x6b, 0xc5, 0x15, 0x33, 0x5e, 0xdd, 0xa4, 0xac, 0x2f, 0xa5, - 0x13, 0x0f, 0x3c, 0xfc, 0xd8, 0xca, 0xb8, 0x88, 0x67, 0x75, 0xc4, 0x9a, 0x4c, 0x18, 0x9a, 0x38, - 0x68, 0xaa, 0x4c, 0x94, 0x35, 0xed, 0xa4, 0x0b, 0x80, 0x2b, 0xa9, 0x4d, 0xa4, 0x57, 0x22, 0xfc, - 0xd2, 0xc3, 0x12, 0x0b, 0x8a, 0x3c, 0xd7, 0x6d, 0x8b, 0x47, 0x4f, 0x24, 0xe5, 0xea, 0x1b, 0x03, - 0x78, 0xa2, 0x12, 0x36, 0x3f, 0x92, 0x16, 0x36, 0xff, 0xc5, 0xaf, 0xc3, 0xec, 0x4b, 0x6c, 0x23, - 0x04, 0x1b, 0xa9, 0xce, 0x3a, 0xa1, 0xa5, 0xe0, 0x54, 0x13, 0x43, 0x13, 0x29, 0x95, 0x5b, 0xcb, - 0x97, 0x74, 0x01, 0xbc, 0x3c, 0xb8, 0xa1, 0xb0, 0xf3, 0x3c, 0xfa, 0x21, 0x7a, 0x89, 0x90, 0x2b, - 0x1f, 0x20, 0x3f, 0xc1, 0x22, 0xda, 0x8d, 0xa5, 0x30, 0x57, 0x6d, 0xd4, 0x40, 0x99, 0x08, 0x0d, - 0xef, 0x36, 0x16, 0xa6, 0xec, 0xcf, 0x26, 0x78, 0x7c, 0x77, 0x7e, 0x50, 0x2a, 0xe3, 0xdf, 0x28, - 0xff, 0xd0, 0xc7, 0x0e, 0x8b, 0x6b, 0x56, 0x62, 0x53, 0x37, 0x5a, 0x1a, 0x85, 0x50, 0xec, 0x6a, - 0x6b, 0x2e, 0xd1, 0x35, 0x6e, 0x5d, 0x92, 0x30, 0x39, 0x82, 0x40, 0x7b, 0x6d, 0x89, 0x5b, 0x4d, - 0x30, 0x6d, 0x2e, 0x68, 0x16, 0x24, 0x63, 0x32, 0x24, 0xdc, 0x3e, 0x5b, 0x4a, 0xc4, 0x41, 0xfc, - 0x76, 0x07, 0xe6, 0xa3, 0x1b, 0x18, 0xec, 0x59, 0xed, 0x13, 0x0b, 0x2d, 0xe9, 0x86, 0x89, 0x2c, - 0x0a, 0xb0, 0x19, 0x97, 0x4d, 0x1b, 0xfb, 0xd4, 0xef, 0x54, 0xcd, 0xe5, 0xb2, 0x22, 0x70, 0x3a, - 0x50, 0x03, 0xaa, 0xc0, 0xf8, 0xb4, 0x8e, 0x16, 0xd8, 0x2a, 0xc1, 0xd1, 0x2d, 0xa0, 0x27, 0x59, - 0x63, 0x70, 0xc3, 0x74, 0x14, 0xee, 0xde, 0xa9, 0xd9, 0x73, 0xdb, 0x16, 0x6d, 0xef, 0x7f, 0x50, - 0xb6, 0xd2, 0x54, 0x0d, 0x4d, 0x31, 0x5f, 0x23, 0x2c, 0xfd, 0x8f, 0x67, 0x7c, 0xe9, 0xaa, 0x1c, - 0x29, 0xf5, 0x83, 0x1b, 0x2b, 0x0e, 0x66, 0x0e, 0x5c, 0xfe, 0xc9, 0x38, 0xb0, 0x90, 0xfa, 0x31, - 0x4c, 0xb1, 0xef, 0xea, 0xd0, 0x47, 0x17, 0xde, 0x45, 0xc1, 0x93, 0xef, 0xba, 0xde, 0x9f, 0x69, - 0xc7, 0xa6, 0x14, 0x23, 0xb1, 0x8b, 0xaa, 0xbf, 0x61, 0x37, 0x57, 0x11, 0x6a, 0xb2, 0xf7, 0xec, - 0x52, 0x7e, 0x65, 0x80, 0xff, 0xa1, 0xa8, 0x20, 0x7e, 0x0b, 0xae, 0x21, 0xfa, 0xe8, 0x20, 0x52, - 0x93, 0xc5, 0xe9, 0x39, 0x5b, 0x8e, 0xab, 0xef, 0x86, 0xa6, 0xd8, 0x43, 0x7e, 0xa9, 0x5c, 0x6d, - 0x91, 0xd8, 0x5c, 0xa4, 0x2a, 0xed, 0x26, 0xa8, 0x1b, 0xaa, 0x3b, 0xfa, 0x86, 0x75, 0x37, 0xc6, - 0x70, 0x12, 0x2b, 0x8c, 0x55, 0x96, 0x76, 0x04, 0xf6, 0xe3, 0xf9, 0xe2, 0x0d, 0x2e, 0xe0, 0x23, - 0xdf, 0xfa, 0xe0, 0x9c, 0x11, 0xf9, 0xd4, 0x51, 0x05, 0xed, 0x2b, 0x3f, 0xa3, 0x3f, 0xa2, 0xe6, - 0x30, 0x81, 0x17, 0x00, 0x8f, 0x15, 0x91, 0xfb, 0x21, 0x62, 0xf4, 0xff, 0x93, 0x1a, 0x2e, 0xfe, - 0x1a, 0xcb, 0x93, 0x3d, 0xd4, 0x6e, 0x3a, 0xb8, 0x70, 0xdf, 0x93, 0xb4, 0x02, 0xc4, 0x8c, 0x54, - 0x92, 0xde, 0xa7, 0x32, 0x65, 0x1c, 0x85, 0x95, 0x34, 0xf8, 0x8d, 0x06, 0x5b, 0x7d, 0x72, 0x00, - 0xd8, 0x31, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xfe, 0x30, 0x81, 0xfb, 0x30, 0x1d, 0x06, - 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xee, 0x16, 0xde, 0xfd, 0x11, 0xd3, 0x88, 0xfb, - 0xef, 0xfb, 0x19, 0x23, 0x8a, 0x23, 0x85, 0x7b, 0xe8, 0x41, 0x26, 0xa1, 0x30, 0x81, 0xcb, 0x06, - 0x03, 0x55, 0x1d, 0x23, 0x04, 0x81, 0xc3, 0x30, 0x81, 0xc0, 0x80, 0x14, 0xee, 0x16, 0xde, 0xfd, - 0x11, 0xd3, 0x88, 0xfb, 0xef, 0xfb, 0x19, 0x23, 0x8a, 0x23, 0x85, 0x7b, 0xe8, 0x41, 0x26, 0xa1, - 0xa1, 0x81, 0x9c, 0xa4, 0x81, 0x99, 0x30, 0x81, 0x96, 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, - 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, - 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, - 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x82, - 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, - 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x0c, 0x0f, 0x08, 0x79, - 0x6f, 0x56, 0x21, 0xdf, 0xdd, 0xf5, 0x97, 0x8d, 0xdc, 0x97, 0x06, 0xfb, 0x2e, 0xe0, 0x21, 0x60, - 0xc3, 0x02, 0xf4, 0x41, 0x79, 0x79, 0xc2, 0x23, 0x9a, 0x8a, 0x54, 0x2e, 0x66, 0xab, 0xc0, 0x21, - 0xf6, 0x9f, 0xc5, 0x2e, 0x41, 0xb8, 0xa3, 0x32, 0x9f, 0x3d, 0x4e, 0xf4, 0x83, 0xee, 0xcc, 0x60, - 0xf6, 0x82, 0x3d, 0xb4, 0xa9, 0x9d, 0xcd, 0xa0, 0x02, 0x89, 0xb0, 0x32, 0x1b, 0xb5, 0x7c, 0xf4, - 0x8f, 0xbc, 0x9b, 0x24, 0xc2, 0xe2, 0x81, 0xd6, 0x6f, 0x0e, 0x22, 0x5e, 0x50, 0xd9, 0x5b, 0x2e, - 0x89, 0xbf, 0xa4, 0xfe, 0xa8, 0xc2, 0x9a, 0xf4, 0xec, 0x70, 0x66, 0x01, 0x4b, 0x50, 0x30, 0x97, - 0x0a, 0xcc, 0x9f, 0xac, 0xe4, 0x89, 0x1c, 0x8d, 0x88, 0x0d, 0xdb, 0x21, 0xbd, 0x2f, 0x24, 0x8e, - 0x83, 0xf9, 0xe6, 0x71, 0xed, 0x71, 0x26, 0x31, 0x99, 0x9d, 0x04, 0xeb, 0x34, 0xea, 0x6d, 0x65, - 0xb8, 0x02, 0x83, 0x57, 0x78, 0x36, 0x3a, 0x0b, 0xc7, 0x41, 0x63, 0xb5, 0xf6, 0x1c, 0xd2, 0x01, - 0x86, 0x04, 0x58, 0x40, 0x3e, 0x91, 0x98, 0x39, 0x72, 0x75, 0x11, 0xca, 0x14, 0x73, 0x90, 0x34, - 0x8b, 0x21, 0xa4, 0xd0, 0xba, 0xe7, 0x33, 0x03, 0x22, 0x0f, 0x1a, 0xf7, 0x10, 0x2b, 0x69, 0x4c, - 0x73, 0xef, 0x04, 0x18, 0xf9, 0xe1, 0x11, 0xa8, 0xb8, 0x1b, 0x57, 0x0b, 0x03, 0x10, 0x1c, 0xce, - 0x13, 0xca, 0xe4, 0xde, 0x8c, 0xf4, 0xcf, 0xf5, 0xb7, 0x80, 0x3e, 0xbc, 0x1f, 0x51, 0x9b, 0x20, - 0x8c, 0xb0, 0x2d, 0x67, 0x1c, 0x84, 0x25, 0x4c, 0x8b, 0xd3, 0xa7, 0x09, 0x8e, 0x60, 0xe2, 0x99, - 0x0d, 0x10, 0x12, 0x14, 0xfc, 0x17, 0x62, 0x69, 0xcd, 0xa4, 0x64, 0xf0, 0x7e, 0xba, 0xe0, 0xc9, - 0x51, 0x78, 0xf8, 0xb4, 0x0d, 0x7d, 0xb8, 0xa0, 0xee, 0x9c, 0x9e, 0x84, 0xd5, 0xa4, 0x02, 0xe5, - 0x7a, 0x1c, 0x65, 0xe1, 0x20, 0xfb, 0x4d, 0x61, 0x7a, 0x47, 0x25, 0x06, 0x95, 0x17, 0x62, 0x60, - 0x4b, 0x0b, 0xc6, 0xca, 0xa7, 0x35, 0x8f, 0xd4, 0x63, 0x3e, 0x5e, 0x92, 0x1a, 0x08, 0x7c, 0x6b, - 0x15, 0x41, 0x95, 0x76, 0x7d, 0x39, 0x28, 0xec, 0x3e, 0x1f, 0x49, 0xd5, 0xd5, 0x89, 0xf9, 0x5f, - 0x14, 0x02, 0x2f, 0x27, 0xb0, 0x39, 0xba, 0xf7, 0x91, 0x53, 0x75, 0x77, 0xab, 0x88, 0x40, 0x1d, - 0x77, 0xaf, 0x79, 0xfd, 0xdc, 0xac, 0x99, 0x82, 0xf2, 0x46, 0x05, 0x97, 0x60, 0xef, 0x7b, 0xf5, - 0x34, 0x38, 0xbf, 0xd7, 0x42, 0x3e, 0x8b, 0x5a, 0x4a, 0x0c, 0x22, 0x7e, 0x4d, 0x4e, 0xf6, 0xf7, - 0xcc, 0x6e, 0x31, 0x33, 0x1a, 0x84, 0xbe, 0x07, 0xf7, 0xe8, 0xe2, 0x43, 0x00, 0x54, 0x4a, 0x38, - 0xda, 0x98, 0xe3, 0x84, 0xb2, 0xd0, 0x76, 0x79, 0x94, 0x11, 0x7e, 0xa8, 0xca, 0x56, 0xa0, 0xfd, - 0x4b, 0xba, 0x7c, 0x0a, 0xa4, 0x34, 0x01, 0xad, 0xf4, 0x37, 0x4f, 0x38, 0x33, 0x9f, 0x71, 0xdc, - 0xc4, 0x4c, 0x96, 0xb0, 0x8a, 0x86, 0xe5, 0x8d, 0xd2, 0x44, 0xe3, 0x18, 0xcb, 0x81, 0xa6, 0x7c, - 0xaf, 0x8e, 0xfb, 0x41, 0x6e, 0xc5, 0x82, 0xf0, 0x51, 0xb7, 0x0f, 0x23, 0x9b, 0x77, 0xed, 0x9a, - 0x06, 0x6b, 0x77, 0x7c, 0x8e, 0xc4, 0xdf, 0x50, 0xa0, 0xd2, 0x81, 0x3e, 0x65, 0xbe, 0xe5, 0x51, - 0x79, 0x93, 0x24, 0x8e, 0xb3, 0xb5, 0x25, 0x48, 0x76, 0x0e, 0x75, 0x94, 0xef, 0x9a, 0x9d, 0xc7, - 0x95, 0x08, 0xca, 0x35, 0x6b, 0x73, 0xbc, 0x4b, 0x93, 0x7a, 0x93, 0x55, 0x2d, 0xe4, 0x5f, 0xcf, - 0x11, 0x31, 0x94, 0xb2, 0x5a, 0x05, 0x80, 0xd7, 0x59, 0x79, 0x14, 0x8a, 0x2a, 0xb9, 0xd7, 0x3d, - 0x33, 0x69, 0xa9, 0xab, 0xaa, 0xb8, 0x4c, 0x73, 0xb6, 0x71, 0x2c, 0x6f, 0x31, 0x82, 0x03, 0x6d, - 0x30, 0x82, 0x03, 0x69, 0x02, 0x01, 0x01, 0x30, 0x81, 0xa4, 0x30, 0x81, 0x96, 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, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, - 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, - 0x04, 0x0b, 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, - 0x6e, 0x65, 0x72, 0x02, 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, 0x30, 0x0d, - 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa0, 0x81, 0x9a, - 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, 0x35, 0x31, 0x31, 0x30, - 0x34, 0x30, 0x31, 0x35, 0x36, 0x34, 0x30, 0x5a, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x22, 0x04, 0x20, 0x30, 0x9e, 0x11, 0x91, 0x83, 0x14, 0xd8, - 0xb9, 0xd6, 0x24, 0x8e, 0x04, 0x7e, 0x31, 0xa7, 0x66, 0xf7, 0x3c, 0x96, 0xc6, 0x23, 0x60, 0x2e, - 0xec, 0x9e, 0x0c, 0xda, 0xab, 0x25, 0x58, 0x02, 0xf2, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, - 0x86, 0xf7, 0x63, 0x64, 0x09, 0x01, 0x31, 0x22, 0x04, 0x20, 0x2e, 0xd0, 0xd3, 0x8f, 0xfd, 0xab, - 0xc6, 0x13, 0xc8, 0x7c, 0x7b, 0x3c, 0x05, 0x16, 0xfb, 0x44, 0x66, 0x40, 0xaf, 0xe3, 0x87, 0xa0, - 0x4e, 0x80, 0xf4, 0xf3, 0x5d, 0xd2, 0x68, 0x08, 0x58, 0xe6, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x02, 0x00, 0x89, 0xd3, 0x00, - 0x9b, 0xd0, 0x99, 0x21, 0x21, 0x47, 0xff, 0xa3, 0x4c, 0xef, 0xa7, 0x6e, 0x03, 0x1e, 0xbf, 0x6d, - 0x10, 0x3e, 0xf7, 0x36, 0x7e, 0x98, 0xb4, 0xb6, 0x74, 0xa0, 0xa6, 0x2c, 0x83, 0x33, 0xec, 0xeb, - 0xb5, 0x69, 0x3b, 0x10, 0x80, 0x60, 0x2b, 0xf4, 0x71, 0x84, 0x2a, 0x22, 0xfa, 0xbe, 0x51, 0x3d, - 0x69, 0xdc, 0x2b, 0x94, 0xf6, 0x8a, 0x82, 0xee, 0x88, 0xa3, 0xa4, 0x8a, 0x4d, 0x13, 0xee, 0x4b, - 0xf2, 0xd0, 0xef, 0x3a, 0x2d, 0xe0, 0x3e, 0x52, 0xe9, 0x75, 0xf3, 0xf1, 0x8a, 0xc6, 0x68, 0xab, - 0x5f, 0x97, 0x7c, 0xef, 0x2e, 0x06, 0xe4, 0x53, 0x2e, 0xa5, 0x20, 0x8b, 0x8a, 0x1f, 0x0b, 0x8a, - 0xb2, 0x0e, 0xe0, 0x77, 0xbf, 0x4d, 0x0f, 0x45, 0x15, 0x7f, 0x03, 0xdc, 0x0a, 0x5c, 0xcc, 0x88, - 0x49, 0x0b, 0x19, 0xde, 0xd8, 0xdd, 0x62, 0xc6, 0xad, 0x77, 0xaa, 0x37, 0x19, 0x31, 0x6d, 0x57, - 0x7f, 0x29, 0xc1, 0xe2, 0x7a, 0x15, 0xf9, 0xb9, 0xa5, 0xe2, 0xf3, 0xeb, 0x3f, 0x27, 0x5d, 0xac, - 0x02, 0xb8, 0xf7, 0x6d, 0xfe, 0x0f, 0x22, 0x89, 0xe3, 0x5d, 0xcc, 0xf3, 0x6a, 0x8f, 0x1a, 0xe5, - 0x94, 0xfd, 0xad, 0x9a, 0xc2, 0x5d, 0xb5, 0x1b, 0x48, 0xd8, 0x0b, 0x77, 0x9c, 0x27, 0x24, 0x55, - 0xf3, 0x8f, 0x5b, 0x7e, 0x0a, 0x73, 0x35, 0xb4, 0x6c, 0xc7, 0x84, 0xc3, 0x0b, 0x22, 0x57, 0x4d, - 0xff, 0x45, 0x4d, 0x78, 0xa7, 0xd0, 0x7d, 0xcf, 0x74, 0x5c, 0xe8, 0xa6, 0x26, 0x76, 0xda, 0xf1, - 0x4f, 0x75, 0x89, 0xd1, 0x6c, 0x7e, 0x52, 0x8c, 0x6e, 0xa8, 0x6e, 0x4c, 0x5b, 0x54, 0x94, 0x35, - 0x92, 0xec, 0x22, 0x5c, 0xdd, 0x97, 0x41, 0xef, 0x9f, 0x6d, 0xa2, 0x63, 0xaa, 0x22, 0x81, 0xab, - 0xfa, 0x0d, 0x2d, 0xed, 0xe6, 0x45, 0xe4, 0x2a, 0x51, 0x1d, 0xa6, 0x8d, 0x24, 0x99, 0xda, 0xb6, - 0xe3, 0xeb, 0x56, 0xf8, 0x6d, 0xe7, 0xbf, 0x14, 0xfa, 0x41, 0x82, 0x93, 0x28, 0xb0, 0x3f, 0x83, - 0x3a, 0x10, 0x79, 0x18, 0x4f, 0x21, 0xc7, 0xd1, 0x5f, 0x80, 0x77, 0x98, 0x0e, 0x26, 0xdd, 0x36, - 0xc7, 0xc6, 0x6b, 0xd2, 0x42, 0xd8, 0xa1, 0xfc, 0x69, 0x90, 0xa6, 0xea, 0xe6, 0xf2, 0x5b, 0x78, - 0xb7, 0x27, 0xe2, 0x13, 0xc2, 0xe7, 0xdf, 0x37, 0x30, 0x94, 0xaf, 0xbf, 0x88, 0x63, 0x3d, 0xad, - 0xfc, 0xdb, 0xf4, 0x5f, 0x5c, 0x4b, 0x07, 0x36, 0xc2, 0xc2, 0xca, 0xe3, 0x3d, 0xd9, 0x51, 0x88, - 0x37, 0xb5, 0xd6, 0x36, 0x63, 0x42, 0x8b, 0xd3, 0x86, 0xc3, 0xc0, 0x1c, 0x08, 0x2c, 0x5c, 0x93, - 0x21, 0x3e, 0x7a, 0x54, 0x21, 0xa4, 0xbc, 0x78, 0xdc, 0x41, 0x78, 0x18, 0x83, 0xf6, 0x4d, 0x2d, - 0x3a, 0xa1, 0xf3, 0xd2, 0x3e, 0x31, 0x91, 0x6f, 0xf9, 0xd3, 0xd6, 0xe1, 0xef, 0x83, 0xd7, 0x59, - 0xc9, 0xa3, 0x36, 0xcc, 0x26, 0xfd, 0x7c, 0x93, 0x0a, 0x4e, 0xae, 0x45, 0x4b, 0xb0, 0x58, 0xd0, - 0xb0, 0xca, 0x70, 0x35, 0x2f, 0x63, 0x28, 0x9d, 0x5a, 0xc8, 0x02, 0xf9, 0x8b, 0xaa, 0xcf, 0x6d, - 0x8b, 0xbb, 0xb5, 0xf6, 0x44, 0xe4, 0xcb, 0x3d, 0xbe, 0xd2, 0x70, 0x2d, 0xb3, 0xe9, 0x05, 0x6c, - 0xfe, 0x41, 0xa3, 0x05, 0xec, 0xe4, 0xf1, 0x9e, 0x37, 0x04, 0xd1, 0x9a, 0x60, 0xf9, 0x95, 0xc4, - 0x11, 0xb3, 0xbf, 0x17, 0xa4, 0x72, 0x2a, 0x03, 0x2d, 0x9a, 0x2b, 0xed, 0x97, 0xc9, 0x29, 0x05, - 0x23, 0xbb, 0xd2, 0xfe, 0x0b, 0x91, 0x5b, 0x93, 0x3f, 0x93, 0x10, 0x69, 0xcb, 0x92, 0x14, 0x8c, - 0xd4, 0xf3, 0x4f, 0x51, 0xc4, 0x78, 0x52, 0xc1, 0xea, 0x20, 0xa9, 0x16, 0x9b, 0x51, 0xb3, 0x69, - 0xf7, 0x92, 0xea, 0x6e, 0x94, 0x53, 0xc8, 0xf0, 0xd1, 0x24, 0x38, 0x3a, 0x1d, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00 -}; - -/* - * Invalid CMS message on content with hash agility attribute. - * Only the hash agility attribute value has been changed from the valid message. - */ -uint8_t invalid_message[] = { - 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, 0x00, 0x00, 0xa0, 0x82, 0x06, 0xb4, 0x30, 0x82, 0x06, 0xb0, 0x30, 0x82, 0x04, 0x98, - 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, - 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, - 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 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, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, - 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, - 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 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, 0x18, - 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, - 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x31, 0x30, - 0x32, 0x39, 0x32, 0x31, 0x35, 0x35, 0x35, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x30, 0x32, - 0x38, 0x32, 0x31, 0x35, 0x35, 0x35, 0x38, 0x5a, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, - 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, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, - 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, - 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, - 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, - 0x72, 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, 0xc4, 0x2a, 0x38, 0x4b, 0xdd, 0x1c, 0xc7, 0x39, 0x47, 0xba, 0xbc, 0x5d, 0xd2, 0xcc, - 0x6e, 0x9e, 0x2c, 0x81, 0x26, 0x18, 0x59, 0x18, 0xb8, 0x45, 0x0c, 0xde, 0x5b, 0xbc, 0x25, 0xa4, - 0x78, 0x0b, 0x16, 0x3d, 0x3d, 0x10, 0x34, 0x48, 0xcf, 0x1f, 0x40, 0xaa, 0x4b, 0xb5, 0xbc, 0xf0, - 0x81, 0x5e, 0xa8, 0x72, 0xed, 0x6a, 0x8c, 0xf0, 0x4a, 0x9a, 0x80, 0x09, 0x3b, 0x89, 0xed, 0xad, - 0x2b, 0xb5, 0x5b, 0x0f, 0xe4, 0x3f, 0x6b, 0xc5, 0x15, 0x33, 0x5e, 0xdd, 0xa4, 0xac, 0x2f, 0xa5, - 0x13, 0x0f, 0x3c, 0xfc, 0xd8, 0xca, 0xb8, 0x88, 0x67, 0x75, 0xc4, 0x9a, 0x4c, 0x18, 0x9a, 0x38, - 0x68, 0xaa, 0x4c, 0x94, 0x35, 0xed, 0xa4, 0x0b, 0x80, 0x2b, 0xa9, 0x4d, 0xa4, 0x57, 0x22, 0xfc, - 0xd2, 0xc3, 0x12, 0x0b, 0x8a, 0x3c, 0xd7, 0x6d, 0x8b, 0x47, 0x4f, 0x24, 0xe5, 0xea, 0x1b, 0x03, - 0x78, 0xa2, 0x12, 0x36, 0x3f, 0x92, 0x16, 0x36, 0xff, 0xc5, 0xaf, 0xc3, 0xec, 0x4b, 0x6c, 0x23, - 0x04, 0x1b, 0xa9, 0xce, 0x3a, 0xa1, 0xa5, 0xe0, 0x54, 0x13, 0x43, 0x13, 0x29, 0x95, 0x5b, 0xcb, - 0x97, 0x74, 0x01, 0xbc, 0x3c, 0xb8, 0xa1, 0xb0, 0xf3, 0x3c, 0xfa, 0x21, 0x7a, 0x89, 0x90, 0x2b, - 0x1f, 0x20, 0x3f, 0xc1, 0x22, 0xda, 0x8d, 0xa5, 0x30, 0x57, 0x6d, 0xd4, 0x40, 0x99, 0x08, 0x0d, - 0xef, 0x36, 0x16, 0xa6, 0xec, 0xcf, 0x26, 0x78, 0x7c, 0x77, 0x7e, 0x50, 0x2a, 0xe3, 0xdf, 0x28, - 0xff, 0xd0, 0xc7, 0x0e, 0x8b, 0x6b, 0x56, 0x62, 0x53, 0x37, 0x5a, 0x1a, 0x85, 0x50, 0xec, 0x6a, - 0x6b, 0x2e, 0xd1, 0x35, 0x6e, 0x5d, 0x92, 0x30, 0x39, 0x82, 0x40, 0x7b, 0x6d, 0x89, 0x5b, 0x4d, - 0x30, 0x6d, 0x2e, 0x68, 0x16, 0x24, 0x63, 0x32, 0x24, 0xdc, 0x3e, 0x5b, 0x4a, 0xc4, 0x41, 0xfc, - 0x76, 0x07, 0xe6, 0xa3, 0x1b, 0x18, 0xec, 0x59, 0xed, 0x13, 0x0b, 0x2d, 0xe9, 0x86, 0x89, 0x2c, - 0x0a, 0xb0, 0x19, 0x97, 0x4d, 0x1b, 0xfb, 0xd4, 0xef, 0x54, 0xcd, 0xe5, 0xb2, 0x22, 0x70, 0x3a, - 0x50, 0x03, 0xaa, 0xc0, 0xf8, 0xb4, 0x8e, 0x16, 0xd8, 0x2a, 0xc1, 0xd1, 0x2d, 0xa0, 0x27, 0x59, - 0x63, 0x70, 0xc3, 0x74, 0x14, 0xee, 0xde, 0xa9, 0xd9, 0x73, 0xdb, 0x16, 0x6d, 0xef, 0x7f, 0x50, - 0xb6, 0xd2, 0x54, 0x0d, 0x4d, 0x31, 0x5f, 0x23, 0x2c, 0xfd, 0x8f, 0x67, 0x7c, 0xe9, 0xaa, 0x1c, - 0x29, 0xf5, 0x83, 0x1b, 0x2b, 0x0e, 0x66, 0x0e, 0x5c, 0xfe, 0xc9, 0x38, 0xb0, 0x90, 0xfa, 0x31, - 0x4c, 0xb1, 0xef, 0xea, 0xd0, 0x47, 0x17, 0xde, 0x45, 0xc1, 0x93, 0xef, 0xba, 0xde, 0x9f, 0x69, - 0xc7, 0xa6, 0x14, 0x23, 0xb1, 0x8b, 0xaa, 0xbf, 0x61, 0x37, 0x57, 0x11, 0x6a, 0xb2, 0xf7, 0xec, - 0x52, 0x7e, 0x65, 0x80, 0xff, 0xa1, 0xa8, 0x20, 0x7e, 0x0b, 0xae, 0x21, 0xfa, 0xe8, 0x20, 0x52, - 0x93, 0xc5, 0xe9, 0x39, 0x5b, 0x8e, 0xab, 0xef, 0x86, 0xa6, 0xd8, 0x43, 0x7e, 0xa9, 0x5c, 0x6d, - 0x91, 0xd8, 0x5c, 0xa4, 0x2a, 0xed, 0x26, 0xa8, 0x1b, 0xaa, 0x3b, 0xfa, 0x86, 0x75, 0x37, 0xc6, - 0x70, 0x12, 0x2b, 0x8c, 0x55, 0x96, 0x76, 0x04, 0xf6, 0xe3, 0xf9, 0xe2, 0x0d, 0x2e, 0xe0, 0x23, - 0xdf, 0xfa, 0xe0, 0x9c, 0x11, 0xf9, 0xd4, 0x51, 0x05, 0xed, 0x2b, 0x3f, 0xa3, 0x3f, 0xa2, 0xe6, - 0x30, 0x81, 0x17, 0x00, 0x8f, 0x15, 0x91, 0xfb, 0x21, 0x62, 0xf4, 0xff, 0x93, 0x1a, 0x2e, 0xfe, - 0x1a, 0xcb, 0x93, 0x3d, 0xd4, 0x6e, 0x3a, 0xb8, 0x70, 0xdf, 0x93, 0xb4, 0x02, 0xc4, 0x8c, 0x54, - 0x92, 0xde, 0xa7, 0x32, 0x65, 0x1c, 0x85, 0x95, 0x34, 0xf8, 0x8d, 0x06, 0x5b, 0x7d, 0x72, 0x00, - 0xd8, 0x31, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xfe, 0x30, 0x81, 0xfb, 0x30, 0x1d, 0x06, - 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xee, 0x16, 0xde, 0xfd, 0x11, 0xd3, 0x88, 0xfb, - 0xef, 0xfb, 0x19, 0x23, 0x8a, 0x23, 0x85, 0x7b, 0xe8, 0x41, 0x26, 0xa1, 0x30, 0x81, 0xcb, 0x06, - 0x03, 0x55, 0x1d, 0x23, 0x04, 0x81, 0xc3, 0x30, 0x81, 0xc0, 0x80, 0x14, 0xee, 0x16, 0xde, 0xfd, - 0x11, 0xd3, 0x88, 0xfb, 0xef, 0xfb, 0x19, 0x23, 0x8a, 0x23, 0x85, 0x7b, 0xe8, 0x41, 0x26, 0xa1, - 0xa1, 0x81, 0x9c, 0xa4, 0x81, 0x99, 0x30, 0x81, 0x96, 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, - 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, - 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, - 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x82, - 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, - 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x0c, 0x0f, 0x08, 0x79, - 0x6f, 0x56, 0x21, 0xdf, 0xdd, 0xf5, 0x97, 0x8d, 0xdc, 0x97, 0x06, 0xfb, 0x2e, 0xe0, 0x21, 0x60, - 0xc3, 0x02, 0xf4, 0x41, 0x79, 0x79, 0xc2, 0x23, 0x9a, 0x8a, 0x54, 0x2e, 0x66, 0xab, 0xc0, 0x21, - 0xf6, 0x9f, 0xc5, 0x2e, 0x41, 0xb8, 0xa3, 0x32, 0x9f, 0x3d, 0x4e, 0xf4, 0x83, 0xee, 0xcc, 0x60, - 0xf6, 0x82, 0x3d, 0xb4, 0xa9, 0x9d, 0xcd, 0xa0, 0x02, 0x89, 0xb0, 0x32, 0x1b, 0xb5, 0x7c, 0xf4, - 0x8f, 0xbc, 0x9b, 0x24, 0xc2, 0xe2, 0x81, 0xd6, 0x6f, 0x0e, 0x22, 0x5e, 0x50, 0xd9, 0x5b, 0x2e, - 0x89, 0xbf, 0xa4, 0xfe, 0xa8, 0xc2, 0x9a, 0xf4, 0xec, 0x70, 0x66, 0x01, 0x4b, 0x50, 0x30, 0x97, - 0x0a, 0xcc, 0x9f, 0xac, 0xe4, 0x89, 0x1c, 0x8d, 0x88, 0x0d, 0xdb, 0x21, 0xbd, 0x2f, 0x24, 0x8e, - 0x83, 0xf9, 0xe6, 0x71, 0xed, 0x71, 0x26, 0x31, 0x99, 0x9d, 0x04, 0xeb, 0x34, 0xea, 0x6d, 0x65, - 0xb8, 0x02, 0x83, 0x57, 0x78, 0x36, 0x3a, 0x0b, 0xc7, 0x41, 0x63, 0xb5, 0xf6, 0x1c, 0xd2, 0x01, - 0x86, 0x04, 0x58, 0x40, 0x3e, 0x91, 0x98, 0x39, 0x72, 0x75, 0x11, 0xca, 0x14, 0x73, 0x90, 0x34, - 0x8b, 0x21, 0xa4, 0xd0, 0xba, 0xe7, 0x33, 0x03, 0x22, 0x0f, 0x1a, 0xf7, 0x10, 0x2b, 0x69, 0x4c, - 0x73, 0xef, 0x04, 0x18, 0xf9, 0xe1, 0x11, 0xa8, 0xb8, 0x1b, 0x57, 0x0b, 0x03, 0x10, 0x1c, 0xce, - 0x13, 0xca, 0xe4, 0xde, 0x8c, 0xf4, 0xcf, 0xf5, 0xb7, 0x80, 0x3e, 0xbc, 0x1f, 0x51, 0x9b, 0x20, - 0x8c, 0xb0, 0x2d, 0x67, 0x1c, 0x84, 0x25, 0x4c, 0x8b, 0xd3, 0xa7, 0x09, 0x8e, 0x60, 0xe2, 0x99, - 0x0d, 0x10, 0x12, 0x14, 0xfc, 0x17, 0x62, 0x69, 0xcd, 0xa4, 0x64, 0xf0, 0x7e, 0xba, 0xe0, 0xc9, - 0x51, 0x78, 0xf8, 0xb4, 0x0d, 0x7d, 0xb8, 0xa0, 0xee, 0x9c, 0x9e, 0x84, 0xd5, 0xa4, 0x02, 0xe5, - 0x7a, 0x1c, 0x65, 0xe1, 0x20, 0xfb, 0x4d, 0x61, 0x7a, 0x47, 0x25, 0x06, 0x95, 0x17, 0x62, 0x60, - 0x4b, 0x0b, 0xc6, 0xca, 0xa7, 0x35, 0x8f, 0xd4, 0x63, 0x3e, 0x5e, 0x92, 0x1a, 0x08, 0x7c, 0x6b, - 0x15, 0x41, 0x95, 0x76, 0x7d, 0x39, 0x28, 0xec, 0x3e, 0x1f, 0x49, 0xd5, 0xd5, 0x89, 0xf9, 0x5f, - 0x14, 0x02, 0x2f, 0x27, 0xb0, 0x39, 0xba, 0xf7, 0x91, 0x53, 0x75, 0x77, 0xab, 0x88, 0x40, 0x1d, - 0x77, 0xaf, 0x79, 0xfd, 0xdc, 0xac, 0x99, 0x82, 0xf2, 0x46, 0x05, 0x97, 0x60, 0xef, 0x7b, 0xf5, - 0x34, 0x38, 0xbf, 0xd7, 0x42, 0x3e, 0x8b, 0x5a, 0x4a, 0x0c, 0x22, 0x7e, 0x4d, 0x4e, 0xf6, 0xf7, - 0xcc, 0x6e, 0x31, 0x33, 0x1a, 0x84, 0xbe, 0x07, 0xf7, 0xe8, 0xe2, 0x43, 0x00, 0x54, 0x4a, 0x38, - 0xda, 0x98, 0xe3, 0x84, 0xb2, 0xd0, 0x76, 0x79, 0x94, 0x11, 0x7e, 0xa8, 0xca, 0x56, 0xa0, 0xfd, - 0x4b, 0xba, 0x7c, 0x0a, 0xa4, 0x34, 0x01, 0xad, 0xf4, 0x37, 0x4f, 0x38, 0x33, 0x9f, 0x71, 0xdc, - 0xc4, 0x4c, 0x96, 0xb0, 0x8a, 0x86, 0xe5, 0x8d, 0xd2, 0x44, 0xe3, 0x18, 0xcb, 0x81, 0xa6, 0x7c, - 0xaf, 0x8e, 0xfb, 0x41, 0x6e, 0xc5, 0x82, 0xf0, 0x51, 0xb7, 0x0f, 0x23, 0x9b, 0x77, 0xed, 0x9a, - 0x06, 0x6b, 0x77, 0x7c, 0x8e, 0xc4, 0xdf, 0x50, 0xa0, 0xd2, 0x81, 0x3e, 0x65, 0xbe, 0xe5, 0x51, - 0x79, 0x93, 0x24, 0x8e, 0xb3, 0xb5, 0x25, 0x48, 0x76, 0x0e, 0x75, 0x94, 0xef, 0x9a, 0x9d, 0xc7, - 0x95, 0x08, 0xca, 0x35, 0x6b, 0x73, 0xbc, 0x4b, 0x93, 0x7a, 0x93, 0x55, 0x2d, 0xe4, 0x5f, 0xcf, - 0x11, 0x31, 0x94, 0xb2, 0x5a, 0x05, 0x80, 0xd7, 0x59, 0x79, 0x14, 0x8a, 0x2a, 0xb9, 0xd7, 0x3d, - 0x33, 0x69, 0xa9, 0xab, 0xaa, 0xb8, 0x4c, 0x73, 0xb6, 0x71, 0x2c, 0x6f, 0x31, 0x82, 0x03, 0x6d, - 0x30, 0x82, 0x03, 0x69, 0x02, 0x01, 0x01, 0x30, 0x81, 0xa4, 0x30, 0x81, 0x96, 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, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, - 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, - 0x04, 0x0b, 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, - 0x6e, 0x65, 0x72, 0x02, 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, 0x30, 0x0d, - 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa0, 0x81, 0x9a, - 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, 0x35, 0x31, 0x31, 0x30, - 0x34, 0x30, 0x31, 0x35, 0x36, 0x34, 0x30, 0x5a, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x22, 0x04, 0x20, 0x30, 0x9e, 0x11, 0x91, 0x83, 0x14, 0xd8, - 0xb9, 0xd6, 0x24, 0x8e, 0x04, 0x7e, 0x31, 0xa7, 0x66, 0xf7, 0x3c, 0x96, 0xc6, 0x23, 0x60, 0x2e, - 0xec, 0x9e, 0x0c, 0xda, 0xab, 0x25, 0x58, 0x02, 0xf2, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, - 0x86, 0xf7, 0x63, 0x64, 0x09, 0x01, 0x31, 0x22, 0x04, 0x20, 0x2e, 0xd0, 0xd0, 0x8f, 0xfd, 0xab, - 0xc6, 0x13, 0xc8, 0x7c, 0x7b, 0x3c, 0x05, 0x16, 0xfb, 0x44, 0x66, 0x40, 0xaf, 0xe3, 0x87, 0xa0, - 0x4e, 0x80, 0xf4, 0xf3, 0x5d, 0xd2, 0x68, 0x08, 0x58, 0xe6, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x02, 0x00, 0x89, 0xd3, 0x00, - 0x9b, 0xd0, 0x99, 0x21, 0x21, 0x47, 0xff, 0xa3, 0x4c, 0xef, 0xa7, 0x6e, 0x03, 0x1e, 0xbf, 0x6d, - 0x10, 0x3e, 0xf7, 0x36, 0x7e, 0x98, 0xb4, 0xb6, 0x74, 0xa0, 0xa6, 0x2c, 0x83, 0x33, 0xec, 0xeb, - 0xb5, 0x69, 0x3b, 0x10, 0x80, 0x60, 0x2b, 0xf4, 0x71, 0x84, 0x2a, 0x22, 0xfa, 0xbe, 0x51, 0x3d, - 0x69, 0xdc, 0x2b, 0x94, 0xf6, 0x8a, 0x82, 0xee, 0x88, 0xa3, 0xa4, 0x8a, 0x4d, 0x13, 0xee, 0x4b, - 0xf2, 0xd0, 0xef, 0x3a, 0x2d, 0xe0, 0x3e, 0x52, 0xe9, 0x75, 0xf3, 0xf1, 0x8a, 0xc6, 0x68, 0xab, - 0x5f, 0x97, 0x7c, 0xef, 0x2e, 0x06, 0xe4, 0x53, 0x2e, 0xa5, 0x20, 0x8b, 0x8a, 0x1f, 0x0b, 0x8a, - 0xb2, 0x0e, 0xe0, 0x77, 0xbf, 0x4d, 0x0f, 0x45, 0x15, 0x7f, 0x03, 0xdc, 0x0a, 0x5c, 0xcc, 0x88, - 0x49, 0x0b, 0x19, 0xde, 0xd8, 0xdd, 0x62, 0xc6, 0xad, 0x77, 0xaa, 0x37, 0x19, 0x31, 0x6d, 0x57, - 0x7f, 0x29, 0xc1, 0xe2, 0x7a, 0x15, 0xf9, 0xb9, 0xa5, 0xe2, 0xf3, 0xeb, 0x3f, 0x27, 0x5d, 0xac, - 0x02, 0xb8, 0xf7, 0x6d, 0xfe, 0x0f, 0x22, 0x89, 0xe3, 0x5d, 0xcc, 0xf3, 0x6a, 0x8f, 0x1a, 0xe5, - 0x94, 0xfd, 0xad, 0x9a, 0xc2, 0x5d, 0xb5, 0x1b, 0x48, 0xd8, 0x0b, 0x77, 0x9c, 0x27, 0x24, 0x55, - 0xf3, 0x8f, 0x5b, 0x7e, 0x0a, 0x73, 0x35, 0xb4, 0x6c, 0xc7, 0x84, 0xc3, 0x0b, 0x22, 0x57, 0x4d, - 0xff, 0x45, 0x4d, 0x78, 0xa7, 0xd0, 0x7d, 0xcf, 0x74, 0x5c, 0xe8, 0xa6, 0x26, 0x76, 0xda, 0xf1, - 0x4f, 0x75, 0x89, 0xd1, 0x6c, 0x7e, 0x52, 0x8c, 0x6e, 0xa8, 0x6e, 0x4c, 0x5b, 0x54, 0x94, 0x35, - 0x92, 0xec, 0x22, 0x5c, 0xdd, 0x97, 0x41, 0xef, 0x9f, 0x6d, 0xa2, 0x63, 0xaa, 0x22, 0x81, 0xab, - 0xfa, 0x0d, 0x2d, 0xed, 0xe6, 0x45, 0xe4, 0x2a, 0x51, 0x1d, 0xa6, 0x8d, 0x24, 0x99, 0xda, 0xb6, - 0xe3, 0xeb, 0x56, 0xf8, 0x6d, 0xe7, 0xbf, 0x14, 0xfa, 0x41, 0x82, 0x93, 0x28, 0xb0, 0x3f, 0x83, - 0x3a, 0x10, 0x79, 0x18, 0x4f, 0x21, 0xc7, 0xd1, 0x5f, 0x80, 0x77, 0x98, 0x0e, 0x26, 0xdd, 0x36, - 0xc7, 0xc6, 0x6b, 0xd2, 0x42, 0xd8, 0xa1, 0xfc, 0x69, 0x90, 0xa6, 0xea, 0xe6, 0xf2, 0x5b, 0x78, - 0xb7, 0x27, 0xe2, 0x13, 0xc2, 0xe7, 0xdf, 0x37, 0x30, 0x94, 0xaf, 0xbf, 0x88, 0x63, 0x3d, 0xad, - 0xfc, 0xdb, 0xf4, 0x5f, 0x5c, 0x4b, 0x07, 0x36, 0xc2, 0xc2, 0xca, 0xe3, 0x3d, 0xd9, 0x51, 0x88, - 0x37, 0xb5, 0xd6, 0x36, 0x63, 0x42, 0x8b, 0xd3, 0x86, 0xc3, 0xc0, 0x1c, 0x08, 0x2c, 0x5c, 0x93, - 0x21, 0x3e, 0x7a, 0x54, 0x21, 0xa4, 0xbc, 0x78, 0xdc, 0x41, 0x78, 0x18, 0x83, 0xf6, 0x4d, 0x2d, - 0x3a, 0xa1, 0xf3, 0xd2, 0x3e, 0x31, 0x91, 0x6f, 0xf9, 0xd3, 0xd6, 0xe1, 0xef, 0x83, 0xd7, 0x59, - 0xc9, 0xa3, 0x36, 0xcc, 0x26, 0xfd, 0x7c, 0x93, 0x0a, 0x4e, 0xae, 0x45, 0x4b, 0xb0, 0x58, 0xd0, - 0xb0, 0xca, 0x70, 0x35, 0x2f, 0x63, 0x28, 0x9d, 0x5a, 0xc8, 0x02, 0xf9, 0x8b, 0xaa, 0xcf, 0x6d, - 0x8b, 0xbb, 0xb5, 0xf6, 0x44, 0xe4, 0xcb, 0x3d, 0xbe, 0xd2, 0x70, 0x2d, 0xb3, 0xe9, 0x05, 0x6c, - 0xfe, 0x41, 0xa3, 0x05, 0xec, 0xe4, 0xf1, 0x9e, 0x37, 0x04, 0xd1, 0x9a, 0x60, 0xf9, 0x95, 0xc4, - 0x11, 0xb3, 0xbf, 0x17, 0xa4, 0x72, 0x2a, 0x03, 0x2d, 0x9a, 0x2b, 0xed, 0x97, 0xc9, 0x29, 0x05, - 0x23, 0xbb, 0xd2, 0xfe, 0x0b, 0x91, 0x5b, 0x93, 0x3f, 0x93, 0x10, 0x69, 0xcb, 0x92, 0x14, 0x8c, - 0xd4, 0xf3, 0x4f, 0x51, 0xc4, 0x78, 0x52, 0xc1, 0xea, 0x20, 0xa9, 0x16, 0x9b, 0x51, 0xb3, 0x69, - 0xf7, 0x92, 0xea, 0x6e, 0x94, 0x53, 0xc8, 0xf0, 0xd1, 0x24, 0x38, 0x3a, 0x1d, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00 -}; - -/* Valid CMS message with no hash agility attribute */ -unsigned char valid_no_attr[] = { - 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, 0x00, 0x00, 0xa0, 0x82, 0x06, 0xb4, 0x30, 0x82, 0x06, 0xb0, 0x30, 0x82, 0x04, 0x98, - 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, - 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, - 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 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, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, - 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, - 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 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, 0x18, - 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, - 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x31, 0x30, - 0x32, 0x39, 0x32, 0x31, 0x35, 0x35, 0x35, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x30, 0x32, - 0x38, 0x32, 0x31, 0x35, 0x35, 0x35, 0x38, 0x5a, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, - 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, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, - 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, - 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, - 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, - 0x72, 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, 0xc4, 0x2a, 0x38, 0x4b, 0xdd, 0x1c, 0xc7, 0x39, 0x47, 0xba, 0xbc, 0x5d, 0xd2, 0xcc, - 0x6e, 0x9e, 0x2c, 0x81, 0x26, 0x18, 0x59, 0x18, 0xb8, 0x45, 0x0c, 0xde, 0x5b, 0xbc, 0x25, 0xa4, - 0x78, 0x0b, 0x16, 0x3d, 0x3d, 0x10, 0x34, 0x48, 0xcf, 0x1f, 0x40, 0xaa, 0x4b, 0xb5, 0xbc, 0xf0, - 0x81, 0x5e, 0xa8, 0x72, 0xed, 0x6a, 0x8c, 0xf0, 0x4a, 0x9a, 0x80, 0x09, 0x3b, 0x89, 0xed, 0xad, - 0x2b, 0xb5, 0x5b, 0x0f, 0xe4, 0x3f, 0x6b, 0xc5, 0x15, 0x33, 0x5e, 0xdd, 0xa4, 0xac, 0x2f, 0xa5, - 0x13, 0x0f, 0x3c, 0xfc, 0xd8, 0xca, 0xb8, 0x88, 0x67, 0x75, 0xc4, 0x9a, 0x4c, 0x18, 0x9a, 0x38, - 0x68, 0xaa, 0x4c, 0x94, 0x35, 0xed, 0xa4, 0x0b, 0x80, 0x2b, 0xa9, 0x4d, 0xa4, 0x57, 0x22, 0xfc, - 0xd2, 0xc3, 0x12, 0x0b, 0x8a, 0x3c, 0xd7, 0x6d, 0x8b, 0x47, 0x4f, 0x24, 0xe5, 0xea, 0x1b, 0x03, - 0x78, 0xa2, 0x12, 0x36, 0x3f, 0x92, 0x16, 0x36, 0xff, 0xc5, 0xaf, 0xc3, 0xec, 0x4b, 0x6c, 0x23, - 0x04, 0x1b, 0xa9, 0xce, 0x3a, 0xa1, 0xa5, 0xe0, 0x54, 0x13, 0x43, 0x13, 0x29, 0x95, 0x5b, 0xcb, - 0x97, 0x74, 0x01, 0xbc, 0x3c, 0xb8, 0xa1, 0xb0, 0xf3, 0x3c, 0xfa, 0x21, 0x7a, 0x89, 0x90, 0x2b, - 0x1f, 0x20, 0x3f, 0xc1, 0x22, 0xda, 0x8d, 0xa5, 0x30, 0x57, 0x6d, 0xd4, 0x40, 0x99, 0x08, 0x0d, - 0xef, 0x36, 0x16, 0xa6, 0xec, 0xcf, 0x26, 0x78, 0x7c, 0x77, 0x7e, 0x50, 0x2a, 0xe3, 0xdf, 0x28, - 0xff, 0xd0, 0xc7, 0x0e, 0x8b, 0x6b, 0x56, 0x62, 0x53, 0x37, 0x5a, 0x1a, 0x85, 0x50, 0xec, 0x6a, - 0x6b, 0x2e, 0xd1, 0x35, 0x6e, 0x5d, 0x92, 0x30, 0x39, 0x82, 0x40, 0x7b, 0x6d, 0x89, 0x5b, 0x4d, - 0x30, 0x6d, 0x2e, 0x68, 0x16, 0x24, 0x63, 0x32, 0x24, 0xdc, 0x3e, 0x5b, 0x4a, 0xc4, 0x41, 0xfc, - 0x76, 0x07, 0xe6, 0xa3, 0x1b, 0x18, 0xec, 0x59, 0xed, 0x13, 0x0b, 0x2d, 0xe9, 0x86, 0x89, 0x2c, - 0x0a, 0xb0, 0x19, 0x97, 0x4d, 0x1b, 0xfb, 0xd4, 0xef, 0x54, 0xcd, 0xe5, 0xb2, 0x22, 0x70, 0x3a, - 0x50, 0x03, 0xaa, 0xc0, 0xf8, 0xb4, 0x8e, 0x16, 0xd8, 0x2a, 0xc1, 0xd1, 0x2d, 0xa0, 0x27, 0x59, - 0x63, 0x70, 0xc3, 0x74, 0x14, 0xee, 0xde, 0xa9, 0xd9, 0x73, 0xdb, 0x16, 0x6d, 0xef, 0x7f, 0x50, - 0xb6, 0xd2, 0x54, 0x0d, 0x4d, 0x31, 0x5f, 0x23, 0x2c, 0xfd, 0x8f, 0x67, 0x7c, 0xe9, 0xaa, 0x1c, - 0x29, 0xf5, 0x83, 0x1b, 0x2b, 0x0e, 0x66, 0x0e, 0x5c, 0xfe, 0xc9, 0x38, 0xb0, 0x90, 0xfa, 0x31, - 0x4c, 0xb1, 0xef, 0xea, 0xd0, 0x47, 0x17, 0xde, 0x45, 0xc1, 0x93, 0xef, 0xba, 0xde, 0x9f, 0x69, - 0xc7, 0xa6, 0x14, 0x23, 0xb1, 0x8b, 0xaa, 0xbf, 0x61, 0x37, 0x57, 0x11, 0x6a, 0xb2, 0xf7, 0xec, - 0x52, 0x7e, 0x65, 0x80, 0xff, 0xa1, 0xa8, 0x20, 0x7e, 0x0b, 0xae, 0x21, 0xfa, 0xe8, 0x20, 0x52, - 0x93, 0xc5, 0xe9, 0x39, 0x5b, 0x8e, 0xab, 0xef, 0x86, 0xa6, 0xd8, 0x43, 0x7e, 0xa9, 0x5c, 0x6d, - 0x91, 0xd8, 0x5c, 0xa4, 0x2a, 0xed, 0x26, 0xa8, 0x1b, 0xaa, 0x3b, 0xfa, 0x86, 0x75, 0x37, 0xc6, - 0x70, 0x12, 0x2b, 0x8c, 0x55, 0x96, 0x76, 0x04, 0xf6, 0xe3, 0xf9, 0xe2, 0x0d, 0x2e, 0xe0, 0x23, - 0xdf, 0xfa, 0xe0, 0x9c, 0x11, 0xf9, 0xd4, 0x51, 0x05, 0xed, 0x2b, 0x3f, 0xa3, 0x3f, 0xa2, 0xe6, - 0x30, 0x81, 0x17, 0x00, 0x8f, 0x15, 0x91, 0xfb, 0x21, 0x62, 0xf4, 0xff, 0x93, 0x1a, 0x2e, 0xfe, - 0x1a, 0xcb, 0x93, 0x3d, 0xd4, 0x6e, 0x3a, 0xb8, 0x70, 0xdf, 0x93, 0xb4, 0x02, 0xc4, 0x8c, 0x54, - 0x92, 0xde, 0xa7, 0x32, 0x65, 0x1c, 0x85, 0x95, 0x34, 0xf8, 0x8d, 0x06, 0x5b, 0x7d, 0x72, 0x00, - 0xd8, 0x31, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xfe, 0x30, 0x81, 0xfb, 0x30, 0x1d, 0x06, - 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xee, 0x16, 0xde, 0xfd, 0x11, 0xd3, 0x88, 0xfb, - 0xef, 0xfb, 0x19, 0x23, 0x8a, 0x23, 0x85, 0x7b, 0xe8, 0x41, 0x26, 0xa1, 0x30, 0x81, 0xcb, 0x06, - 0x03, 0x55, 0x1d, 0x23, 0x04, 0x81, 0xc3, 0x30, 0x81, 0xc0, 0x80, 0x14, 0xee, 0x16, 0xde, 0xfd, - 0x11, 0xd3, 0x88, 0xfb, 0xef, 0xfb, 0x19, 0x23, 0x8a, 0x23, 0x85, 0x7b, 0xe8, 0x41, 0x26, 0xa1, - 0xa1, 0x81, 0x9c, 0xa4, 0x81, 0x99, 0x30, 0x81, 0x96, 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, - 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, - 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, - 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x82, - 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, - 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x0c, 0x0f, 0x08, 0x79, - 0x6f, 0x56, 0x21, 0xdf, 0xdd, 0xf5, 0x97, 0x8d, 0xdc, 0x97, 0x06, 0xfb, 0x2e, 0xe0, 0x21, 0x60, - 0xc3, 0x02, 0xf4, 0x41, 0x79, 0x79, 0xc2, 0x23, 0x9a, 0x8a, 0x54, 0x2e, 0x66, 0xab, 0xc0, 0x21, - 0xf6, 0x9f, 0xc5, 0x2e, 0x41, 0xb8, 0xa3, 0x32, 0x9f, 0x3d, 0x4e, 0xf4, 0x83, 0xee, 0xcc, 0x60, - 0xf6, 0x82, 0x3d, 0xb4, 0xa9, 0x9d, 0xcd, 0xa0, 0x02, 0x89, 0xb0, 0x32, 0x1b, 0xb5, 0x7c, 0xf4, - 0x8f, 0xbc, 0x9b, 0x24, 0xc2, 0xe2, 0x81, 0xd6, 0x6f, 0x0e, 0x22, 0x5e, 0x50, 0xd9, 0x5b, 0x2e, - 0x89, 0xbf, 0xa4, 0xfe, 0xa8, 0xc2, 0x9a, 0xf4, 0xec, 0x70, 0x66, 0x01, 0x4b, 0x50, 0x30, 0x97, - 0x0a, 0xcc, 0x9f, 0xac, 0xe4, 0x89, 0x1c, 0x8d, 0x88, 0x0d, 0xdb, 0x21, 0xbd, 0x2f, 0x24, 0x8e, - 0x83, 0xf9, 0xe6, 0x71, 0xed, 0x71, 0x26, 0x31, 0x99, 0x9d, 0x04, 0xeb, 0x34, 0xea, 0x6d, 0x65, - 0xb8, 0x02, 0x83, 0x57, 0x78, 0x36, 0x3a, 0x0b, 0xc7, 0x41, 0x63, 0xb5, 0xf6, 0x1c, 0xd2, 0x01, - 0x86, 0x04, 0x58, 0x40, 0x3e, 0x91, 0x98, 0x39, 0x72, 0x75, 0x11, 0xca, 0x14, 0x73, 0x90, 0x34, - 0x8b, 0x21, 0xa4, 0xd0, 0xba, 0xe7, 0x33, 0x03, 0x22, 0x0f, 0x1a, 0xf7, 0x10, 0x2b, 0x69, 0x4c, - 0x73, 0xef, 0x04, 0x18, 0xf9, 0xe1, 0x11, 0xa8, 0xb8, 0x1b, 0x57, 0x0b, 0x03, 0x10, 0x1c, 0xce, - 0x13, 0xca, 0xe4, 0xde, 0x8c, 0xf4, 0xcf, 0xf5, 0xb7, 0x80, 0x3e, 0xbc, 0x1f, 0x51, 0x9b, 0x20, - 0x8c, 0xb0, 0x2d, 0x67, 0x1c, 0x84, 0x25, 0x4c, 0x8b, 0xd3, 0xa7, 0x09, 0x8e, 0x60, 0xe2, 0x99, - 0x0d, 0x10, 0x12, 0x14, 0xfc, 0x17, 0x62, 0x69, 0xcd, 0xa4, 0x64, 0xf0, 0x7e, 0xba, 0xe0, 0xc9, - 0x51, 0x78, 0xf8, 0xb4, 0x0d, 0x7d, 0xb8, 0xa0, 0xee, 0x9c, 0x9e, 0x84, 0xd5, 0xa4, 0x02, 0xe5, - 0x7a, 0x1c, 0x65, 0xe1, 0x20, 0xfb, 0x4d, 0x61, 0x7a, 0x47, 0x25, 0x06, 0x95, 0x17, 0x62, 0x60, - 0x4b, 0x0b, 0xc6, 0xca, 0xa7, 0x35, 0x8f, 0xd4, 0x63, 0x3e, 0x5e, 0x92, 0x1a, 0x08, 0x7c, 0x6b, - 0x15, 0x41, 0x95, 0x76, 0x7d, 0x39, 0x28, 0xec, 0x3e, 0x1f, 0x49, 0xd5, 0xd5, 0x89, 0xf9, 0x5f, - 0x14, 0x02, 0x2f, 0x27, 0xb0, 0x39, 0xba, 0xf7, 0x91, 0x53, 0x75, 0x77, 0xab, 0x88, 0x40, 0x1d, - 0x77, 0xaf, 0x79, 0xfd, 0xdc, 0xac, 0x99, 0x82, 0xf2, 0x46, 0x05, 0x97, 0x60, 0xef, 0x7b, 0xf5, - 0x34, 0x38, 0xbf, 0xd7, 0x42, 0x3e, 0x8b, 0x5a, 0x4a, 0x0c, 0x22, 0x7e, 0x4d, 0x4e, 0xf6, 0xf7, - 0xcc, 0x6e, 0x31, 0x33, 0x1a, 0x84, 0xbe, 0x07, 0xf7, 0xe8, 0xe2, 0x43, 0x00, 0x54, 0x4a, 0x38, - 0xda, 0x98, 0xe3, 0x84, 0xb2, 0xd0, 0x76, 0x79, 0x94, 0x11, 0x7e, 0xa8, 0xca, 0x56, 0xa0, 0xfd, - 0x4b, 0xba, 0x7c, 0x0a, 0xa4, 0x34, 0x01, 0xad, 0xf4, 0x37, 0x4f, 0x38, 0x33, 0x9f, 0x71, 0xdc, - 0xc4, 0x4c, 0x96, 0xb0, 0x8a, 0x86, 0xe5, 0x8d, 0xd2, 0x44, 0xe3, 0x18, 0xcb, 0x81, 0xa6, 0x7c, - 0xaf, 0x8e, 0xfb, 0x41, 0x6e, 0xc5, 0x82, 0xf0, 0x51, 0xb7, 0x0f, 0x23, 0x9b, 0x77, 0xed, 0x9a, - 0x06, 0x6b, 0x77, 0x7c, 0x8e, 0xc4, 0xdf, 0x50, 0xa0, 0xd2, 0x81, 0x3e, 0x65, 0xbe, 0xe5, 0x51, - 0x79, 0x93, 0x24, 0x8e, 0xb3, 0xb5, 0x25, 0x48, 0x76, 0x0e, 0x75, 0x94, 0xef, 0x9a, 0x9d, 0xc7, - 0x95, 0x08, 0xca, 0x35, 0x6b, 0x73, 0xbc, 0x4b, 0x93, 0x7a, 0x93, 0x55, 0x2d, 0xe4, 0x5f, 0xcf, - 0x11, 0x31, 0x94, 0xb2, 0x5a, 0x05, 0x80, 0xd7, 0x59, 0x79, 0x14, 0x8a, 0x2a, 0xb9, 0xd7, 0x3d, - 0x33, 0x69, 0xa9, 0xab, 0xaa, 0xb8, 0x4c, 0x73, 0xb6, 0x71, 0x2c, 0x6f, 0x31, 0x82, 0x03, 0x3b, - 0x30, 0x82, 0x03, 0x37, 0x02, 0x01, 0x01, 0x30, 0x81, 0xa4, 0x30, 0x81, 0x96, 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, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, - 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, - 0x04, 0x0b, 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, - 0x6e, 0x65, 0x72, 0x02, 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, 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, 0x35, 0x31, 0x31, 0x30, 0x34, - 0x30, 0x31, 0x35, 0x36, 0x34, 0x30, 0x5a, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x09, 0x04, 0x31, 0x22, 0x04, 0x20, 0x30, 0x9e, 0x11, 0x91, 0x83, 0x14, 0xd8, 0xb9, - 0xd6, 0x24, 0x8e, 0x04, 0x7e, 0x31, 0xa7, 0x66, 0xf7, 0x3c, 0x96, 0xc6, 0x23, 0x60, 0x2e, 0xec, - 0x9e, 0x0c, 0xda, 0xab, 0x25, 0x58, 0x02, 0xf2, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x02, 0x00, 0xbc, 0x5a, 0x74, 0xac, 0x24, - 0x13, 0xa5, 0xa3, 0xfb, 0x61, 0xfb, 0x19, 0x7a, 0x3f, 0x7b, 0x46, 0x5a, 0xcd, 0x8a, 0x92, 0x23, - 0xeb, 0xd0, 0xdf, 0xf2, 0x05, 0xbe, 0x02, 0xf9, 0xd5, 0x81, 0xca, 0x16, 0xf9, 0xd9, 0x63, 0x9e, - 0x19, 0xb8, 0xea, 0x1d, 0x51, 0x2c, 0xfc, 0x65, 0x0c, 0x67, 0x31, 0x5d, 0xa2, 0x87, 0x40, 0xa2, - 0x58, 0x57, 0x35, 0xe1, 0xa2, 0xc8, 0x25, 0xe4, 0x79, 0xd1, 0xc2, 0x76, 0x26, 0x20, 0x11, 0x76, - 0x38, 0xc8, 0xa1, 0x08, 0x98, 0x7c, 0x28, 0x8a, 0x14, 0x23, 0x89, 0xfa, 0xe6, 0x55, 0xaf, 0x47, - 0x1f, 0xe8, 0x5c, 0xc4, 0x0b, 0x88, 0x27, 0x75, 0xf5, 0x2d, 0x2c, 0x63, 0x63, 0x7b, 0xd3, 0x2b, - 0xd2, 0xb1, 0x4d, 0xf5, 0xd3, 0xa9, 0xdc, 0xc1, 0x34, 0x9d, 0xb8, 0x44, 0xae, 0xa3, 0x41, 0xd7, - 0x1e, 0x02, 0xff, 0x06, 0x3d, 0x8b, 0x3b, 0x01, 0xc6, 0xa9, 0x0f, 0x7a, 0x59, 0x03, 0x05, 0x2a, - 0xcf, 0x19, 0xc1, 0xd2, 0xea, 0x30, 0x3f, 0xbd, 0x83, 0x80, 0x26, 0xd7, 0x73, 0x32, 0x00, 0x8d, - 0x4f, 0x69, 0xaa, 0xf0, 0x39, 0x3f, 0xae, 0x46, 0xfc, 0x19, 0x7e, 0x62, 0xd2, 0xc8, 0x59, 0xa2, - 0xd1, 0x23, 0xa2, 0xab, 0xdd, 0x5b, 0xbc, 0xa9, 0x4d, 0x8c, 0x3a, 0xa4, 0x9d, 0x8e, 0x80, 0x0c, - 0x2b, 0x2d, 0x26, 0x27, 0xb7, 0xf2, 0xb9, 0x19, 0xc5, 0x8e, 0x17, 0x44, 0xb2, 0x19, 0x29, 0x3b, - 0x25, 0x7e, 0x76, 0xf8, 0x97, 0x85, 0xbc, 0x78, 0xa4, 0x41, 0xcb, 0x10, 0xed, 0xd7, 0x8c, 0x4c, - 0x56, 0x44, 0xfc, 0x7c, 0xa8, 0x98, 0xff, 0xa5, 0xef, 0x21, 0xe4, 0xc2, 0x2b, 0xaf, 0xfb, 0xb2, - 0xcb, 0x4c, 0x63, 0x19, 0x53, 0xae, 0xc4, 0xbc, 0x44, 0x31, 0xcb, 0x06, 0x2f, 0x01, 0x2b, 0x6b, - 0x7e, 0xd8, 0x24, 0x76, 0x16, 0x74, 0xa5, 0xb2, 0x46, 0xff, 0x14, 0xde, 0xc8, 0xe5, 0xfc, 0xeb, - 0xfa, 0xb8, 0xc2, 0x39, 0x9d, 0xf6, 0xdd, 0xbb, 0xba, 0x7d, 0x2d, 0x49, 0x4c, 0x7d, 0x87, 0xe2, - 0x0a, 0xb7, 0x52, 0xb5, 0x3d, 0x9d, 0x02, 0xf2, 0x04, 0x3d, 0x9b, 0x8b, 0x04, 0xe8, 0x84, 0x50, - 0x19, 0xb7, 0xfa, 0x4f, 0x9f, 0xa6, 0x00, 0x06, 0x2a, 0x44, 0xb2, 0x58, 0x91, 0x2f, 0xde, 0xd6, - 0x25, 0xcc, 0xd5, 0x68, 0x04, 0x51, 0xb1, 0x0f, 0x08, 0x41, 0xdd, 0xea, 0x16, 0x70, 0xbd, 0x5a, - 0xbc, 0x05, 0x60, 0xbc, 0xd4, 0x67, 0x62, 0xe2, 0xc3, 0xc0, 0x79, 0xdf, 0x49, 0xd7, 0x52, 0x62, - 0xde, 0xce, 0x68, 0x5c, 0x32, 0x9b, 0xd3, 0xb8, 0xef, 0x62, 0x7b, 0x4b, 0x0e, 0x15, 0xae, 0x92, - 0xfb, 0x06, 0x36, 0xb9, 0x05, 0x72, 0x2f, 0x01, 0x55, 0x70, 0x2b, 0x09, 0x54, 0xe1, 0x70, 0x15, - 0xab, 0x24, 0xcb, 0x07, 0x4c, 0x7e, 0xde, 0x38, 0xb2, 0x03, 0x56, 0xdb, 0x2f, 0x8c, 0x3b, 0xe5, - 0x5e, 0x1a, 0xbb, 0x90, 0x08, 0x55, 0xb2, 0x3d, 0xd9, 0x6f, 0xe8, 0x81, 0x08, 0x04, 0x5e, 0x82, - 0x84, 0x7e, 0x9c, 0x3f, 0x5a, 0x66, 0x6f, 0x6c, 0xc6, 0x98, 0x82, 0x27, 0xb6, 0x49, 0x7b, 0x14, - 0x07, 0x9d, 0x20, 0x61, 0x9d, 0xd9, 0x3d, 0xd0, 0x71, 0x0c, 0x72, 0x82, 0x50, 0xac, 0x61, 0xcd, - 0xc5, 0xc6, 0xc9, 0x90, 0xe2, 0x92, 0x5b, 0x02, 0x73, 0xda, 0x98, 0x2e, 0x21, 0x1e, 0x66, 0x79, - 0x83, 0x2e, 0x1d, 0x66, 0x0e, 0x2b, 0x6d, 0x42, 0x7d, 0xf4, 0x0a, 0xd3, 0xa1, 0x9b, 0x7f, 0x61, - 0xa7, 0x13, 0x3a, 0xa4, 0x6e, 0x0d, 0x0b, 0xbf, 0x42, 0x32, 0xf7, 0xca, 0x0e, 0x96, 0x0a, 0xcb, - 0x9a, 0x0a, 0x6a, 0x24, 0x8c, 0x43, 0x76, 0x0e, 0xa8, 0x71, 0xcd, 0x3f, 0xc4, 0x85, 0x46, 0x50, - 0xb9, 0x65, 0x43, 0x49, 0xae, 0x31, 0x25, 0x76, 0x4b, 0xfb, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00 -}; - -#endif /* cms_hashagility_test_h */ diff --git a/OSX/libsecurity_cms/regressions/cms-trust-settings-test.c b/OSX/libsecurity_cms/regressions/cms-trust-settings-test.c index f15725afb..99b457f67 100644 --- a/OSX/libsecurity_cms/regressions/cms-trust-settings-test.c +++ b/OSX/libsecurity_cms/regressions/cms-trust-settings-test.c @@ -21,6 +21,7 @@ * @APPLE_LICENSE_HEADER_END@ */ +#include #include #include @@ -38,6 +39,7 @@ #define kSystemLoginKeychainPath "/Library/Keychains/System.keychain" #include "regressions/test/testmore.h" +#include "cms_regressions.h" #include "cms-trust-settings-test.h" // See diff --git a/OSX/libsecurity_cms/regressions/cms-trust-settings-test.h b/OSX/libsecurity_cms/regressions/cms-trust-settings-test.h index 10f1021dd..31e69a5cd 100644 --- a/OSX/libsecurity_cms/regressions/cms-trust-settings-test.h +++ b/OSX/libsecurity_cms/regressions/cms-trust-settings-test.h @@ -26,8 +26,6 @@ #include -int cms_trust_settings_test(int argc, char *const *argv); - unsigned char _cert[] = { 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, diff --git a/OSX/libsecurity_cms/regressions/cms_regressions.h b/OSX/libsecurity_cms/regressions/cms_regressions.h index 4cc5ad521..3085f6e6a 100644 --- a/OSX/libsecurity_cms/regressions/cms_regressions.h +++ b/OSX/libsecurity_cms/regressions/cms_regressions.h @@ -25,5 +25,6 @@ #include -ONE_TEST(cms_hash_agility_test) ONE_TEST(cms_trust_settings_test) +ONE_TEST(smime_cms_test) +ONE_TEST(cms_01_basic) diff --git a/OSX/libsecurity_codesigning/CodeSigningHelper/CodeSigningHelper.entitlements b/OSX/libsecurity_codesigning/CodeSigningHelper/CodeSigningHelper.entitlements new file mode 100644 index 000000000..b4e6a353b --- /dev/null +++ b/OSX/libsecurity_codesigning/CodeSigningHelper/CodeSigningHelper.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.private.tcc.allow + + kTCCServiceSystemPolicyAllFiles + + + diff --git a/OSX/libsecurity_codesigning/CodeSigningHelper/main.cpp b/OSX/libsecurity_codesigning/CodeSigningHelper/main.cpp index be200db38..a7e46bcd4 100644 --- a/OSX/libsecurity_codesigning/CodeSigningHelper/main.cpp +++ b/OSX/libsecurity_codesigning/CodeSigningHelper/main.cpp @@ -40,11 +40,26 @@ request(xpc_connection_t peer, xpc_object_t event) if (pid <= 0) return; + size_t audit_size; + audit_token_t const *audit = + (audit_token_t const *)xpc_dictionary_get_data(event, "audit", &audit_size); + + if (audit != NULL && audit_size != sizeof(audit_token_t)) { + Syslog::error("audit token has unexpected size %zu", audit_size); + return; + } + xpc_object_t reply = xpc_dictionary_create_reply(event); if (reply == NULL) return; - CFTemp attributes("{%O=%d}", kSecGuestAttributePid, pid); + CFTemp attributes("{%O=%d}", kSecGuestAttributePid, pid); + + if (audit != NULL) { + CFRef auditData = makeCFData(audit, audit_size); + CFDictionaryAddValue(attributes.get(), kSecGuestAttributeAudit, + auditData); + } CFRef code; if ((rc = SecCodeCopyGuestWithAttributes(NULL, attributes, kSecCSDefaultFlags, &code.aref())) == noErr) { diff --git a/OSX/libsecurity_codesigning/antlr2/src/CharBuffer.cpp b/OSX/libsecurity_codesigning/antlr2/src/CharBuffer.cpp index c40495e31..b58bd3545 100644 --- a/OSX/libsecurity_codesigning/antlr2/src/CharBuffer.cpp +++ b/OSX/libsecurity_codesigning/antlr2/src/CharBuffer.cpp @@ -40,7 +40,15 @@ CharBuffer::CharBuffer(ANTLR_USE_NAMESPACE(std)istream& input_) int CharBuffer::getChar() { // try { - return input.get(); + int i = input.get(); + + if (i == -1) { + // pass through EOF + return -1; + } + + // prevent negative-valued characters through sign extension of high-bit characters + return static_cast(static_cast(i)); // } // catch (ANTLR_USE_NAMESPACE(std)ios_base::failure& e) { // throw CharStreamIOException(e); diff --git a/OSX/libsecurity_codesigning/lib/CSCommon.h b/OSX/libsecurity_codesigning/lib/CSCommon.h index 6aeef6490..d3a6bb182 100644 --- a/OSX/libsecurity_codesigning/lib/CSCommon.h +++ b/OSX/libsecurity_codesigning/lib/CSCommon.h @@ -84,8 +84,8 @@ CF_ENUM(OSStatus) { errSecCSStaticCodeChanged = -67034, /* the code on disk does not match what is running */ errSecCSDBDenied = -67033, /* permission to use a database denied */ errSecCSDBAccess = -67032, /* cannot access a database */ - errSecCSSigDBDenied = errSecCSDBDenied, - errSecCSSigDBAccess = errSecCSDBAccess, + errSecCSSigDBDenied = -67033, /* permission to use a database denied */ + errSecCSSigDBAccess = -67032, /* cannot access a database */ errSecCSHostProtocolInvalidAttribute = -67031, /* host returned invalid or inconsistent guest attributes */ errSecCSInfoPlistFailed = -67030, /* invalid Info.plist (plist or signature have been modified) */ errSecCSNoMainExecutable = -67029, /* the code has no main executable file */ @@ -119,10 +119,13 @@ CF_ENUM(OSStatus) { errSecCSBadDiskImageFormat = -67001, /* disk image format unrecognized, invalid, or unsuitable */ errSecCSUnsupportedDigestAlgorithm = -67000, /* a requested signature digest algorithm is not supported */ errSecCSInvalidAssociatedFileData = -66999, /* resource fork, Finder information, or similar detritus not allowed */ - errSecCSInvalidTeamIdentifier = -66998, /* a Team Identifier string is invalid */ - errSecCSBadTeamIdentifier = -66997, /* a Team Identifier is wrong or inappropriate */ - errSecCSSignatureUntrusted = -66996, /* signature is valid but signer is not trusted */ + errSecCSInvalidTeamIdentifier = -66998, /* a Team Identifier string is invalid */ + errSecCSBadTeamIdentifier = -66997, /* a Team Identifier is wrong or inappropriate */ + errSecCSSignatureUntrusted = -66996, /* signature is valid but signer is not trusted */ errSecMultipleExecSegments = -66995, /* the image contains multiple executable segments */ + errSecCSInvalidEntitlements = -66994, /* invalid entitlement plist */ + errSecCSInvalidRuntimeVersion = -66993, /* an invalid runtime version was explicitly set */ + errSecCSRevokedNotarization = -66992, /* notarization indicates this code has been revoked */ }; /* @@ -245,6 +248,9 @@ typedef CF_OPTIONS(uint32_t, SecCSFlags) { immediately if it becomes invalid. @constant kSecCodeSignatureForceExpiration Forces the kSecCSConsiderExpiration flag on all validations of the code. + @constant kSecCodeSignatureRuntime + Instructs the kernel to apply runtime hardening policies as required by the + hardened runtime version */ typedef CF_OPTIONS(uint32_t, SecCodeSignatureFlags) { kSecCodeSignatureHost = 0x0001, /* may host guest code */ @@ -255,6 +261,7 @@ typedef CF_OPTIONS(uint32_t, SecCodeSignatureFlags) { kSecCodeSignatureRestrict = 0x0800, /* restrict dyld loading */ kSecCodeSignatureEnforcement = 0x1000, /* enforce code signing */ kSecCodeSignatureLibraryValidation = 0x2000, /* library validation required */ + kSecCodeSignatureRuntime = 0x10000, /* apply runtime hardening policies */ }; /*! @@ -296,11 +303,20 @@ typedef CF_OPTIONS(uint32_t, SecCodeSignatureFlags) { This bit can only be set. Code that has the kill flag set will never be dynamically invalid (and live). Note however that a change in static validity does not necessarily trigger instant death. + + @constant kSecCodeStatusDebugged + Indicated that code has been debugged by another process that was allowed to do so. The debugger + causes this to be set when it attachs. + + @constant kSecCodeStatusPlatform + Indicates the code is platform code, shipping with the operating system and signed by Apple. */ typedef CF_OPTIONS(uint32_t, SecCodeStatus) { - kSecCodeStatusValid = 0x0001, - kSecCodeStatusHard = 0x0100, - kSecCodeStatusKill = 0x0200, + kSecCodeStatusValid = 0x00000001, + kSecCodeStatusHard = 0x00000100, + kSecCodeStatusKill = 0x00000200, + kSecCodeStatusDebugged = 0x10000000, + kSecCodeStatusPlatform = 0x04000000, }; @@ -337,6 +353,7 @@ typedef CF_ENUM(uint32_t, SecCSDigestAlgorithm) { kSecCodeSignatureHashSHA256 = 2, /* SHA-256 */ kSecCodeSignatureHashSHA256Truncated = 3, /* SHA-256 truncated to first 20 bytes */ kSecCodeSignatureHashSHA384 = 4, /* SHA-384 */ + kSecCodeSignatureHashSHA512 = 5, /* SHA-512 */ }; CF_ASSUME_NONNULL_END diff --git a/OSX/libsecurity_codesigning/lib/CSCommonPriv.h b/OSX/libsecurity_codesigning/lib/CSCommonPriv.h index d527dd37f..0bb820219 100644 --- a/OSX/libsecurity_codesigning/lib/CSCommonPriv.h +++ b/OSX/libsecurity_codesigning/lib/CSCommonPriv.h @@ -71,6 +71,7 @@ extern const SecCodeDirectoryFlagTable kSecCodeDirectoryFlagTable[]; data that is usually written to separate files. This is the format of detached signatures if the program is capable of having multiple architectures. @constant kSecCodeMagicEntitlement Magic number for a standard entitlement blob. + @constant kSecCodeMagicEntitlementDER Magic number for a DER entitlement blob. @constant kSecCodeMagicByte The first byte (in NBO) shared by all these magic numbers. This is not a valid ASCII character; test for this to distinguish between text and binary data if you expect a code signing-related binary blob. @@ -83,7 +84,8 @@ enum { kSecCodeMagicEmbeddedSignature = 0xfade0cc0, /* single-architecture embedded signature */ kSecCodeMagicDetachedSignature = 0xfade0cc1, /* detached multi-architecture signature */ kSecCodeMagicEntitlement = 0xfade7171, /* entitlement blob */ - + kSecCodeMagicEntitlementDER = 0xfade7172, /* entitlement DER blob */ + kSecCodeMagicByte = 0xfa /* shared first byte */ }; diff --git a/OSX/libsecurity_codesigning/lib/Code.cpp b/OSX/libsecurity_codesigning/lib/Code.cpp index d5de3047c..712b2ff4c 100644 --- a/OSX/libsecurity_codesigning/lib/Code.cpp +++ b/OSX/libsecurity_codesigning/lib/Code.cpp @@ -26,10 +26,10 @@ // #include "Code.h" #include "StaticCode.h" -#include #include "cskernel.h" #include #include +#include "SecInternalReleasePriv.h" namespace Security { namespace CodeSigning { @@ -206,13 +206,27 @@ void SecCode::checkValidity(SecCSFlags flags) // check my static state myDisk->validateNonResourceComponents(); // also validates the CodeDirectory - if (flags & kSecCSStrictValidate) + if (flags & kSecCSStrictValidate) { myDisk->diskRep()->strictValidate(myDisk->codeDirectory(), DiskRep::ToleratedErrors(), flags); + } else if (flags & kSecCSStrictValidateStructure) { + myDisk->diskRep()->strictValidateStructure(myDisk->codeDirectory(), DiskRep::ToleratedErrors(), flags); + } // check my own dynamic state - if (!(this->host()->getGuestStatus(this) & kSecCodeStatusValid)) - MacOSError::throwMe(errSecCSGuestInvalid); - + SecCodeStatus dynamic_status = this->host()->getGuestStatus(this); + bool isValid = (dynamic_status & kSecCodeStatusValid) != 0; + if (!isValid) { + bool isDebugged = (dynamic_status & kSecCodeStatusDebugged) != 0; + bool isPlatform = (dynamic_status & kSecCodeStatusPlatform) != 0; + bool isInternal = SecIsInternalRelease(); + + if (!isDebugged || (isPlatform && !isInternal)) { + // fatal if the code is invalid and not being debugged, but + // never let platform code be debugged except on internal systems. + MacOSError::throwMe(errSecCSGuestInvalid); + } + } + // check that static and dynamic views are consistent if (this->cdHash() && !CFEqual(this->cdHash(), myDisk->cdHash())) MacOSError::throwMe(errSecCSStaticCodeChanged); @@ -255,6 +269,7 @@ void SecCode::changeGuestStatus(SecCode *guest, SecCodeStatusOperation operation // SecCode *SecCode::autoLocateGuest(CFDictionaryRef attributes, SecCSFlags flags) { +#if TARGET_OS_OSX // special case: with no attributes at all, return the root of trust if (CFDictionaryGetCount(attributes) == 0) return KernelCode::active()->retain(); @@ -280,6 +295,7 @@ SecCode *SecCode::autoLocateGuest(CFDictionaryRef attributes, SecCSFlags flags) return code.yield(); } } +#endif // TARGET_OS_OSX MacOSError::throwMe(errSecCSNoSuchCode); } diff --git a/OSX/libsecurity_codesigning/lib/CodeSigner.cpp b/OSX/libsecurity_codesigning/lib/CodeSigner.cpp index ee8045f98..bc11737f2 100644 --- a/OSX/libsecurity_codesigning/lib/CodeSigner.cpp +++ b/OSX/libsecurity_codesigning/lib/CodeSigner.cpp @@ -34,6 +34,7 @@ #include #include #include +#include namespace Security { @@ -58,6 +59,53 @@ class SecCodeSigner::Parser : CFDictionary { else return false; } + + uint32_t parseRuntimeVersion(std::string& runtime) + { + uint32_t version = 0; + char* cursor = const_cast(runtime.c_str()); + char* end = cursor + runtime.length(); + char* nxt = NULL; + long component = 0; + int component_shift = 16; + + // x should convert to 0x00XX0000 + // x.y should convert to 0x00XXYY00 + // x.y.z should covert to 0x00XXYYZZ + // 0, 0.0, and 0.0.0 are rejected + // anything else should be rejected + while (cursor < end) { + nxt = NULL; + errno = 0; + component = strtol(cursor, &nxt, 10); + if (cursor == nxt || + (errno != 0) || + (component < 0 || component > UINT8_MAX)) { + secdebug("signer", "Runtime version: %s is invalid", runtime.c_str()); + MacOSError::throwMe(errSecCSInvalidRuntimeVersion); + } + version |= (component & 0xff) << component_shift; + component_shift -= 8; + + if (*nxt == '\0') { + break; + } + + if (*nxt != '.' || component_shift < 0 || (nxt + 1) == end) { + // Catch a trailing "." + secdebug("signer", "Runtime version: %s is invalid", runtime.c_str()); + MacOSError::throwMe(errSecCSInvalidRuntimeVersion); + } + cursor = nxt + 1; + } + + if (version == 0) { + secdebug("signer","Runtime version: %s is a version of zero", runtime.c_str()); + MacOSError::throwMe(errSecCSInvalidRuntimeVersion); + } + + return version; + } }; @@ -65,7 +113,7 @@ class SecCodeSigner::Parser : CFDictionary { // Construct a SecCodeSigner // SecCodeSigner::SecCodeSigner(SecCSFlags flags) - : mOpFlags(flags), mLimitedAsync(NULL) + : mOpFlags(flags), mLimitedAsync(NULL), mRuntimeVersionOverride(0) { } @@ -122,8 +170,9 @@ std::string SecCodeSigner::getTeamIDFromSigner(CFArrayRef certs) // bool SecCodeSigner::valid() const { - if (mOpFlags & kSecCSRemoveSignature) + if (mOpFlags & (kSecCSRemoveSignature | kSecCSEditSignature)) { return true; + } return mSigner; } @@ -140,6 +189,9 @@ void SecCodeSigner::sign(SecStaticCode *code, SecCSFlags flags) if ((flags | mOpFlags) & kSecCSRemoveSignature) { secinfo("signer", "%p will remove signature from %p", this, code); operation.remove(flags); + } else if ((flags | mOpFlags) & kSecCSEditSignature) { + secinfo("signer", "%p will edit signature of %p", this, code); + operation.edit(flags); } else { if (!valid()) MacOSError::throwMe(errSecCSInvalidObjectRef); @@ -181,6 +233,29 @@ void SecCodeSigner::returnDetachedSignature(BlobCore *blob, Signer &signer) SecCodeSigner::Parser::Parser(SecCodeSigner &state, CFDictionaryRef parameters) : CFDictionary(parameters, errSecCSBadDictionaryFormat) { + CFNumberRef editCpuType = get(kSecCodeSignerEditCpuType); + CFNumberRef editCpuSubtype = get(kSecCodeSignerEditCpuSubtype); + if (editCpuType != NULL && editCpuSubtype != NULL) { + state.mEditArch = Architecture(cfNumber(editCpuType), + cfNumber(editCpuSubtype)); + } + + state.mEditCMS = get(kSecCodeSignerEditCMS); + + state.mDryRun = getBool(kSecCodeSignerDryRun); + + state.mSDKRoot = get(kSecCodeSignerSDKRoot); + + state.mPreserveAFSC = getBool(kSecCodeSignerPreserveAFSC); + + if (state.mOpFlags & kSecCSEditSignature) { + return; + /* Everything below this point is irrelevant for + * Signature Editing, which does not create any + * parts of the signature, only replaces them. + */ + } + // the signer may be an identity or null state.mSigner = SecIdentityRef(get(kSecCodeSignerIdentity)); if (state.mSigner) @@ -204,7 +279,7 @@ SecCodeSigner::Parser::Parser(SecCodeSigner &state, CFDictionaryRef parameters) if (CFNumberRef cmsSize = get(CFSTR("cmssize"))) state.mCMSSize = cfNumber(cmsSize); else - state.mCMSSize = 9000; // likely big enough + state.mCMSSize = 18000; // big enough for now, not forever. // metadata preservation options if (CFNumberRef preserve = get(kSecCodeSignerPreserveMetadata)) { @@ -257,15 +332,11 @@ SecCodeSigner::Parser::Parser(SecCodeSigner &state, CFDictionaryRef parameters) MacOSError::throwMe(errSecCSInvalidObjectRef); } - state.mDryRun = getBool(kSecCodeSignerDryRun); - state.mResourceRules = get(kSecCodeSignerResourceRules); state.mApplicationData = get(kSecCodeSignerApplicationData); state.mEntitlementData = get(kSecCodeSignerEntitlements); - state.mSDKRoot = get(kSecCodeSignerSDKRoot); - if (CFBooleanRef timestampRequest = get(kSecCodeSignerRequireTimestamp)) { state.mWantTimeStamp = timestampRequest == kCFBooleanTrue; } else { // pick default @@ -280,6 +351,18 @@ SecCodeSigner::Parser::Parser(SecCodeSigner &state, CFDictionaryRef parameters) state.mTimestampAuthentication = get(kSecCodeSignerTimestampAuthentication); state.mTimestampService = get(kSecCodeSignerTimestampServer); state.mNoTimeStampCerts = getBool(kSecCodeSignerTimestampOmitCertificates); + + if (CFStringRef runtimeVersionOverride = get(kSecCodeSignerRuntimeVersion)) { + std::string runtime = cfString(runtimeVersionOverride); + if (runtime.empty()) { + MacOSError::throwMe(errSecCSInvalidRuntimeVersion); + } + state.mRuntimeVersionOverride = parseRuntimeVersion(runtime); + } + + // Don't add the adhoc flag, even if no signer identity was specified. + // Useful for editing in the CMS at a later point. + state.mOmitAdhocFlag = getBool(kSecCodeSignerOmitAdhocFlag); } diff --git a/OSX/libsecurity_codesigning/lib/CodeSigner.h b/OSX/libsecurity_codesigning/lib/CodeSigner.h index e9e41d288..099d18c7e 100644 --- a/OSX/libsecurity_codesigning/lib/CodeSigner.h +++ b/OSX/libsecurity_codesigning/lib/CodeSigner.h @@ -93,7 +93,14 @@ class SecCodeSigner : public SecCFObject { bool mWantTimeStamp; // use a Timestamp server bool mNoTimeStampCerts; // don't request certificates with timestamping request LimitedAsync *mLimitedAsync; // limited async workers for verification + uint32_t mRuntimeVersionOverride; // runtime Version Override + bool mPreserveAFSC; // preserve AFSC compression + bool mOmitAdhocFlag; // don't add adhoc flag, even without signer identity + // Signature Editing + Architecture mEditArch; // architecture to edit (defaults to all if empty) + CFRef mEditCMS; // CMS to replace in the signature + }; diff --git a/OSX/libsecurity_codesigning/lib/RequirementKeywords.h b/OSX/libsecurity_codesigning/lib/RequirementKeywords.h index dde809997..e0794ed3e 100644 --- a/OSX/libsecurity_codesigning/lib/RequirementKeywords.h +++ b/OSX/libsecurity_codesigning/lib/RequirementKeywords.h @@ -12,6 +12,8 @@ "identifier", "cdhash", "platform", + "notarized", + "legacy", "anchor", "apple", "generic", @@ -21,5 +23,7 @@ "info", "entitlement", "exists", + "absent", "leaf", "root", + "timestamp", diff --git a/OSX/libsecurity_codesigning/lib/RequirementLexer.cpp b/OSX/libsecurity_codesigning/lib/RequirementLexer.cpp index 5ed5abea6..d7f147c3c 100644 --- a/OSX/libsecurity_codesigning/lib/RequirementLexer.cpp +++ b/OSX/libsecurity_codesigning/lib/RequirementLexer.cpp @@ -12,12 +12,26 @@ #include "requirement.h" #include "reqmaker.h" #include "csutilities.h" +#include +#include #include #include #include // OID coding +#include using namespace CodeSigning; typedef Requirement::Maker Maker; +extern "C" { + +/* Decode a choice of UTCTime or GeneralizedTime to a CFAbsoluteTime. Return +an absoluteTime if the date was valid and properly decoded. Return +NULL_TIME otherwise. */ +CFAbsoluteTime SecAbsoluteTimeFromDateContent(DERTag tag, const uint8_t *bytes, + size_t length); + +} + + ANTLR_BEGIN_NAMESPACE(Security_CodeSigning) RequirementLexer::RequirementLexer(std::istream& in) : antlr::CharScanner(new antlr::CharBuffer(in),true) @@ -39,31 +53,35 @@ RequirementLexer::RequirementLexer(const antlr::LexerSharedInputState& state) void RequirementLexer::initLiterals() { - literals["certificate"] = 25; + literals["certificate"] = 27; literals["always"] = 15; literals["host"] = 6; literals["guest"] = 5; literals["cdhash"] = 20; - literals["entitlement"] = 29; + literals["entitlement"] = 31; literals["library"] = 8; + literals["timestamp"] = 53; + literals["legacy"] = 23; literals["never"] = 17; - literals["cert"] = 26; + literals["cert"] = 28; literals["plugin"] = 9; + literals["absent"] = 33; literals["or"] = 10; - literals["leaf"] = 42; - literals["info"] = 28; + literals["leaf"] = 45; + literals["info"] = 30; literals["designated"] = 7; - literals["apple"] = 23; - literals["trusted"] = 27; + literals["apple"] = 25; + literals["trusted"] = 29; literals["true"] = 16; + literals["notarized"] = 22; literals["and"] = 11; - literals["root"] = 43; + literals["root"] = 46; literals["platform"] = 21; - literals["anchor"] = 22; + literals["anchor"] = 24; literals["false"] = 18; - literals["generic"] = 24; + literals["generic"] = 26; literals["identifier"] = 19; - literals["exists"] = 30; + literals["exists"] = 32; } antlr::RefToken RequirementLexer::nextToken() @@ -393,11 +411,11 @@ void RequirementLexer::mIDENT(bool _createToken) { } default: { - goto _loop47; + goto _loop49; } } } - _loop47:; + _loop49:; } // ( ... )* _ttype = testLiteralsTable(text.substr(_begin, text.length()-_begin),_ttype); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { @@ -498,11 +516,11 @@ void RequirementLexer::mDOTKEY(bool _createToken) { } } else { - goto _loop51; + goto _loop53; } } - _loop51:; + _loop53:; } // ( ... )* _ttype = testLiteralsTable(_ttype); if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { @@ -519,18 +537,18 @@ void RequirementLexer::mINTEGER(bool _createToken) { std::string::size_type _saveIndex; { // ( ... )+ - int _cnt69=0; + int _cnt71=0; for (;;) { if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { matchRange('0','9'); } else { - if ( _cnt69>=1 ) { goto _loop69; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} + if ( _cnt71>=1 ) { goto _loop71; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } - _cnt69++; + _cnt71++; } - _loop69:; + _loop71:; } // ( ... )+ if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); @@ -548,19 +566,19 @@ void RequirementLexer::mPATHNAME(bool _createToken) { match("/"); mIDENT(false); { // ( ... )+ - int _cnt54=0; + int _cnt56=0; for (;;) { if ((LA(1) == 0x2f /* '/' */ )) { match("/"); mIDENT(false); } else { - if ( _cnt54>=1 ) { goto _loop54; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} + if ( _cnt56>=1 ) { goto _loop56; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } - _cnt54++; + _cnt56++; } - _loop54:; + _loop56:; } // ( ... )+ if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); @@ -582,18 +600,18 @@ void RequirementLexer::mHASHCONSTANT(bool _createToken) { match('\"' /* charlit */ ); text.erase(_saveIndex); { // ( ... )+ - int _cnt57=0; + int _cnt59=0; for (;;) { if ((_tokenSet_1.member(LA(1)))) { mHEX(false); } else { - if ( _cnt57>=1 ) { goto _loop57; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} + if ( _cnt59>=1 ) { goto _loop59; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } - _cnt57++; + _cnt59++; } - _loop57:; + _loop59:; } // ( ... )+ _saveIndex = text.length(); match('\"' /* charlit */ ); @@ -671,18 +689,18 @@ void RequirementLexer::mHEXCONSTANT(bool _createToken) { match('x' /* charlit */ ); text.erase(_saveIndex); { // ( ... )+ - int _cnt60=0; + int _cnt62=0; for (;;) { if ((_tokenSet_1.member(LA(1)))) { mHEX(false); } else { - if ( _cnt60>=1 ) { goto _loop60; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} + if ( _cnt62>=1 ) { goto _loop62; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } - _cnt60++; + _cnt62++; } - _loop60:; + _loop62:; } // ( ... )+ if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { _token = makeToken(_ttype); @@ -702,158 +720,27 @@ void RequirementLexer::mSTRING(bool _createToken) { text.erase(_saveIndex); { // ( ... )* for (;;) { - switch ( LA(1)) { - case 0x5c /* '\\' */ : - { + if ((LA(1) == 0x5c /* '\\' */ )) { { _saveIndex = text.length(); match('\\' /* charlit */ ); text.erase(_saveIndex); match('\"' /* charlit */ ); } - break; } - case 0x0 /* '\0' */ : - case 0x1 /* '\1' */ : - case 0x2 /* '\2' */ : - case 0x3 /* '\3' */ : - case 0x4 /* '\4' */ : - case 0x5 /* '\5' */ : - case 0x6 /* '\6' */ : - case 0x7 /* '\7' */ : - case 0x8 /* '\10' */ : - case 0x9 /* '\t' */ : - case 0xa /* '\n' */ : - case 0xb /* '\13' */ : - case 0xc /* '\14' */ : - case 0xd /* '\r' */ : - case 0xe /* '\16' */ : - case 0xf /* '\17' */ : - case 0x10 /* '\20' */ : - case 0x11 /* '\21' */ : - case 0x12 /* '\22' */ : - case 0x13 /* '\23' */ : - case 0x14 /* '\24' */ : - case 0x15 /* '\25' */ : - case 0x16 /* '\26' */ : - case 0x17 /* '\27' */ : - case 0x18 /* '\30' */ : - case 0x19 /* '\31' */ : - case 0x1a /* '\32' */ : - case 0x1b /* '\33' */ : - case 0x1c /* '\34' */ : - case 0x1d /* '\35' */ : - case 0x1e /* '\36' */ : - case 0x1f /* '\37' */ : - case 0x20 /* ' ' */ : - case 0x21 /* '!' */ : - case 0x23 /* '#' */ : - case 0x24 /* '$' */ : - case 0x25 /* '%' */ : - case 0x26 /* '&' */ : - case 0x27 /* '\'' */ : - case 0x28 /* '(' */ : - case 0x29 /* ')' */ : - case 0x2a /* '*' */ : - case 0x2b /* '+' */ : - case 0x2c /* ',' */ : - case 0x2d /* '-' */ : - case 0x2e /* '.' */ : - case 0x2f /* '/' */ : - case 0x30 /* '0' */ : - case 0x31 /* '1' */ : - case 0x32 /* '2' */ : - case 0x33 /* '3' */ : - case 0x34 /* '4' */ : - case 0x35 /* '5' */ : - case 0x36 /* '6' */ : - case 0x37 /* '7' */ : - case 0x38 /* '8' */ : - case 0x39 /* '9' */ : - case 0x3a /* ':' */ : - case 0x3b /* ';' */ : - case 0x3c /* '<' */ : - case 0x3d /* '=' */ : - case 0x3e /* '>' */ : - case 0x3f /* '?' */ : - case 0x40 /* '@' */ : - case 0x41 /* 'A' */ : - case 0x42 /* 'B' */ : - case 0x43 /* 'C' */ : - case 0x44 /* 'D' */ : - case 0x45 /* 'E' */ : - case 0x46 /* 'F' */ : - case 0x47 /* 'G' */ : - case 0x48 /* 'H' */ : - case 0x49 /* 'I' */ : - case 0x4a /* 'J' */ : - case 0x4b /* 'K' */ : - case 0x4c /* 'L' */ : - case 0x4d /* 'M' */ : - case 0x4e /* 'N' */ : - case 0x4f /* 'O' */ : - case 0x50 /* 'P' */ : - case 0x51 /* 'Q' */ : - case 0x52 /* 'R' */ : - case 0x53 /* 'S' */ : - case 0x54 /* 'T' */ : - case 0x55 /* 'U' */ : - case 0x56 /* 'V' */ : - case 0x57 /* 'W' */ : - case 0x58 /* 'X' */ : - case 0x59 /* 'Y' */ : - case 0x5a /* 'Z' */ : - case 0x5b /* '[' */ : - case 0x5d /* ']' */ : - case 0x5e /* '^' */ : - case 0x5f /* '_' */ : - case 0x60 /* '`' */ : - case 0x61 /* 'a' */ : - case 0x62 /* 'b' */ : - case 0x63 /* 'c' */ : - case 0x64 /* 'd' */ : - case 0x65 /* 'e' */ : - case 0x66 /* 'f' */ : - case 0x67 /* 'g' */ : - case 0x68 /* 'h' */ : - case 0x69 /* 'i' */ : - case 0x6a /* 'j' */ : - case 0x6b /* 'k' */ : - case 0x6c /* 'l' */ : - case 0x6d /* 'm' */ : - case 0x6e /* 'n' */ : - case 0x6f /* 'o' */ : - case 0x70 /* 'p' */ : - case 0x71 /* 'q' */ : - case 0x72 /* 'r' */ : - case 0x73 /* 's' */ : - case 0x74 /* 't' */ : - case 0x75 /* 'u' */ : - case 0x76 /* 'v' */ : - case 0x77 /* 'w' */ : - case 0x78 /* 'x' */ : - case 0x79 /* 'y' */ : - case 0x7a /* 'z' */ : - case 0x7b /* '{' */ : - case 0x7c /* '|' */ : - case 0x7d /* '}' */ : - case 0x7e /* '~' */ : - case 0x7f: - { + else if ((_tokenSet_2.member(LA(1)))) { { { match(_tokenSet_2); } } - break; - } - default: - { - goto _loop66; } + else { + goto _loop68; } + } - _loop66:; + _loop68:; } // ( ... )* _saveIndex = text.length(); match('\"' /* charlit */ ); @@ -1110,7 +997,7 @@ void RequirementLexer::mWS(bool _createToken) { std::string::size_type _saveIndex; { // ( ... )+ - int _cnt90=0; + int _cnt92=0; for (;;) { switch ( LA(1)) { case 0x20 /* ' ' */ : @@ -1131,12 +1018,12 @@ void RequirementLexer::mWS(bool _createToken) { } default: { - if ( _cnt90>=1 ) { goto _loop90; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} + if ( _cnt92>=1 ) { goto _loop92; } else {throw antlr::NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} } } - _cnt90++; + _cnt92++; } - _loop90:; + _loop92:; } // ( ... )+ _ttype = antlr::Token::SKIP; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { @@ -1159,11 +1046,11 @@ void RequirementLexer::mSHELLCOMMENT(bool _createToken) { matchNot('\n' /* charlit */ ); } else { - goto _loop93; + goto _loop95; } } - _loop93:; + _loop95:; } // ( ... )* _ttype = antlr::Token::SKIP; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { @@ -1196,11 +1083,11 @@ void RequirementLexer::mC_COMMENT(bool _createToken) { } } else { - goto _loop99; + goto _loop101; } } - _loop99:; + _loop101:; } // ( ... )* match("*/"); _ttype = antlr::Token::SKIP; @@ -1224,11 +1111,11 @@ void RequirementLexer::mCPP_COMMENT(bool _createToken) { matchNot('\n' /* charlit */ ); } else { - goto _loop102; + goto _loop104; } } - _loop102:; + _loop104:; } // ( ... )* _ttype = antlr::Token::SKIP; if ( _createToken && _token==antlr::nullToken && _ttype!=antlr::Token::SKIP ) { @@ -1240,30 +1127,30 @@ void RequirementLexer::mCPP_COMMENT(bool _createToken) { } -const unsigned long RequirementLexer::_tokenSet_0_data_[] = { 0UL, 0UL, 134217726UL, 134217726UL, 0UL, 0UL, 0UL, 0UL }; -const antlr::BitSet RequirementLexer::_tokenSet_0(_tokenSet_0_data_,8); -const unsigned long RequirementLexer::_tokenSet_1_data_[] = { 0UL, 67043328UL, 126UL, 126UL, 0UL, 0UL, 0UL, 0UL }; +const unsigned long RequirementLexer::_tokenSet_0_data_[] = { 0UL, 0UL, 134217726UL, 134217726UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; +const antlr::BitSet RequirementLexer::_tokenSet_0(_tokenSet_0_data_,10); +const unsigned long RequirementLexer::_tokenSet_1_data_[] = { 0UL, 67043328UL, 126UL, 126UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // 0 1 2 3 4 5 6 7 8 9 -const antlr::BitSet RequirementLexer::_tokenSet_1(_tokenSet_1_data_,8); -const unsigned long RequirementLexer::_tokenSet_2_data_[] = { 4294967295UL, 4294967291UL, 4026531839UL, 4294967295UL, 0UL, 0UL, 0UL, 0UL }; +const antlr::BitSet RequirementLexer::_tokenSet_1(_tokenSet_1_data_,10); +const unsigned long RequirementLexer::_tokenSet_2_data_[] = { 4294967295UL, 4294967291UL, 4026531839UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967292UL, 2097151UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf 0x10 // 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e -// 0x1f ! # $ % & \' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 -const antlr::BitSet RequirementLexer::_tokenSet_2(_tokenSet_2_data_,8); -const unsigned long RequirementLexer::_tokenSet_3_data_[] = { 4294966271UL, 4294967295UL, 4294967295UL, 4294967295UL, 0UL, 0UL, 0UL, 0UL }; +// 0x1f ! # $ % & \' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = +const antlr::BitSet RequirementLexer::_tokenSet_2(_tokenSet_2_data_,16); +const unsigned long RequirementLexer::_tokenSet_3_data_[] = { 4294966271UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967292UL, 2097151UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xb 0xc 0xd 0xe 0xf 0x10 0x11 // 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f -// ! \" # $ % & \' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 -const antlr::BitSet RequirementLexer::_tokenSet_3(_tokenSet_3_data_,8); -const unsigned long RequirementLexer::_tokenSet_4_data_[] = { 4294967295UL, 4294934527UL, 4294967295UL, 4294967295UL, 0UL, 0UL, 0UL, 0UL }; +// ! \" # $ % & \' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = +const antlr::BitSet RequirementLexer::_tokenSet_3(_tokenSet_3_data_,16); +const unsigned long RequirementLexer::_tokenSet_4_data_[] = { 4294967295UL, 4294934527UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967292UL, 2097151UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf 0x10 // 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e -// 0x1f ! \" # $ % & \' ( ) * + , - . 0 1 2 3 4 5 6 7 8 9 -const antlr::BitSet RequirementLexer::_tokenSet_4(_tokenSet_4_data_,8); -const unsigned long RequirementLexer::_tokenSet_5_data_[] = { 4294967295UL, 4294966271UL, 4294967295UL, 4294967295UL, 0UL, 0UL, 0UL, 0UL }; +// 0x1f ! \" # $ % & \' ( ) * + , - . 0 1 2 3 4 5 6 7 8 9 : ; < = +const antlr::BitSet RequirementLexer::_tokenSet_4(_tokenSet_4_data_,16); +const unsigned long RequirementLexer::_tokenSet_5_data_[] = { 4294967295UL, 4294966271UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967292UL, 2097151UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; // 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf 0x10 // 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e -// 0x1f ! \" # $ % & \' ( ) + , - . / 0 1 2 3 4 5 6 7 8 9 -const antlr::BitSet RequirementLexer::_tokenSet_5(_tokenSet_5_data_,8); +// 0x1f ! \" # $ % & \' ( ) + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = +const antlr::BitSet RequirementLexer::_tokenSet_5(_tokenSet_5_data_,16); ANTLR_END_NAMESPACE diff --git a/OSX/libsecurity_codesigning/lib/RequirementParser.cpp b/OSX/libsecurity_codesigning/lib/RequirementParser.cpp index dfaa34508..28b891eb1 100644 --- a/OSX/libsecurity_codesigning/lib/RequirementParser.cpp +++ b/OSX/libsecurity_codesigning/lib/RequirementParser.cpp @@ -7,12 +7,26 @@ #include "requirement.h" #include "reqmaker.h" #include "csutilities.h" +#include +#include #include #include #include // OID coding +#include using namespace CodeSigning; typedef Requirement::Maker Maker; +extern "C" { + +/* Decode a choice of UTCTime or GeneralizedTime to a CFAbsoluteTime. Return +an absoluteTime if the date was valid and properly decoded. Return +NULL_TIME otherwise. */ +CFAbsoluteTime SecAbsoluteTimeFromDateContent(DERTag tag, const uint8_t *bytes, + size_t length); + +} + + ANTLR_BEGIN_NAMESPACE(Security_CodeSigning) // @@ -66,7 +80,12 @@ ANTLR_BEGIN_NAMESPACE(Security_CodeSigning) void RequirementParser::certMatchOperation(Maker &maker, int32_t slot, string key) { - if (matchPrefix(key, "subject.")) { + if (const char *oids = matchPrefix(key, "timestamp.")) { + maker.put(opCertFieldDate); + maker.put(slot); + CssmAutoData oid(Allocator::standard()); oid.fromOid(oids); + maker.putData(oid.data(), oid.length()); + } else if (matchPrefix(key, "subject.")) { maker.put(opCertField); maker.put(slot); maker.put(key); @@ -129,6 +148,8 @@ BlobCore * RequirementParser::autosense() { case LITERAL_identifier: case LITERAL_cdhash: case LITERAL_platform: + case LITERAL_notarized: + case LITERAL_legacy: case LITERAL_anchor: case LITERAL_certificate: case LITERAL_cert: @@ -476,6 +497,18 @@ void RequirementParser::primary( maker.platform(ident); break; } + case LITERAL_notarized: + { + match(LITERAL_notarized); + maker.put(opNotarized); + break; + } + case LITERAL_legacy: + { + match(LITERAL_legacy); + maker.put(opLegacyDevID); + break; + } default: if ((LA(1) == LPAREN) && (_tokenSet_8.member(LA(2)))) { match(LPAREN); @@ -964,78 +997,10 @@ void RequirementParser::match_suffix( maker.put(matchExists); break; } - case EQL: - case EQQL: + case LITERAL_absent: { - { - switch ( LA(1)) { - case EQL: - { - match(EQL); - break; - } - case EQQL: - { - match(EQQL); - break; - } - default: - { - throw antlr::NoViableAltException(LT(1), getFilename()); - } - } - } - MatchOperation mop = matchEqual; string value; - { - switch ( LA(1)) { - case STAR: - { - match(STAR); - mop = matchEndsWith; - break; - } - case HEXCONSTANT: - case DOTKEY: - case STRING: - { - break; - } - default: - { - throw antlr::NoViableAltException(LT(1), getFilename()); - } - } - } - value=datavalue(); - { - switch ( LA(1)) { - case STAR: - { - match(STAR); - mop = (mop == matchEndsWith) ? matchContains : matchBeginsWith; - break; - } - case antlr::Token::EOF_TYPE: - case LITERAL_guest: - case LITERAL_host: - case LITERAL_designated: - case LITERAL_library: - case LITERAL_plugin: - case LITERAL_or: - case LITERAL_and: - case RPAREN: - case INTEGER: - case SEMI: - { - break; - } - default: - { - throw antlr::NoViableAltException(LT(1), getFilename()); - } - } - } - maker.put(mop); maker.put(value); + match(LITERAL_absent); + maker.put(matchAbsent); break; } case SUBS: @@ -1046,40 +1011,150 @@ void RequirementParser::match_suffix( maker.put(matchContains); maker.put(value); break; } - case LESS: - { - match(LESS); - string value; - value=datavalue(); - maker.put(matchLessThan); maker.put(value); - break; - } - case GT: - { - match(GT); - string value; - value=datavalue(); - maker.put(matchGreaterThan); maker.put(value); - break; - } - case LE: - { - match(LE); - string value; - value=datavalue(); - maker.put(matchLessEqual); maker.put(value); - break; - } - case GE: - { - match(GE); - string value; - value=datavalue(); - maker.put(matchGreaterEqual); maker.put(value); - break; - } default: - { + if ((LA(1) == EQL || LA(1) == EQQL) && (_tokenSet_16.member(LA(2)))) { + { + switch ( LA(1)) { + case EQL: + { + match(EQL); + break; + } + case EQQL: + { + match(EQQL); + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + MatchOperation mop = matchEqual; string value; + { + switch ( LA(1)) { + case STAR: + { + match(STAR); + mop = matchEndsWith; + break; + } + case HEXCONSTANT: + case DOTKEY: + case STRING: + { + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + value=datavalue(); + { + switch ( LA(1)) { + case STAR: + { + match(STAR); + mop = (mop == matchEndsWith) ? matchContains : matchBeginsWith; + break; + } + case antlr::Token::EOF_TYPE: + case LITERAL_guest: + case LITERAL_host: + case LITERAL_designated: + case LITERAL_library: + case LITERAL_plugin: + case LITERAL_or: + case LITERAL_and: + case RPAREN: + case INTEGER: + case SEMI: + { + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + maker.put(mop); maker.put(value); + } + else if ((LA(1) == EQL || LA(1) == EQQL) && (LA(2) == LITERAL_timestamp)) { + { + switch ( LA(1)) { + case EQL: + { + match(EQL); + break; + } + case EQQL: + { + match(EQQL); + break; + } + default: + { + throw antlr::NoViableAltException(LT(1), getFilename()); + } + } + } + MatchOperation mop = matchOn; int64_t value; + value=timestamp(); + maker.put(mop); maker.put(value); + } + else if ((LA(1) == LESS) && ((LA(2) >= HEXCONSTANT && LA(2) <= STRING))) { + match(LESS); + string value; + value=datavalue(); + maker.put(matchLessThan); maker.put(value); + } + else if ((LA(1) == GT) && ((LA(2) >= HEXCONSTANT && LA(2) <= STRING))) { + match(GT); + string value; + value=datavalue(); + maker.put(matchGreaterThan); maker.put(value); + } + else if ((LA(1) == LE) && ((LA(2) >= HEXCONSTANT && LA(2) <= STRING))) { + match(LE); + string value; + value=datavalue(); + maker.put(matchLessEqual); maker.put(value); + } + else if ((LA(1) == GE) && ((LA(2) >= HEXCONSTANT && LA(2) <= STRING))) { + match(GE); + string value; + value=datavalue(); + maker.put(matchGreaterEqual); maker.put(value); + } + else if ((LA(1) == LESS) && (LA(2) == LITERAL_timestamp)) { + match(LESS); + int64_t value; + value=timestamp(); + maker.put(matchBefore); maker.put(value); + } + else if ((LA(1) == GT) && (LA(2) == LITERAL_timestamp)) { + match(GT); + int64_t value; + value=timestamp(); + maker.put(matchAfter); maker.put(value); + } + else if ((LA(1) == LE) && (LA(2) == LITERAL_timestamp)) { + match(LE); + int64_t value; + value=timestamp(); + maker.put(matchOnOrBefore); maker.put(value); + } + else if ((LA(1) == GE) && (LA(2) == LITERAL_timestamp)) { + match(GE); + int64_t value; + value=timestamp(); + maker.put(matchOnOrAfter); maker.put(value); + } + else { throw antlr::NoViableAltException(LT(1), getFilename()); } } @@ -1117,7 +1192,24 @@ string RequirementParser::datavalue() { } catch (antlr::RecognitionException& ex) { reportError(ex); - recover(ex,_tokenSet_16); + recover(ex,_tokenSet_17); + } + return result; +} + +int64_t RequirementParser::timestamp() { + int64_t result; + antlr::RefToken s = antlr::nullToken; + + try { // for error handling + match(LITERAL_timestamp); + s = LT(1); + match(STRING); + result = (int64_t)SecAbsoluteTimeFromDateContent(ASN1_GENERALIZED_TIME, (uint8_t const *)s->getText().c_str(), s->getText().length()); + } + catch (antlr::RecognitionException& ex) { + reportError(ex); + recover(ex,_tokenSet_9); } return result; } @@ -1151,7 +1243,7 @@ string RequirementParser::stringvalue() { } catch (antlr::RecognitionException& ex) { reportError(ex); - recover(ex,_tokenSet_17); + recover(ex,_tokenSet_18); } return result; } @@ -1224,6 +1316,8 @@ const char* RequirementParser::tokenNames[] = { "\"identifier\"", "\"cdhash\"", "\"platform\"", + "\"notarized\"", + "\"legacy\"", "\"anchor\"", "\"apple\"", "\"generic\"", @@ -1233,6 +1327,7 @@ const char* RequirementParser::tokenNames[] = { "\"info\"", "\"entitlement\"", "\"exists\"", + "\"absent\"", "EQL", "EQQL", "STAR", @@ -1252,6 +1347,7 @@ const char* RequirementParser::tokenNames[] = { "STRING", "PATHNAME", "INTEGER", + "\"timestamp\"", "SEMI", "IDENT", "HEX", @@ -1266,66 +1362,69 @@ const char* RequirementParser::tokenNames[] = { const unsigned long RequirementParser::_tokenSet_0_data_[] = { 2UL, 0UL, 0UL, 0UL }; // EOF const antlr::BitSet RequirementParser::_tokenSet_0(_tokenSet_0_data_,4); -const unsigned long RequirementParser::_tokenSet_1_data_[] = { 992UL, 131072UL, 0UL, 0UL }; +const unsigned long RequirementParser::_tokenSet_1_data_[] = { 992UL, 1048576UL, 0UL, 0UL }; // "guest" "host" "designated" "library" "plugin" INTEGER const antlr::BitSet RequirementParser::_tokenSet_1(_tokenSet_1_data_,4); const unsigned long RequirementParser::_tokenSet_2_data_[] = { 16UL, 0UL, 0UL, 0UL }; // ARROW const antlr::BitSet RequirementParser::_tokenSet_2(_tokenSet_2_data_,4); -const unsigned long RequirementParser::_tokenSet_3_data_[] = { 994UL, 131072UL, 0UL, 0UL }; +const unsigned long RequirementParser::_tokenSet_3_data_[] = { 994UL, 1048576UL, 0UL, 0UL }; // EOF "guest" "host" "designated" "library" "plugin" INTEGER const antlr::BitSet RequirementParser::_tokenSet_3(_tokenSet_3_data_,4); -const unsigned long RequirementParser::_tokenSet_4_data_[] = { 2281713650UL, 512129UL, 0UL, 0UL }; +const unsigned long RequirementParser::_tokenSet_4_data_[] = { 536883186UL, 6194188UL, 0UL, 0UL }; // EOF ARROW "guest" "host" "designated" "library" "plugin" "or" "and" // RPAREN "trusted" EQL EQQL LBRACK HASHCONSTANT DOTKEY STRING PATHNAME // INTEGER SEMI const antlr::BitSet RequirementParser::_tokenSet_4(_tokenSet_4_data_,4); -const unsigned long RequirementParser::_tokenSet_5_data_[] = { 9186UL, 393216UL, 0UL, 0UL }; +const unsigned long RequirementParser::_tokenSet_5_data_[] = { 9186UL, 5242880UL, 0UL, 0UL }; // EOF "guest" "host" "designated" "library" "plugin" RPAREN INTEGER SEMI const antlr::BitSet RequirementParser::_tokenSet_5(_tokenSet_5_data_,4); -const unsigned long RequirementParser::_tokenSet_6_data_[] = { 994UL, 393216UL, 0UL, 0UL }; +const unsigned long RequirementParser::_tokenSet_6_data_[] = { 994UL, 5242880UL, 0UL, 0UL }; // EOF "guest" "host" "designated" "library" "plugin" INTEGER SEMI const antlr::BitSet RequirementParser::_tokenSet_6(_tokenSet_6_data_,4); -const unsigned long RequirementParser::_tokenSet_7_data_[] = { 10210UL, 393216UL, 0UL, 0UL }; +const unsigned long RequirementParser::_tokenSet_7_data_[] = { 10210UL, 5242880UL, 0UL, 0UL }; // EOF "guest" "host" "designated" "library" "plugin" "or" RPAREN INTEGER // SEMI const antlr::BitSet RequirementParser::_tokenSet_7(_tokenSet_7_data_,4); -const unsigned long RequirementParser::_tokenSet_8_data_[] = { 914345984UL, 0UL, 0UL, 0UL }; +const unsigned long RequirementParser::_tokenSet_8_data_[] = { 3657420800UL, 0UL, 0UL, 0UL }; // LPAREN NOT "always" "true" "never" "false" "identifier" "cdhash" "platform" -// "anchor" "certificate" "cert" "info" "entitlement" +// "notarized" "legacy" "anchor" "certificate" "cert" "info" "entitlement" const antlr::BitSet RequirementParser::_tokenSet_8(_tokenSet_8_data_,4); -const unsigned long RequirementParser::_tokenSet_9_data_[] = { 12258UL, 393216UL, 0UL, 0UL }; +const unsigned long RequirementParser::_tokenSet_9_data_[] = { 12258UL, 5242880UL, 0UL, 0UL }; // EOF "guest" "host" "designated" "library" "plugin" "or" "and" RPAREN // INTEGER SEMI const antlr::BitSet RequirementParser::_tokenSet_9(_tokenSet_9_data_,4); -const unsigned long RequirementParser::_tokenSet_10_data_[] = { 0UL, 134656UL, 0UL, 0UL }; +const unsigned long RequirementParser::_tokenSet_10_data_[] = { 0UL, 1077248UL, 0UL, 0UL }; // NEG "leaf" "root" INTEGER const antlr::BitSet RequirementParser::_tokenSet_10(_tokenSet_10_data_,4); -const unsigned long RequirementParser::_tokenSet_11_data_[] = { 2147483648UL, 118913UL, 0UL, 0UL }; +const unsigned long RequirementParser::_tokenSet_11_data_[] = { 0UL, 951308UL, 0UL, 0UL }; // EQL EQQL LBRACK HASHCONSTANT DOTKEY STRING PATHNAME const antlr::BitSet RequirementParser::_tokenSet_11(_tokenSet_11_data_,4); -const unsigned long RequirementParser::_tokenSet_12_data_[] = { 0UL, 249856UL, 0UL, 0UL }; +const unsigned long RequirementParser::_tokenSet_12_data_[] = { 0UL, 1998848UL, 0UL, 0UL }; // HASHCONSTANT DOTKEY STRING PATHNAME INTEGER const antlr::BitSet RequirementParser::_tokenSet_12(_tokenSet_12_data_,4); -const unsigned long RequirementParser::_tokenSet_13_data_[] = { 2281701376UL, 118913UL, 0UL, 0UL }; +const unsigned long RequirementParser::_tokenSet_13_data_[] = { 536870912UL, 951308UL, 0UL, 0UL }; // "trusted" EQL EQQL LBRACK HASHCONSTANT DOTKEY STRING PATHNAME const antlr::BitSet RequirementParser::_tokenSet_13(_tokenSet_13_data_,4); -const unsigned long RequirementParser::_tokenSet_14_data_[] = { 1073754082UL, 512000UL, 0UL, 0UL }; +const unsigned long RequirementParser::_tokenSet_14_data_[] = { 12258UL, 6193153UL, 0UL, 0UL }; // EOF "guest" "host" "designated" "library" "plugin" "or" "and" RPAREN // "exists" HASHCONSTANT DOTKEY STRING PATHNAME INTEGER SEMI const antlr::BitSet RequirementParser::_tokenSet_14(_tokenSet_14_data_,4); -const unsigned long RequirementParser::_tokenSet_15_data_[] = { 3221237730UL, 393341UL, 0UL, 0UL }; +const unsigned long RequirementParser::_tokenSet_15_data_[] = { 12258UL, 5243887UL, 0UL, 0UL }; // EOF "guest" "host" "designated" "library" "plugin" "or" "and" RPAREN -// "exists" EQL EQQL SUBS LESS GT LE GE INTEGER SEMI +// "exists" "absent" EQL EQQL SUBS LESS GT LE GE INTEGER SEMI const antlr::BitSet RequirementParser::_tokenSet_15(_tokenSet_15_data_,4); -const unsigned long RequirementParser::_tokenSet_16_data_[] = { 12258UL, 393218UL, 0UL, 0UL }; +const unsigned long RequirementParser::_tokenSet_16_data_[] = { 0UL, 458768UL, 0UL, 0UL }; +// STAR HEXCONSTANT DOTKEY STRING +const antlr::BitSet RequirementParser::_tokenSet_16(_tokenSet_16_data_,4); +const unsigned long RequirementParser::_tokenSet_17_data_[] = { 12258UL, 5242896UL, 0UL, 0UL }; // EOF "guest" "host" "designated" "library" "plugin" "or" "and" RPAREN // STAR INTEGER SEMI -const antlr::BitSet RequirementParser::_tokenSet_16(_tokenSet_16_data_,4); -const unsigned long RequirementParser::_tokenSet_17_data_[] = { 12258UL, 393474UL, 0UL, 0UL }; +const antlr::BitSet RequirementParser::_tokenSet_17(_tokenSet_17_data_,4); +const unsigned long RequirementParser::_tokenSet_18_data_[] = { 12258UL, 5244944UL, 0UL, 0UL }; // EOF "guest" "host" "designated" "library" "plugin" "or" "and" RPAREN // STAR RBRACK INTEGER SEMI -const antlr::BitSet RequirementParser::_tokenSet_17(_tokenSet_17_data_,4); +const antlr::BitSet RequirementParser::_tokenSet_18(_tokenSet_18_data_,4); ANTLR_END_NAMESPACE diff --git a/OSX/libsecurity_codesigning/lib/RequirementParser.hpp b/OSX/libsecurity_codesigning/lib/RequirementParser.hpp index 81857c657..7f8c16899 100644 --- a/OSX/libsecurity_codesigning/lib/RequirementParser.hpp +++ b/OSX/libsecurity_codesigning/lib/RequirementParser.hpp @@ -96,6 +96,7 @@ class CUSTOM_API RequirementParser : public antlr::LLkParser, public Requirement Maker &maker ); public: string datavalue(); + public: int64_t timestamp(); public: string stringvalue(); public: string pathstring(); public: @@ -109,10 +110,10 @@ class CUSTOM_API RequirementParser : public antlr::LLkParser, public Requirement private: static const char* tokenNames[]; #ifndef NO_STATIC_CONSTS - static const int NUM_TOKENS = 58; + static const int NUM_TOKENS = 62; #else enum { - NUM_TOKENS = 58 + NUM_TOKENS = 62 }; #endif @@ -152,6 +153,8 @@ class CUSTOM_API RequirementParser : public antlr::LLkParser, public Requirement static const antlr::BitSet _tokenSet_16; static const unsigned long _tokenSet_17_data_[]; static const antlr::BitSet _tokenSet_17; + static const unsigned long _tokenSet_18_data_[]; + static const antlr::BitSet _tokenSet_18; }; ANTLR_END_NAMESPACE diff --git a/OSX/libsecurity_codesigning/lib/RequirementParserTokenTypes.hpp b/OSX/libsecurity_codesigning/lib/RequirementParserTokenTypes.hpp index 3654840c1..b95db8cbf 100644 --- a/OSX/libsecurity_codesigning/lib/RequirementParserTokenTypes.hpp +++ b/OSX/libsecurity_codesigning/lib/RequirementParserTokenTypes.hpp @@ -31,42 +31,46 @@ struct CUSTOM_API RequirementParserTokenTypes { LITERAL_identifier = 19, LITERAL_cdhash = 20, LITERAL_platform = 21, - LITERAL_anchor = 22, - LITERAL_apple = 23, - LITERAL_generic = 24, - LITERAL_certificate = 25, - LITERAL_cert = 26, - LITERAL_trusted = 27, - LITERAL_info = 28, - LITERAL_entitlement = 29, - LITERAL_exists = 30, - EQL = 31, - EQQL = 32, - STAR = 33, - SUBS = 34, - LESS = 35, - GT = 36, - LE = 37, - GE = 38, - LBRACK = 39, - RBRACK = 40, - NEG = 41, - LITERAL_leaf = 42, - LITERAL_root = 43, - HASHCONSTANT = 44, - HEXCONSTANT = 45, - DOTKEY = 46, - STRING = 47, - PATHNAME = 48, - INTEGER = 49, - SEMI = 50, - IDENT = 51, - HEX = 52, - COMMA = 53, - WS = 54, - SHELLCOMMENT = 55, - C_COMMENT = 56, - CPP_COMMENT = 57, + LITERAL_notarized = 22, + LITERAL_legacy = 23, + LITERAL_anchor = 24, + LITERAL_apple = 25, + LITERAL_generic = 26, + LITERAL_certificate = 27, + LITERAL_cert = 28, + LITERAL_trusted = 29, + LITERAL_info = 30, + LITERAL_entitlement = 31, + LITERAL_exists = 32, + LITERAL_absent = 33, + EQL = 34, + EQQL = 35, + STAR = 36, + SUBS = 37, + LESS = 38, + GT = 39, + LE = 40, + GE = 41, + LBRACK = 42, + RBRACK = 43, + NEG = 44, + LITERAL_leaf = 45, + LITERAL_root = 46, + HASHCONSTANT = 47, + HEXCONSTANT = 48, + DOTKEY = 49, + STRING = 50, + PATHNAME = 51, + INTEGER = 52, + LITERAL_timestamp = 53, + SEMI = 54, + IDENT = 55, + HEX = 56, + COMMA = 57, + WS = 58, + SHELLCOMMENT = 59, + C_COMMENT = 60, + CPP_COMMENT = 61, NULL_TREE_LOOKAHEAD = 3 }; #ifdef __cplusplus diff --git a/OSX/libsecurity_codesigning/lib/RequirementParserTokenTypes.txt b/OSX/libsecurity_codesigning/lib/RequirementParserTokenTypes.txt index 781f4f52c..b22ffae7b 100644 --- a/OSX/libsecurity_codesigning/lib/RequirementParserTokenTypes.txt +++ b/OSX/libsecurity_codesigning/lib/RequirementParserTokenTypes.txt @@ -18,39 +18,43 @@ LITERAL_false="false"=18 LITERAL_identifier="identifier"=19 LITERAL_cdhash="cdhash"=20 LITERAL_platform="platform"=21 -LITERAL_anchor="anchor"=22 -LITERAL_apple="apple"=23 -LITERAL_generic="generic"=24 -LITERAL_certificate="certificate"=25 -LITERAL_cert="cert"=26 -LITERAL_trusted="trusted"=27 -LITERAL_info="info"=28 -LITERAL_entitlement="entitlement"=29 -LITERAL_exists="exists"=30 -EQL=31 -EQQL=32 -STAR=33 -SUBS=34 -LESS=35 -GT=36 -LE=37 -GE=38 -LBRACK=39 -RBRACK=40 -NEG=41 -LITERAL_leaf="leaf"=42 -LITERAL_root="root"=43 -HASHCONSTANT=44 -HEXCONSTANT=45 -DOTKEY=46 -STRING=47 -PATHNAME=48 -INTEGER=49 -SEMI=50 -IDENT=51 -HEX=52 -COMMA=53 -WS=54 -SHELLCOMMENT=55 -C_COMMENT=56 -CPP_COMMENT=57 +LITERAL_notarized="notarized"=22 +LITERAL_legacy="legacy"=23 +LITERAL_anchor="anchor"=24 +LITERAL_apple="apple"=25 +LITERAL_generic="generic"=26 +LITERAL_certificate="certificate"=27 +LITERAL_cert="cert"=28 +LITERAL_trusted="trusted"=29 +LITERAL_info="info"=30 +LITERAL_entitlement="entitlement"=31 +LITERAL_exists="exists"=32 +LITERAL_absent="absent"=33 +EQL=34 +EQQL=35 +STAR=36 +SUBS=37 +LESS=38 +GT=39 +LE=40 +GE=41 +LBRACK=42 +RBRACK=43 +NEG=44 +LITERAL_leaf="leaf"=45 +LITERAL_root="root"=46 +HASHCONSTANT=47 +HEXCONSTANT=48 +DOTKEY=49 +STRING=50 +PATHNAME=51 +INTEGER=52 +LITERAL_timestamp="timestamp"=53 +SEMI=54 +IDENT=55 +HEX=56 +COMMA=57 +WS=58 +SHELLCOMMENT=59 +C_COMMENT=60 +CPP_COMMENT=61 diff --git a/OSX/libsecurity_codesigning/lib/SecAssessment.cpp b/OSX/libsecurity_codesigning/lib/SecAssessment.cpp index f3395e63b..1db113117 100644 --- a/OSX/libsecurity_codesigning/lib/SecAssessment.cpp +++ b/OSX/libsecurity_codesigning/lib/SecAssessment.cpp @@ -26,24 +26,16 @@ #include "policyengine.h" #include "xpcengine.h" #include "csutilities.h" +#include "xar++.h" #include #include #include #include #include #include -#include using namespace CodeSigning; - -static void esp_do_check(const char *op, CFDictionaryRef dict) -{ - OSStatus result = __esp_check_ns(op, (void *)(CFDictionaryRef)dict); - if (result != noErr) - MacOSError::throwMe(result); -} - // // CF Objects // @@ -147,6 +139,7 @@ CFStringRef kSecAssessmentAssessmentAuthorityFlags = CFSTR("assessment:authority CFStringRef kSecAssessmentAssessmentFromCache = CFSTR("assessment:authority:cached"); CFStringRef kSecAssessmentAssessmentWeakSignature = CFSTR("assessment:authority:weak"); CFStringRef kSecAssessmentAssessmentCodeSigningError = CFSTR("assessment:cserror"); +CFStringRef kSecAssessmentAssessmentNotarizationDate = CFSTR("assessment:notarization-date"); CFStringRef kDisabledOverride = CFSTR("security disabled"); @@ -166,11 +159,6 @@ SecAssessmentRef SecAssessmentCreate(CFURLRef path, SYSPOLICY_ASSESS_API(cfString(path).c_str(), int(type), flags); try { - if (__esp_enabled() && (flags & kSecAssessmentFlagDirect)) { - CFTemp dict("{path=%O, flags=%d, context=%O, override=%d}", path, flags, context, overrideAssessment()); - esp_do_check("cs-assessment-evaluate", dict); - } - if (flags & kSecAssessmentFlagDirect) { // ask the engine right here to do its thing SYSPOLICY_ASSESS_LOCAL(); @@ -198,11 +186,6 @@ SecAssessmentRef SecAssessmentCreate(CFURLRef path, cfadd(result, "{%O=#F}", kSecAssessmentAssessmentVerdict); } - if (__esp_enabled() && (flags & kSecAssessmentFlagDirect)) { - CFTemp dict("{path=%O, flags=%d, context=%O, override=%d, result=%O}", path, flags, context, overrideAssessment(), (CFDictionaryRef)result); - __esp_notify_ns("cs-assessment-evaluate", (void *)(CFDictionaryRef)dict); - } - return new SecAssessment(path, type, result.yield()); END_CSAPI_ERRORS1(NULL) @@ -441,13 +424,6 @@ CFDictionaryRef SecAssessmentCopyUpdate(CFTypeRef target, } if (flags & kSecAssessmentFlagDirect) { - if (__esp_enabled()) { - CFTemp dict("{target=%O, flags=%d, context=%O}", target, flags, context); - OSStatus esp_result = __esp_check_ns("cs-assessment-update", (void *)(CFDictionaryRef)dict); - if (esp_result != noErr) - return NULL; - } - // ask the engine right here to do its thing result = gEngine().update(target, flags, ctx); } else { @@ -455,17 +431,20 @@ CFDictionaryRef SecAssessmentCopyUpdate(CFTypeRef target, result = xpcEngineUpdate(target, flags, ctx); } - if (__esp_enabled() && (flags & kSecAssessmentFlagDirect)) { - CFTemp dict("{target=%O, flags=%d, context=%O, outcome=%O}", target, flags, context, (CFDictionaryRef)result); - __esp_notify_ns("cs-assessment-update", (void *)(CFDictionaryRef)dict); - } - traceUpdate(target, context, result); return result.yield(); END_CSAPI_ERRORS1(NULL) } +static Boolean +updateAuthority(const char *authority, bool enable, CFErrorRef *errors) +{ + CFStringRef updateValue = enable ? kSecAssessmentUpdateOperationEnable : kSecAssessmentUpdateOperationDisable; + CFTemp ctx("{%O=%s, %O=%O}", kSecAssessmentUpdateKeyLabel, authority, kSecAssessmentContextKeyUpdate, updateValue); + return SecAssessmentUpdate(NULL, kSecCSDefaultFlags, ctx, errors); +} + // // The fcntl of System Policies. @@ -475,9 +454,6 @@ Boolean SecAssessmentControl(CFStringRef control, void *arguments, CFErrorRef *e { BEGIN_CSAPI - CFTemp dict("{control=%O}", control); - esp_do_check("cs-assessment-control", dict); - if (CFEqual(control, CFSTR("ui-enable"))) { setAssessment(true); MessageTrace trace("com.apple.security.assessment.state", "enable"); @@ -496,14 +472,13 @@ Boolean SecAssessmentControl(CFStringRef control, void *arguments, CFErrorRef *e result = kCFBooleanTrue; return true; } else if (CFEqual(control, CFSTR("ui-enable-devid"))) { - CFTemp ctx("{%O=%s, %O=%O}", kSecAssessmentUpdateKeyLabel, "Developer ID", kSecAssessmentContextKeyUpdate, kSecAssessmentUpdateOperationEnable); - SecAssessmentUpdate(NULL, kSecCSDefaultFlags, ctx, errors); + updateAuthority("Developer ID", true, errors); + updateAuthority("Notarized Developer ID", true, errors); MessageTrace trace("com.apple.security.assessment.state", "enable-devid"); trace.send("enable Developer ID approval"); return true; } else if (CFEqual(control, CFSTR("ui-disable-devid"))) { - CFTemp ctx("{%O=%s, %O=%O}", kSecAssessmentUpdateKeyLabel, "Developer ID", kSecAssessmentContextKeyUpdate, kSecAssessmentUpdateOperationDisable); - SecAssessmentUpdate(NULL, kSecCSDefaultFlags, ctx, errors); + updateAuthority("Developer ID", false, errors); MessageTrace trace("com.apple.security.assessment.state", "disable-devid"); trace.send("disable Developer ID approval"); return true; @@ -517,6 +492,28 @@ Boolean SecAssessmentControl(CFStringRef control, void *arguments, CFErrorRef *e else result = kCFBooleanTrue; return true; + } else if (CFEqual(control, CFSTR("ui-enable-notarized"))) { + updateAuthority("Notarized Developer ID", true, errors); + updateAuthority("Unnotarized Developer ID", true, errors); + MessageTrace trace("com.apple.security.assessment.state", "enable-notarized"); + trace.send("enable Notarized Developer ID approval"); + return true; + } else if (CFEqual(control, CFSTR("ui-disable-notarized"))) { + updateAuthority("Notarized Developer ID", false, errors); + updateAuthority("Unnotarized Developer ID", false, errors); + MessageTrace trace("com.apple.security.assessment.state", "disable-notarized"); + trace.send("disable Notarized Developer ID approval"); + return true; + } else if (CFEqual(control, CFSTR("ui-get-notarized"))) { + xpcEngineCheckNotarized((CFBooleanRef*)(arguments)); + return true; + } else if (CFEqual(control, CFSTR("ui-get-notarized-local"))) { + CFBooleanRef &result = *(CFBooleanRef*)(arguments); + if (gEngine().value("SELECT disabled FROM authority WHERE label = 'Notarized Developer ID';", true)) + result = kCFBooleanFalse; + else + result = kCFBooleanTrue; + return true; } else if (CFEqual(control, CFSTR("ui-record-reject"))) { // send this through syspolicyd for update validation xpcEngineRecord(CFDictionaryRef(arguments)); @@ -544,3 +541,51 @@ Boolean SecAssessmentControl(CFStringRef control, void *arguments, CFErrorRef *e END_CSAPI_ERRORS1(false) } + +Boolean SecAssessmentTicketRegister(CFDataRef ticketData, CFErrorRef *errors) +{ + BEGIN_CSAPI + + xpcEngineTicketRegister(ticketData); + return true; + + END_CSAPI_ERRORS1(false) +} + +Boolean SecAssessmentRegisterPackageTicket(CFURLRef packageURL, CFErrorRef* errors) +{ + BEGIN_CSAPI + + string path = cfString(packageURL); + Xar xar(path.c_str()); + + if (!xar) { + MacOSError::throwMe(errSecParam); + } + + xar.registerStapledNotarization(); + return true; + + END_CSAPI_ERRORS1(false) +} + +Boolean SecAssessmentTicketLookup(CFDataRef hash, SecCSDigestAlgorithm hashType, SecAssessmentTicketFlags flags, double *date, CFErrorRef *errors) +{ + BEGIN_CSAPI + + xpcEngineTicketLookup(hash, hashType, flags, date); + return true; + + END_CSAPI_ERRORS1(false) +} + +Boolean SecAssessmentLegacyCheck(CFDataRef hash, SecCSDigestAlgorithm hashType, CFStringRef teamID, CFErrorRef *errors) +{ + BEGIN_CSAPI + + xpcEngineLegacyCheck(hash, hashType, teamID); + return true; + + END_CSAPI_ERRORS1(false) +} + diff --git a/OSX/libsecurity_codesigning/lib/SecAssessment.h b/OSX/libsecurity_codesigning/lib/SecAssessment.h index efc6dd4a0..59d5fa8d7 100644 --- a/OSX/libsecurity_codesigning/lib/SecAssessment.h +++ b/OSX/libsecurity_codesigning/lib/SecAssessment.h @@ -24,6 +24,7 @@ #define _H_SECASSESSMENT #include +#include #ifdef __cplusplus extern "C" { @@ -156,6 +157,7 @@ extern CFStringRef kSecAssessmentAssessmentAuthorityRow; // (internal) extern CFStringRef kSecAssessmentAssessmentAuthorityOverride; // (internal) extern CFStringRef kSecAssessmentAssessmentAuthorityOriginalVerdict; // (internal) extern CFStringRef kSecAssessmentAssessmentAuthorityFlags; // (internal) +extern CFStringRef kSecAssessmentAssessmentNotarizationDate; // (internal) extern CFStringRef kDisabledOverride; // AuthorityOverride value for "Gatekeeper is disabled" @@ -312,6 +314,19 @@ Boolean SecAssessmentUpdate(CFTypeRef target, */ Boolean SecAssessmentControl(CFStringRef control, void *arguments, CFErrorRef *errors); +/* + * SecAssessmentTicket SPI + */ +typedef uint64_t SecAssessmentTicketFlags; +enum { + kSecAssessmentTicketFlagDefault = 0, // default behavior, offline check + kSecAssessmentTicketFlagForceOnlineCheck = 1 << 0, // force an online check + kSecAssessmentTicketFlagLegacyListCheck = 1 << 1, // Check the DeveloperID Legacy list +}; +Boolean SecAssessmentTicketRegister(CFDataRef ticketData, CFErrorRef *errors); +Boolean SecAssessmentRegisterPackageTicket(CFURLRef packageURL, CFErrorRef* errors) API_AVAILABLE(macos(10.14.6)); +Boolean SecAssessmentTicketLookup(CFDataRef hash, SecCSDigestAlgorithm hashType, SecAssessmentTicketFlags flags, double *date, CFErrorRef *errors); +Boolean SecAssessmentLegacyCheck(CFDataRef hash, SecCSDigestAlgorithm hashType, CFStringRef teamID, CFErrorRef *errors); #ifdef __cplusplus } diff --git a/OSX/libsecurity_codesigning/lib/SecCode.cpp b/OSX/libsecurity_codesigning/lib/SecCode.cpp index 7cf857401..2a494dc7e 100644 --- a/OSX/libsecurity_codesigning/lib/SecCode.cpp +++ b/OSX/libsecurity_codesigning/lib/SecCode.cpp @@ -159,6 +159,7 @@ const CFStringRef kSecGuestAttributeDynamicCodeInfoPlist = CFSTR("dynamicCodeInf const CFStringRef kSecGuestAttributeArchitecture = CFSTR("architecture"); const CFStringRef kSecGuestAttributeSubarchitecture = CFSTR("subarchitecture"); +#if TARGET_OS_OSX OSStatus SecCodeCopyGuestWithAttributes(SecCodeRef hostRef, CFDictionaryRef attributes, SecCSFlags flags, SecCodeRef *guestRef) { @@ -178,7 +179,8 @@ OSStatus SecCodeCopyGuestWithAttributes(SecCodeRef hostRef, // -// Shorthand for getting the SecCodeRef for a UNIX process +// Deprecated since 10.6, DO NOT USE. This can be raced. +// Use SecCodeCreateWithAuditToken instead. // OSStatus SecCodeCreateWithPID(pid_t pid, SecCSFlags flags, SecCodeRef *processRef) { @@ -193,6 +195,26 @@ OSStatus SecCodeCreateWithPID(pid_t pid, SecCSFlags flags, SecCodeRef *processRe END_CSAPI } +// +// Shorthand for getting the SecCodeRef for a UNIX process +// +OSStatus SecCodeCreateWithAuditToken(const audit_token_t *audit, + SecCSFlags flags, SecCodeRef *processRef) +{ + BEGIN_CSAPI + + checkFlags(flags); + CFRef auditData = makeCFData(audit, sizeof(audit_token_t)); + if (SecCode *guest = KernelCode::active()->locateGuest(CFTemp("{%O=%O}", kSecGuestAttributeAudit, auditData.get()))) { + CodeSigning::Required(processRef) = guest->handle(false); + } else { + return errSecCSNoSuchCode; + } + + END_CSAPI +} +#endif // TARGET_OS_OSX + // // Check validity of an Code @@ -211,8 +233,10 @@ OSStatus SecCodeCheckValidityWithErrors(SecCodeRef codeRef, SecCSFlags flags, checkFlags(flags, kSecCSConsiderExpiration | kSecCSStrictValidate + | kSecCSStrictValidateStructure | kSecCSRestrictSidebandData - | kSecCSEnforceRevocationChecks); + | kSecCSEnforceRevocationChecks + ); SecPointer code = SecCode::required(codeRef); code->checkValidity(flags); if (const SecRequirement *req = SecRequirement::optional(requirementRef)) @@ -255,18 +279,22 @@ const CFStringRef kSecCodeInfoTimestamp = CFSTR("signing-timestamp"); const CFStringRef kSecCodeInfoTrust = CFSTR("trust"); const CFStringRef kSecCodeInfoUnique = CFSTR("unique"); const CFStringRef kSecCodeInfoCdHashes = CFSTR("cdhashes"); - +const CFStringRef kSecCodeInfoCdHashesFull = CFSTR("cdhashes-full"); +const CFStringRef kSecCodeInfoRuntimeVersion = CFSTR("runtime-version"); const CFStringRef kSecCodeInfoCodeDirectory = CFSTR("CodeDirectory"); const CFStringRef kSecCodeInfoCodeOffset = CFSTR("CodeOffset"); const CFStringRef kSecCodeInfoDiskRepInfo = CFSTR("DiskRepInfo"); const CFStringRef kSecCodeInfoResourceDirectory = CFSTR("ResourceDirectory"); +const CFStringRef kSecCodeInfoNotarizationDate = CFSTR("NotarizationDate"); +const CFStringRef kSecCodeInfoCMSDigestHashType = CFSTR("CMSDigestHashType"); +const CFStringRef kSecCodeInfoCMSDigest = CFSTR("CMSDigest"); /* DiskInfoRepInfo types */ -const CFStringRef kSecCodeInfoDiskRepOSPlatform = CFSTR("OSPlatform"); -const CFStringRef kSecCodeInfoDiskRepOSVersionMin = CFSTR("OSVersionMin"); -const CFStringRef kSecCodeInfoDiskRepOSSDKVersion = CFSTR("SDKVersion"); -const CFStringRef kSecCodeInfoDiskRepNoLibraryValidation = CFSTR("NoLibraryValidation"); +const CFStringRef kSecCodeInfoDiskRepVersionPlatform = CFSTR("VersionPlatform"); +const CFStringRef kSecCodeInfoDiskRepVersionMin = CFSTR("VersionMin"); +const CFStringRef kSecCodeInfoDiskRepVersionSDK = CFSTR("VersionSDK"); +const CFStringRef kSecCodeInfoDiskRepNoLibraryValidation = CFSTR("NoLibraryValidation"); OSStatus SecCodeCopySigningInformation(SecStaticCodeRef codeRef, SecCSFlags flags, @@ -280,7 +308,8 @@ OSStatus SecCodeCopySigningInformation(SecStaticCodeRef codeRef, SecCSFlags flag | kSecCSRequirementInformation | kSecCSDynamicInformation | kSecCSContentInformation - | kSecCSSkipResourceDirectory); + | kSecCSSkipResourceDirectory + | kSecCSCalculateCMSDigest); SecPointer code = SecStaticCode::requiredStatic(codeRef); CFRef info = code->signingInformation(flags); diff --git a/OSX/libsecurity_codesigning/lib/SecCode.h b/OSX/libsecurity_codesigning/lib/SecCode.h index 1f0f831d1..aa53b5acc 100644 --- a/OSX/libsecurity_codesigning/lib/SecCode.h +++ b/OSX/libsecurity_codesigning/lib/SecCode.h @@ -51,9 +51,7 @@ CFTypeID SecCodeGetTypeID(void); Obtains a SecCode object for the code making the call. The calling code is determined in a way that is subject to modification over time, but obeys the following rules. If it is a UNIX process, its process id (pid) - is always used. If it is an active code host that has a dedicated guest, such a guest - is always preferred. If it is a host that has called SecHostSelectGuest, such selection - is considered until revoked. + is always used. @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. @param self Upon successful return, contains a SecCodeRef representing the caller. @@ -131,6 +129,7 @@ extern const CFStringRef kSecGuestAttributeDynamicCodeInfoPlist; extern const CFStringRef kSecGuestAttributeArchitecture; extern const CFStringRef kSecGuestAttributeSubarchitecture; +#if TARGET_OS_OSX /*! @function SecCodeCopyGuestWithAttributes This is the omnibus API function for obtaining dynamic code references. @@ -188,6 +187,7 @@ extern const CFStringRef kSecGuestAttributeSubarchitecture; OSStatus SecCodeCopyGuestWithAttributes(SecCodeRef __nullable host, CFDictionaryRef __nullable attributes, SecCSFlags flags, SecCodeRef * __nonnull CF_RETURNS_RETAINED guest); +#endif // TARGET_OS_OSX /*! @@ -425,7 +425,8 @@ CF_ENUM(uint32_t) { kSecCSRequirementInformation = 1 << 2, kSecCSDynamicInformation = 1 << 3, kSecCSContentInformation = 1 << 4, - kSecCSSkipResourceDirectory = 1 << 5 + kSecCSSkipResourceDirectory = 1 << 5, + kSecCSCalculateCMSDigest = 1 << 6, }; /* flag required to get this value */ extern const CFStringRef kSecCodeInfoCertificates; /* Signing */ @@ -453,6 +454,7 @@ extern const CFStringRef kSecCodeInfoTimestamp; /* Signing */ extern const CFStringRef kSecCodeInfoTrust; /* Signing */ extern const CFStringRef kSecCodeInfoUnique; /* generic */ extern const CFStringRef kSecCodeInfoCdHashes; /* generic */ +extern const CFStringRef kSecCodeInfoRuntimeVersion; /*generic */ OSStatus SecCodeCopySigningInformation(SecStaticCodeRef code, SecCSFlags flags, CFDictionaryRef * __nonnull CF_RETURNS_RETAINED information); diff --git a/OSX/libsecurity_codesigning/lib/SecCodeHost.cpp b/OSX/libsecurity_codesigning/lib/SecCodeHost.cpp index 7de4bf901..b678a71f7 100644 --- a/OSX/libsecurity_codesigning/lib/SecCodeHost.cpp +++ b/OSX/libsecurity_codesigning/lib/SecCodeHost.cpp @@ -33,32 +33,13 @@ using namespace CodeSigning; -// -// Munge a CFDictionary into a CssmData representing its plist -// -class DictData : public CFRef { -public: - DictData(CFDictionaryRef dict) : CFRef(makeCFData(dict)) { } - - operator CssmData() const - { - if (*this) - return CssmData::wrap(CFDataGetBytePtr(*this), CFDataGetLength(*this)); - else - return CssmData(); - } -}; - - OSStatus SecHostCreateGuest(SecGuestRef host, uint32_t status, CFURLRef path, CFDictionaryRef attributes, SecCSFlags flags, SecGuestRef *newGuest) { BEGIN_CSAPI - checkFlags(flags, kSecCSDedicatedHost | kSecCSGenerateGuestHash); - CodeSigning::Required(newGuest) = SecurityServer::ClientSession().createGuest(host, - status, cfString(path).c_str(), CssmData(), DictData(attributes), flags); + MacOSError::throwMe(errSecCSNotSupported); END_CSAPI } @@ -67,9 +48,8 @@ OSStatus SecHostRemoveGuest(SecGuestRef host, SecGuestRef guest, SecCSFlags flag { BEGIN_CSAPI - checkFlags(flags); - SecurityServer::ClientSession().removeGuest(host, guest); - + MacOSError::throwMe(errSecCSNotSupported); + END_CSAPI } @@ -77,9 +57,8 @@ OSStatus SecHostSelectGuest(SecGuestRef guestRef, SecCSFlags flags) { BEGIN_CSAPI - checkFlags(flags); - SecurityServer::ClientSession().selectGuest(guestRef); - + MacOSError::throwMe(errSecCSNotSupported); + END_CSAPI } @@ -88,9 +67,8 @@ OSStatus SecHostSelectedGuest(SecCSFlags flags, SecGuestRef *guestRef) { BEGIN_CSAPI - checkFlags(flags); - CodeSigning::Required(guestRef) = SecurityServer::ClientSession().selectedGuest(); - + MacOSError::throwMe(errSecCSNotSupported); + END_CSAPI } @@ -100,9 +78,8 @@ OSStatus SecHostSetGuestStatus(SecGuestRef guestRef, { BEGIN_CSAPI - checkFlags(flags); - SecurityServer::ClientSession().setGuestStatus(guestRef, status, DictData(attributes)); - + MacOSError::throwMe(errSecCSNotSupported); + END_CSAPI } @@ -110,8 +87,7 @@ OSStatus SecHostSetHostingPort(mach_port_t hostingPort, SecCSFlags flags) { BEGIN_CSAPI - checkFlags(flags); - SecurityServer::ClientSession().registerHosting(hostingPort, flags); - + MacOSError::throwMe(errSecCSNotSupported); + END_CSAPI } diff --git a/OSX/libsecurity_codesigning/lib/SecCodeHost.h b/OSX/libsecurity_codesigning/lib/SecCodeHost.h index 7e462af46..ea61aa24e 100644 --- a/OSX/libsecurity_codesigning/lib/SecCodeHost.h +++ b/OSX/libsecurity_codesigning/lib/SecCodeHost.h @@ -21,22 +21,6 @@ * @APPLE_LICENSE_HEADER_END@ */ -/*! - @header SecCodeHost - This header provides the hosting API for Code Signing. These are calls - that are (only) made by code that is hosting guests. - In the context of Code Signing, a Host is code that creates and manages other - codes from which it defends its own integrity. As part of that duty, it maintains - state for each of its children, and answers questions about them. - - A Host is externally represented by a SecCodeRef (it is a SecCode object). - So is a Guest. There is no specific API object to represent Hosts or Guests. - Within the Hosting API, guests are identified by simple numeric handles that - are unique and valid only in the context of their specific host. - - The functions in this API always apply to the Host making the API calls. - They cannot be used to (directly) interrogate another host. -*/ #ifndef _H_SECCODEHOST #define _H_SECCODEHOST @@ -48,87 +32,6 @@ extern "C" { CF_ASSUME_NONNULL_BEGIN -/*! - @header SecCodeHost - This header describes the Code Signing Hosting API. These are calls made - by code that wishes to become a Host in the Code Signing Host/Guest infrastructure. - Hosting allows the caller to establish separate, independent code identities - (SecCodeRefs) for parts of itself, usually because it is loading and managing - code in the form of scripts, plugins, etc. - - The Hosting API does not directly connect to the Code Signing Client APIs. - Certain calls in the client API will cause internal queries to hosts about their - guests. The Host side of these queries is managed through this API. The results - will eventually be delivered to client API callers in appropriate form. - - If code never calls any of the Hosting API functions, it is deemed to not have - guests and not act as a Host. This is the default and requires no action. - - Hosting operates in one of two modes, dynamic or proxy. Whichever mode is first - engaged prevails for the lifetime of the caller. There is no way to switch between - the two, and calling an API belonging to the opposite mode will fail. - - In dynamic hosting mode, the caller provides a Mach port that receives direct - queries about its guests. Dynamic mode is engaged by calling SecHostSetHostingPort. - - In proxy hosting mode, the caller provides information about its guests as - guests are created, removed, or change status. The system caches this information - and answers queries about guests from this pool of information. The caller is not - directly involved in answering such queries, and has no way to intervene. -*/ - - -/*! - @function SecHostCreateGuest - Create a new Guest and describe its initial properties. - - This call activates Hosting Proxy Mode. From here on, the system will record - guest information provided through SecHostCreateGuest, SecHostSetGuestStatus, and - SecHostRemoveGuest, and report hosting status to callers directly. This mode - is incompatible with dynamic host mode as established by a call to SecHostSetHostingPort. - - @param host Pass kSecNoGuest to create a guest of the process itself. - To create a guest of another guest (extending the hosting chain), pass the SecGuestRef - of the guest to act as the new guest's host. If host has a dedicated guest, - it will be deemed to be be the actual host, recursively. - @param status The Code Signing status word for the new guest. These are combinations - of the kSecCodeStatus* flags in . Note that the proxy will enforce - the rules for the stickiness of these bits. In particular, if you don't pass the - kSecCodeStatusValid bit during creation, your new guest will be born invalid and will - never have a valid identity. - @param path The canonical path to the guest's code on disk. This is the path you would - pass to SecStaticCodeCreateWithPath to make a static code object reference. You must - use an absolute path. - @param attributes An optional CFDictionaryRef containing attributes that can be used - to locate this particular guest among all of the caller's guests. The "canonical" - attribute is automatically added for the value of guestRef. If you pass NULL, - no other attributes are established for the guest. - While any key can be used in the attributes dictionary, the kSecGuestAttribute* constants - (in SecCode.h) are conventionally used here. - @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior, or - a combination of the flags defined below for special features. - @result Upon success, errSecSuccess. Upon error, an OSStatus value documented in - CSCommon.h or certain other Security framework headers. - @param newGuest Upon successful creation of the new guest, the new SecGuestRef - that should be used to identify the new guest from here on. - - @constant kSecCSDedicatedHost Declares dedicated hosting for the given host. - In dedicated hosting, the host has exactly one guest (the one this call is - introducing), and the host will spend all of its time from here on running - that guest (or on its behalf). This declaration is irreversable for the lifetime - of the host. Note that this is a declaration about the given host, and is not - binding upon other hosts on either side of the hosting chain, though they in turn - may declare dedicated hosting if desired. - It is invalid to declare dedicated hosting if other guests have already been - introduced for this host, and it is invalid to introduce additional guests - for this host after this call. - @constant kSecCSGenerateGuestHash Ask the proxy to generate the binary identifier - (hash of CodeDirectory) from the copy on disk at the path given. This is not optimal - since an attacker with write access may be able to substitute a different copy just - in time, but it is convenient. For optimal security, the host should calculate the - hash from the loaded in-memory signature of its guest and pass the result as an - attribute with key kSecGuestAttributeHash. -*/ CF_ENUM(uint32_t) { kSecCSDedicatedHost = 1 << 0, kSecCSGenerateGuestHash = 1 << 1, @@ -136,104 +39,20 @@ CF_ENUM(uint32_t) { OSStatus SecHostCreateGuest(SecGuestRef host, uint32_t status, CFURLRef path, CFDictionaryRef __nullable attributes, - SecCSFlags flags, SecGuestRef * __nonnull newGuest); - - -/*! - @function SecHostRemoveGuest - Announce that the guest with the given guestRef has permanently disappeared. - It removes all memory of the guest from the hosting system. You cannot remove - a dedicated guest. - - @param host The SecGuestRef that was used to create guest. You cannot specify - a proximate host (host of a host) here. However, the substitution for dedicated - guests described for SecHostCreateGuest also takes place here. - @param guest The handle for a Guest previously created with SecHostCreateGuest - that has not previously been destroyed. This guest is to be destroyed now. - @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. - @result Upon success, errSecSuccess. Upon error, an OSStatus value documented in - CSCommon.h or certain other Security framework headers. -*/ -OSStatus SecHostRemoveGuest(SecGuestRef host, SecGuestRef guest, SecCSFlags flags); - - -/*! - @function SecHostSelectGuest - Tell the Code Signing host subsystem that the calling thread will now act - on behalf of the given Guest. This must be a valid Guest previously created - with SecHostCreateGuest. - - @param guestRef The handle for a Guest previously created with SecHostCreateGuest - on whose behalf this thread will act from now on. This setting will be remembered - until it is changed (or the thread terminates). - To indicate that the thread will act on behalf of the Host itself (rather than - any Guest), pass kSecNoGuest. - @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. - @result Upon success, errSecSuccess. Upon error, an OSStatus value documented in - CSCommon.h or certain other Security framework headers. -*/ -OSStatus SecHostSelectGuest(SecGuestRef guestRef, SecCSFlags flags); - - -/*! - @function SecHostSelectedGuest - Retrieve the handle for the Guest currently selected for the calling thread. - - @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. - @param guestRef Will be assigned the SecGuestRef currently in effect for - the calling thread. If no Guest is active on this thread (i.e. the thread - is acting for the Host), the return value is kSecNoGuest. - @result Upon success, errSecSuccess. Upon error, an OSStatus value documented in - CSCommon.h or certain other Security framework headers. -*/ -OSStatus SecHostSelectedGuest(SecCSFlags flags, SecGuestRef * __nonnull guestRef); - - -/*! - @function SecHostSetGuestStatus - Updates the status of a particular guest. - - @param guestRef The handle for a Guest previously created with SecHostCreateGuest - on whose behalf this thread will act from now on. This setting will be remembered - until it is changed (or the thread terminates). - @param status The new Code Signing status word for the guest. The proxy enforces - the restrictions on changes to guest status; in particular, the kSecCodeStatusValid bit can only - be cleared, and the kSecCodeStatusHard and kSecCodeStatusKill flags can only be set. Pass the previous - guest status to indicate that no change is desired. - @param attributes An optional dictionary containing attributes to be used to distinguish - this guest from all guests of the caller. If given, it completely replaces the attributes - specified earlier. If NULL, previously established attributes are retained. - @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. - @result Upon success, errSecSuccess. Upon error, an OSStatus value documented in - CSCommon.h or certain other Security framework headers. - */ + SecCSFlags flags, SecGuestRef * __nonnull newGuest) +AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6; +OSStatus SecHostRemoveGuest(SecGuestRef host, SecGuestRef guest, SecCSFlags flags) +AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6; +OSStatus SecHostSelectGuest(SecGuestRef guestRef, SecCSFlags flags) +AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6; +OSStatus SecHostSelectedGuest(SecCSFlags flags, SecGuestRef * __nonnull guestRef) +AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6; OSStatus SecHostSetGuestStatus(SecGuestRef guestRef, uint32_t status, CFDictionaryRef __nullable attributes, - SecCSFlags flags); - - -/*! - @function SecHostSetHostingPort - Tells the Code Signing Hosting subsystem that the calling code will directly respond - to hosting inquiries over the given port. - - This API should be the first hosting API call made. With it, the calling code takes - direct responsibility for answering questions about its guests using the hosting IPC - services. The SecHostCreateGuest, SecHostDestroyGuest and SecHostSetGuestStatus calls - are not valid after this. The SecHostSelectGuest and SecHostSelectedGuest calls will - still work, and will use whatever SecGuestRefs the caller has assigned in its internal - data structures. - - This call cannot be undone; once it is made, record-and-forward facilities are - disabled for the lifetime of the calling code. - - @param hostingPort A Mach message port with send rights. This port will be recorded - and handed to parties interested in querying the host about its children. - @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. - @result Upon success, errSecSuccess. Upon error, an OSStatus value documented in - CSCommon.h or certain other Security framework headers. - */ -OSStatus SecHostSetHostingPort(mach_port_t hostingPort, SecCSFlags flags); + SecCSFlags flags) + AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6; +OSStatus SecHostSetHostingPort(mach_port_t hostingPort, SecCSFlags flags) +AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6; CF_ASSUME_NONNULL_END diff --git a/OSX/libsecurity_codesigning/lib/SecCodeHostLib.c b/OSX/libsecurity_codesigning/lib/SecCodeHostLib.c deleted file mode 100644 index 447745236..000000000 --- a/OSX/libsecurity_codesigning/lib/SecCodeHostLib.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2007,2011 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 "SecCodeHost.h" -#include "SecCodeHostLib.h" -#include -#include -#include -#include - - -// -// Global state -// -mach_port_t gServerPort; -SecCSFlags gInitFlags; - - -// -// Framing macros and facilities -// -#define UCSP_ARGS gServerPort, mig_get_reply_port(), &securitydCreds, &rcode -#define ATTRDATA(attr) (void *)(attr), (attr) ? strlen((attr)) : 0 - -#define CALL(func) \ - security_token_t securitydCreds; \ - CSSM_RETURN rcode; \ - if (KERN_SUCCESS != func) \ - return errSecCSInternalError; \ - if (securitydCreds.val[0] != 0) \ - return CSSM_ERRCODE_VERIFICATION_FAILURE; \ - return rcode - - - -// -// Mandatory initialization call -// -OSStatus SecHostLibInit(SecCSFlags flags) -{ - if (gServerPort != MACH_PORT_NULL) // re-initialization attempt - return errSecCSInternalError; - - mach_port_t bootstrapPort; - if (KERN_SUCCESS != task_get_bootstrap_port(mach_task_self(), &bootstrapPort)) - return errSecCSInternalError; - static char serverName[BOOTSTRAP_MAX_NAME_LEN] = SECURITYSERVER_BOOTSTRAP_NAME; - if (KERN_SUCCESS != bootstrap_look_up(bootstrapPort, serverName, &gServerPort)) - return errSecCSInternalError; - - ClientSetupInfo info = { 0x1234, SSPROTOVERSION }; - CALL(ucsp_client_setup(UCSP_ARGS, mach_task_self(), info, "?:unspecified")); -} - - -// -// Guest creation. -// At this time, this ONLY supports the creation of (one) dedicated guest. -// -OSStatus SecHostLibCreateGuest(SecGuestRef host, - uint32_t status, const char *path, const char *attributeXML, - SecCSFlags flags, SecGuestRef *newGuest) -{ - return SecHostLibCreateGuest2(host, status, path, "", 0, attributeXML, flags, newGuest); -} - -OSStatus SecHostLibCreateGuest2(SecGuestRef host, - uint32_t status, const char *path, const void *cdhash, size_t cdhashLength, const char *attributeXML, - SecCSFlags flags, SecGuestRef *newGuest) -{ - if (flags != kSecCSDedicatedHost) - return errSecCSInvalidFlags; - - CALL(ucsp_client_createGuest(UCSP_ARGS, host, status, path, - (void *)cdhash, cdhashLength, ATTRDATA(attributeXML), flags, newGuest)); -} - - -// -// Update the status of a guest. -// -OSStatus SecHostLibSetGuestStatus(SecGuestRef guestRef, - uint32_t status, const char *attributeXML, - SecCSFlags flags) -{ - CALL(ucsp_client_setGuestStatus(UCSP_ARGS, guestRef, status, ATTRDATA(attributeXML))); -} - - -// -// Enable dynamic hosting mode. -// -OSStatus SecHostSetHostingPort(mach_port_t hostingPort, SecCSFlags flags) -{ - CALL(ucsp_client_registerHosting(UCSP_ARGS, hostingPort, flags)); -} - - -// -// Helper for checked incorporation of code. -// -OSStatus SecHostLibCheckLoad(const char *path, SecRequirementType type) -{ - CALL(ucsp_client_helpCheckLoad(UCSP_ARGS, path, type)); -} diff --git a/OSX/libsecurity_codesigning/lib/SecCodeHostLib.h b/OSX/libsecurity_codesigning/lib/SecCodeHostLib.h deleted file mode 100644 index 3cceb306f..000000000 --- a/OSX/libsecurity_codesigning/lib/SecCodeHostLib.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2007,2011 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 SecCodeHostLib - This header provides a subset of the hosting API for Code Signing. - This subset functionality is implemented as a static library written - entirely in C, and depends on nothing except the system library and the - C runtime. It is thus suitable to be used by low-level libraries and - other such system facilities. On the other hand, it does not provide the - full functionality of . - - This file is documented as a delta to , which - you should consult as a baseline. -*/ -#ifndef _H_SECCODEHOSTLIB -#define _H_SECCODEHOSTLIB - -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -/*! - @function SecHostLibInit - This function must be called first to use the SecCodeHostLib facility. - */ -OSStatus SecHostLibInit(SecCSFlags flags); - - -/*! - @function SecHostLibCreateGuest - This function declares a code host, engages hosting proxy services for it, - and creates a guest with given attributes and state. - - NOTE: This version of the function currently only supports dedicated hosting. - If you do not pass the kSecCSDedicatedHost flag, the call will fail. - */ -OSStatus SecHostLibCreateGuest(SecGuestRef host, - uint32_t status, const char *path, const char *attributeXML, - SecCSFlags flags, SecGuestRef *newGuest) DEPRECATED_ATTRIBUTE; - -OSStatus SecHostLibCreateGuest2(SecGuestRef host, - uint32_t status, const char *path, const void *cdhash, size_t cdhashLength, const char *attributeXML, - SecCSFlags flags, SecGuestRef *newGuest); - - -/*! - @function SecHostLibSetGuestStatus - This function can change the state or attributes (or both) of a given guest. - It performs all the work of SecHostSetGuestStatus. - */ -OSStatus SecHostLibSetGuestStatus(SecGuestRef guestRef, - uint32_t status, const char *attributeXML, - SecCSFlags flags); - - -/*! - @function SecHostLibSetHostingPort - Register a Mach port to receive hosting queries on. This enables (and locks) - dynamic hosting mode, and is incompatible with all proxy-mode calls. - You still must call SecHostLibInit first. - */ -OSStatus SecHostSetHostingPort(mach_port_t hostingPort, SecCSFlags flags); - - -/* - Functionality from SecCodeHost.h that is genuinely missing here: - -OSStatus SecHostRemoveGuest(SecGuestRef host, SecGuestRef guest, SecCSFlags flags); - -OSStatus SecHostSelectGuest(SecGuestRef guestRef, SecCSFlags flags); - -OSStatus SecHostSelectedGuest(SecCSFlags flags, SecGuestRef *guestRef); - -*/ - - -/*! - */ -OSStatus SecHostLibCheckLoad(const char *path, SecRequirementType type); - - -#ifdef __cplusplus -} -#endif - -#endif //_H_SECCODEHOSTLIB diff --git a/OSX/libsecurity_codesigning/lib/SecCodePriv.h b/OSX/libsecurity_codesigning/lib/SecCodePriv.h index 810383429..f4d8e2a7a 100644 --- a/OSX/libsecurity_codesigning/lib/SecCodePriv.h +++ b/OSX/libsecurity_codesigning/lib/SecCodePriv.h @@ -38,16 +38,19 @@ extern "C" { /* * Private constants for SecCodeCopySigningInformation. - * These are returned with the */ +extern const CFStringRef kSecCodeInfoCdHashesFull; /* Internal */ extern const CFStringRef kSecCodeInfoCodeDirectory; /* Internal */ extern const CFStringRef kSecCodeInfoCodeOffset; /* Internal */ extern const CFStringRef kSecCodeInfoDiskRepInfo; /* Internal */ extern const CFStringRef kSecCodeInfoResourceDirectory; /* Internal */ +extern const CFStringRef kSecCodeInfoNotarizationDate; /* Internal */ +extern const CFStringRef kSecCodeInfoCMSDigestHashType; /* Internal */ +extern const CFStringRef kSecCodeInfoCMSDigest; /* Internal */ -extern const CFStringRef kSecCodeInfoDiskRepOSPlatform; /* Number */ -extern const CFStringRef kSecCodeInfoDiskRepOSVersionMin; /* Number */ -extern const CFStringRef kSecCodeInfoDiskRepOSSDKVersion; /* Number */ +extern const CFStringRef kSecCodeInfoDiskRepVersionPlatform; /* Number */ +extern const CFStringRef kSecCodeInfoDiskRepVersionMin; /* Number */ +extern const CFStringRef kSecCodeInfoDiskRepVersionSDK; /* Number */ extern const CFStringRef kSecCodeInfoDiskRepNoLibraryValidation; /* String */ /*! @@ -126,24 +129,28 @@ OSStatus SecCodeCopyInternalRequirement(SecStaticCodeRef code, SecRequirementTyp SecCSFlags flags, SecRequirementRef *requirement); +#if TARGET_OS_OSX /*! - @function SecCodeCreateWithPID + @function SecCodeCreateWithAuditToken Asks the kernel to return a SecCode object for a process identified - by a UNIX process id (pid). This is a shorthand for asking SecGetRootCode() - for a guest whose "pid" attribute has the given pid value. + by a UNIX audit token. This is a shorthand for asking SecGetRootCode() + for a guest whose "audit" attribute has the given audit token. - This is a deprecated convenience function. - Call SecCodeCopyGuestWithAttributes instead. - - @param pid A process id for an existing UNIX process on the system. + @param audit A process audit token for an existing UNIX process on the system. @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. @param process On successful return, a SecCode object reference identifying the requesteed process. @result Upon success, errSecSuccess. Upon error, an OSStatus value documented in CSCommon.h or certain other Security framework headers. */ +OSStatus SecCodeCreateWithAuditToken(const audit_token_t *audit, + SecCSFlags flags, SecCodeRef *process) + AVAILABLE_MAC_OS_X_VERSION_10_15_AND_LATER; + +/* Deprecated and unsafe, DO NOT USE. */ OSStatus SecCodeCreateWithPID(pid_t pid, SecCSFlags flags, SecCodeRef *process) AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6; +#endif /* @@ -213,6 +220,18 @@ CFDataRef SecCodeCopyComponent(SecCodeRef code, int slot, CFDataRef hash); */ OSStatus SecCodeValidateFileResource(SecStaticCodeRef code, CFStringRef relativePath, CFDataRef fileData, SecCSFlags flags); + +/* + @constant kSecCSStrictValidateStructure + A subset of the work kSecCSStrictValidate performs, omitting work that + is unnecessary on some platforms. Since the definition of what can be + omitted is in flux, and since we would like to remove that notion + entirely eventually, we makes this a private flag. + */ +CF_ENUM(uint32_t) { + kSecCSStrictValidateStructure = 1 << 13, +}; + #ifdef __cplusplus } #endif diff --git a/OSX/libsecurity_codesigning/lib/SecCodeSigner.cpp b/OSX/libsecurity_codesigning/lib/SecCodeSigner.cpp index 7d83ce7a3..7e09f7604 100644 --- a/OSX/libsecurity_codesigning/lib/SecCodeSigner.cpp +++ b/OSX/libsecurity_codesigning/lib/SecCodeSigner.cpp @@ -59,6 +59,14 @@ const CFStringRef kSecCodeSignerTimestampOmitCertificates = CFSTR("timestamp-omi const CFStringRef kSecCodeSignerPreserveMetadata = CFSTR("preserve-metadata"); const CFStringRef kSecCodeSignerTeamIdentifier = CFSTR("teamidentifier"); const CFStringRef kSecCodeSignerPlatformIdentifier = CFSTR("platform-identifier"); +const CFStringRef kSecCodeSignerRuntimeVersion = CFSTR("runtime-version"); +const CFStringRef kSecCodeSignerPreserveAFSC = CFSTR("preserve-afsc"); +const CFStringRef kSecCodeSignerOmitAdhocFlag = CFSTR("omit-adhoc-flag"); + +// Keys for signature editing +const CFStringRef kSecCodeSignerEditCpuType = CFSTR("edit-cpu-type"); +const CFStringRef kSecCodeSignerEditCpuSubtype = CFSTR("edit-cpu-subtype"); +const CFStringRef kSecCodeSignerEditCMS = CFSTR("edit-cms"); @@ -82,14 +90,17 @@ OSStatus SecCodeSignerCreate(CFDictionaryRef parameters, SecCSFlags flags, BEGIN_CSAPI checkFlags(flags, - kSecCSRemoveSignature + kSecCSEditSignature + | kSecCSRemoveSignature | kSecCSSignPreserveSignature | kSecCSSignNestedCode | kSecCSSignOpaque | kSecCSSignV1 | kSecCSSignNoV1 | kSecCSSignBundleRoot - | kSecCSSignStrictPreflight); + | kSecCSSignStrictPreflight + | kSecCSSignGeneratePEH + | kSecCSSignGenerateEntitlementDER); SecPointer signer = new SecCodeSigner(flags); signer->parameters(parameters); CodeSigning::Required(signerRef) = signer->handle(); diff --git a/OSX/libsecurity_codesigning/lib/SecCodeSigner.h b/OSX/libsecurity_codesigning/lib/SecCodeSigner.h index 7b3704b2f..eba118306 100644 --- a/OSX/libsecurity_codesigning/lib/SecCodeSigner.h +++ b/OSX/libsecurity_codesigning/lib/SecCodeSigner.h @@ -135,6 +135,12 @@ CFTypeID SecCodeSignerGetTypeID(void); on the verifying system. The default is to embed enough certificates to ensure proper verification of Apple-generated timestamp signatures. + @constant kSecCodeSignerRuntimeVersion A CFString indicating the version of runtime hardening policies + that the process should be opted into. The string should be of the form "x", "x.x", or "x.x.x" where + x is a number between 0 and 255. This parameter is optional. If the signer specifies + kSecCodeSignatureRuntime but does not provide this parameter, the runtime version will be the SDK + version built into the Mach-O. + */ extern const CFStringRef kSecCodeSignerApplicationData; extern const CFStringRef kSecCodeSignerDetached; @@ -157,6 +163,12 @@ extern const CFStringRef kSecCodeSignerTimestampOmitCertificates; extern const CFStringRef kSecCodeSignerPreserveMetadata; extern const CFStringRef kSecCodeSignerTeamIdentifier; extern const CFStringRef kSecCodeSignerPlatformIdentifier; +extern const CFStringRef kSecCodeSignerRuntimeVersion; +extern const CFStringRef kSecCodeSignerPreserveAFSC; +extern const CFStringRef kSecCodeSignerOmitAdhocFlag; +extern const CFStringRef kSecCodeSignerEditCpuType; +extern const CFStringRef kSecCodeSignerEditCpuSubtype; +extern const CFStringRef kSecCodeSignerEditCMS; enum { kSecCodeSignerPreserveIdentifier = 1 << 0, // preserve signing identifier @@ -165,7 +177,9 @@ enum { kSecCodeSignerPreserveResourceRules = 1 << 3, // preserve resource rules (and thus resources) kSecCodeSignerPreserveFlags = 1 << 4, // preserve signing flags kSecCodeSignerPreserveTeamIdentifier = 1 << 5, // preserve team identifier flags - kSecCodeSignerPreserveDigestAlgorithm = 1 << 6, // preserve digest algorithms used + kSecCodeSignerPreserveDigestAlgorithm = 1 << 6, // preserve digest algorithms used + kSecCodeSignerPreservePEH = 1 << 7, // preserve pre-encryption hashes + kSecCodeSignerPreserveRuntime = 1 << 8, // preserve the runtime version }; @@ -179,7 +193,9 @@ enum { useful defaults, and will need to be set before signing is attempted. @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. The kSecCSRemoveSignature flag requests that any existing signature be stripped - from the target code instead of signing. + from the target code instead of signing. The kSecCSEditSignature flag + requests editing of existing signatures, which only works with a very + limited set of options. @param staticCode On successful return, a SecStaticCode object reference representing the file system origin of the given SecCode. On error, unchanged. @result Upon success, errSecSuccess. Upon error, an OSStatus value documented in @@ -194,6 +210,9 @@ enum { kSecCSSignNoV1 = 1 << 5, // do not include V1 form kSecCSSignBundleRoot = 1 << 6, // include files in bundle root kSecCSSignStrictPreflight = 1 << 7, // fail signing operation if signature would fail strict validation + kSecCSSignGeneratePEH = 1 << 8, // generate pre-encryption hashes + kSecCSSignGenerateEntitlementDER = 1 << 9, // generate entitlement DER + kSecCSEditSignature = 1 << 10, // edit existing signature }; diff --git a/OSX/libsecurity_codesigning/lib/SecRequirement.cpp b/OSX/libsecurity_codesigning/lib/SecRequirement.cpp index 932096a85..d89c92408 100644 --- a/OSX/libsecurity_codesigning/lib/SecRequirement.cpp +++ b/OSX/libsecurity_codesigning/lib/SecRequirement.cpp @@ -167,6 +167,10 @@ OSStatus SecRequirementCopyString(SecRequirementRef requirementRef, SecCSFlags f CFStringRef kSecRequirementKeyInfoPlist = CFSTR("requirement:eval:info"); CFStringRef kSecRequirementKeyEntitlements = CFSTR("requirement:eval:entitlements"); CFStringRef kSecRequirementKeyIdentifier = CFSTR("requirement:eval:identifier"); +CFStringRef kSecRequirementKeyPackageChecksum = CFSTR("requirement:eval:package_checksum"); +CFStringRef kSecRequirementKeyChecksumAlgorithm = CFSTR("requirement:eval:package_checksum_algorithm"); +CFStringRef kSecRequirementKeySecureTimestamp = CFSTR("requirement:eval:secure_timestamp"); +CFStringRef kSecRequirementKeyTeamIdentifier = CFSTR("requirement:eval:team_identifier"); OSStatus SecRequirementEvaluate(SecRequirementRef requirementRef, CFArrayRef certificateChain, CFDictionaryRef context, @@ -177,13 +181,32 @@ OSStatus SecRequirementEvaluate(SecRequirementRef requirementRef, const Requirement *req = SecRequirement::required(requirementRef)->requirement(); checkFlags(flags); CodeSigning::Required(certificateChain); - + + SecCSDigestAlgorithm checksumAlgorithm = kSecCodeSignatureNoHash; + if (context) { + CFRef num = (CFNumberRef)CFDictionaryGetValue(context, kSecRequirementKeyChecksumAlgorithm); + if (num) { + checksumAlgorithm = (SecCSDigestAlgorithm)cfNumber(num); + } + } + + const char *teamID = NULL; + if (context && CFDictionaryGetValue(context, kSecRequirementKeyTeamIdentifier)) { + CFStringRef str = (CFStringRef)CFDictionaryGetValue(context, kSecRequirementKeyTeamIdentifier); + teamID = CFStringGetCStringPtr(str, kCFStringEncodingUTF8); + } + Requirement::Context ctx(certificateChain, // mandatory context ? CFDictionaryRef(CFDictionaryGetValue(context, kSecRequirementKeyInfoPlist)) : NULL, context ? CFDictionaryRef(CFDictionaryGetValue(context, kSecRequirementKeyEntitlements)) : NULL, (context && CFDictionaryGetValue(context, kSecRequirementKeyIdentifier)) ? cfString(CFStringRef(CFDictionaryGetValue(context, kSecRequirementKeyIdentifier))) : "", - NULL // can't specify a CodeDirectory here + NULL, // can't specify a CodeDirectory here + context ? CFDataRef(CFDictionaryGetValue(context, kSecRequirementKeyPackageChecksum)) : NULL, + checksumAlgorithm, + false, // can't get forced platform this way + context ? CFDateRef(CFDictionaryGetValue(context, kSecRequirementKeySecureTimestamp)) : NULL, + teamID ); req->validate(ctx); @@ -204,13 +227,13 @@ OSStatus SecRequirementsCreateFromRequirements(CFDictionaryRef requirements, Sec if (requirements == NULL) return errSecCSObjectRequired; CFIndex count = CFDictionaryGetCount(requirements); - CFNumberRef keys[count]; - SecRequirementRef reqs[count]; - CFDictionaryGetKeysAndValues(requirements, (const void **)keys, (const void **)reqs); + vector keys_vector(count, NULL); + vector reqs_vector(count, NULL); + CFDictionaryGetKeysAndValues(requirements, (const void **)keys_vector.data(), (const void **)reqs_vector.data()); Requirements::Maker maker; for (CFIndex n = 0; n < count; n++) { - const Requirement *req = SecRequirement::required(reqs[n])->requirement(); - maker.add(cfNumber(keys[n]), req->clone()); + const Requirement *req = SecRequirement::required(reqs_vector[n])->requirement(); + maker.add(cfNumber(keys_vector[n]), req->clone()); } Requirements *reqset = maker.make(); // malloc'ed CodeSigning::Required(requirementSet) = makeCFDataMalloc(*reqset); // takes ownership of reqs diff --git a/OSX/libsecurity_codesigning/lib/SecRequirementPriv.h b/OSX/libsecurity_codesigning/lib/SecRequirementPriv.h index d40b1bec7..cc7ebddba 100644 --- a/OSX/libsecurity_codesigning/lib/SecRequirementPriv.h +++ b/OSX/libsecurity_codesigning/lib/SecRequirementPriv.h @@ -164,6 +164,11 @@ OSStatus SecRequirementCreateGroup(CFStringRef groupName, SecCertificateRef anch extern CFStringRef kSecRequirementKeyInfoPlist; extern CFStringRef kSecRequirementKeyEntitlements; extern CFStringRef kSecRequirementKeyIdentifier; +extern CFStringRef kSecRequirementKeyPackageChecksum; +extern CFStringRef kSecRequirementKeyChecksumAlgorithm; +extern CFStringRef kSecRequirementKeySecureTimestamp; +extern CFStringRef kSecRequirementKeyTeamIdentifier; + /*! @function SecRequirementEvaluate Explicitly evaluate a SecRequirementRef against context provided in the call. diff --git a/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp b/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp index 3d96abd05..b240b4b89 100644 --- a/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp +++ b/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp @@ -52,8 +52,8 @@ OSStatus SecStaticCodeCreateWithPath(CFURLRef path, SecCSFlags flags, SecStaticC { BEGIN_CSAPI - checkFlags(flags); - CodeSigning::Required(staticCodeRef) = (new SecStaticCode(DiskRep::bestGuess(cfString(path).c_str())))->handle(); + checkFlags(flags, kSecCSForceOnlineNotarizationCheck); + CodeSigning::Required(staticCodeRef) = (new SecStaticCode(DiskRep::bestGuess(cfString(path).c_str()), flags))->handle(); END_CSAPI } @@ -68,7 +68,7 @@ OSStatus SecStaticCodeCreateWithPathAndAttributes(CFURLRef path, SecCSFlags flag { BEGIN_CSAPI - checkFlags(flags); + checkFlags(flags, kSecCSForceOnlineNotarizationCheck); DiskRep::Context ctx; std::string version; // holds memory placed into ctx if (attributes) { @@ -87,7 +87,7 @@ OSStatus SecStaticCodeCreateWithPathAndAttributes(CFURLRef path, SecCSFlags flag ctx.version = version.c_str(); } - CodeSigning::Required(staticCodeRef) = (new SecStaticCode(DiskRep::bestGuess(cfString(path).c_str(), &ctx)))->handle(); + CodeSigning::Required(staticCodeRef) = (new SecStaticCode(DiskRep::bestGuess(cfString(path).c_str(), &ctx), flags))->handle(); END_CSAPI } @@ -117,11 +117,14 @@ OSStatus SecStaticCodeCheckValidityWithErrors(SecStaticCodeRef staticCodeRef, Se | kSecCSNoNetworkAccess | kSecCSCheckNestedCode | kSecCSStrictValidate + | kSecCSStrictValidateStructure | kSecCSRestrictSidebandData | kSecCSCheckGatekeeperArchitectures | kSecCSRestrictSymlinks | kSecCSRestrictToAppLike | kSecCSUseSoftwareSigningCert + | kSecCSValidatePEH + | kSecCSSingleThreaded ); if (errors) @@ -237,10 +240,38 @@ OSStatus SecCodeMapMemory(SecStaticCodeRef codeRef, SecCSFlags flags) checkFlags(flags); SecPointer code = SecStaticCode::requiredStatic(codeRef); if (const CodeDirectory *cd = code->codeDirectory(false)) { - fsignatures args = { static_cast(code->diskRep()->signingBase()), (void *)cd, cd->length() }; - UnixError::check(::fcntl(code->diskRep()->fd(), F_ADDSIGS, &args)); - } else + if (code->isDetached()) { + // Detached signatures need to attach their code directory from memory. + fsignatures args = { static_cast(code->diskRep()->signingBase()), (void *)cd, cd->length() }; + UnixError::check(::fcntl(code->diskRep()->fd(), F_ADDSIGS, &args)); + } else { + // All other signatures can simply point to the signature in the main executable. + Universal *execImage = code->diskRep()->mainExecutableImage(); + if (execImage == NULL) { + MacOSError::throwMe(errSecCSNoMainExecutable); + } + + auto_ptr arch(execImage->architecture()); + if (arch.get() == NULL) { + MacOSError::throwMe(errSecCSNoMainExecutable); + } + + size_t signatureOffset = arch->signingOffset(); + size_t signatureLength = arch->signingLength(); + if (signatureOffset == 0) { + MacOSError::throwMe(errSecCSUnsigned); + } + + fsignatures args = { + static_cast(code->diskRep()->signingBase()), + (void *)signatureOffset, + signatureLength, + }; + UnixError::check(::fcntl(code->diskRep()->fd(), F_ADDFILESIGS, &args)); + } + } else { MacOSError::throwMe(errSecCSUnsigned); + } END_CSAPI } diff --git a/OSX/libsecurity_codesigning/lib/SecStaticCode.h b/OSX/libsecurity_codesigning/lib/SecStaticCode.h index 5fdb98b76..b053623eb 100644 --- a/OSX/libsecurity_codesigning/lib/SecStaticCode.h +++ b/OSX/libsecurity_codesigning/lib/SecStaticCode.h @@ -179,6 +179,8 @@ CF_ENUM(uint32_t) { kSecCSRestrictToAppLike = 1 << 8, kSecCSRestrictSidebandData = 1 << 9, kSecCSUseSoftwareSigningCert = 1 << 10, + kSecCSValidatePEH = 1 << 11, + kSecCSSingleThreaded = 1 << 12, }; OSStatus SecStaticCodeCheckValidity(SecStaticCodeRef staticCode, SecCSFlags flags, diff --git a/OSX/libsecurity_codesigning/lib/SecStaticCodePriv.h b/OSX/libsecurity_codesigning/lib/SecStaticCodePriv.h index a736a9e2a..a5376f440 100644 --- a/OSX/libsecurity_codesigning/lib/SecStaticCodePriv.h +++ b/OSX/libsecurity_codesigning/lib/SecStaticCodePriv.h @@ -35,6 +35,13 @@ extern "C" { #endif +/* + Private SecStaticCodeCreate* SecCS flags. + */ +CF_ENUM(uint32_t) { + kSecCSForceOnlineNotarizationCheck = 1 << 0, +}; + /* @function SecCodeSetCallback diff --git a/OSX/libsecurity_codesigning/lib/StaticCode.cpp b/OSX/libsecurity_codesigning/lib/StaticCode.cpp index 8ec4a4374..2d5a3e90b 100644 --- a/OSX/libsecurity_codesigning/lib/StaticCode.cpp +++ b/OSX/libsecurity_codesigning/lib/StaticCode.cpp @@ -29,12 +29,14 @@ #include "reqmaker.h" #if TARGET_OS_OSX #include "drmaker.h" +#include "notarization.h" #endif #include "reqdumper.h" #include "reqparser.h" #include "sigblob.h" #include "resources.h" #include "detachedrep.h" +#include "signerutils.h" #if TARGET_OS_OSX #include "csdatabase.h" #endif @@ -99,13 +101,14 @@ static inline OSStatus errorForSlot(CodeDirectory::SpecialSlot slot) // // Construct a SecStaticCode object given a disk representation object // -SecStaticCode::SecStaticCode(DiskRep *rep) +SecStaticCode::SecStaticCode(DiskRep *rep, uint32_t flags) : mCheckfix30814861builder1(NULL), mRep(rep), mValidated(false), mExecutableValidated(false), mResourcesValidated(false), mResourcesValidContext(NULL), mProgressQueue("com.apple.security.validation-progress", false, QOS_CLASS_UNSPECIFIED), mOuterScope(NULL), mResourceScope(NULL), - mDesignatedReq(NULL), mGotResourceBase(false), mMonitor(NULL), mLimitedAsync(NULL) + mDesignatedReq(NULL), mGotResourceBase(false), mMonitor(NULL), mLimitedAsync(NULL), + mFlags(flags), mNotarizationChecked(false), mStaplingChecked(false), mNotarizationDate(NAN) #if TARGET_OS_OSX , mEvalDetails(NULL) #else @@ -343,6 +346,7 @@ void SecStaticCode::resetValidity() mResourcesValidContext = NULL; } mDir = NULL; + mCodeDirectories.clear(); mSignature = NULL; for (unsigned n = 0; n < cdSlotCount; n++) mCache[n] = NULL; @@ -354,6 +358,9 @@ void SecStaticCode::resetValidity() mGotResourceBase = false; mTrust = NULL; mCertChain = NULL; + mNotarizationChecked = false; + mStaplingChecked = false; + mNotarizationDate = NAN; #if TARGET_OS_OSX mEvalDetails = NULL; #endif @@ -384,7 +391,7 @@ CFDataRef SecStaticCode::component(CodeDirectory::SpecialSlot slot, OSStatus fai return NULL; if (!codeDirectory()->validateSlot(CFDataGetBytePtr(data), // ... and it's no good - CFDataGetLength(data), -slot)) + CFDataGetLength(data), -slot, false)) MacOSError::throwMe(errorForSlot(slot)); // ... then bail } cache = data; // it's okay, cache it @@ -399,6 +406,41 @@ CFDataRef SecStaticCode::component(CodeDirectory::SpecialSlot slot, OSStatus fai } +// +// Get the CodeDirectories. +// Throws (if check==true) or returns NULL (check==false) if there are none. +// Always throws if the CodeDirectories exist but are invalid. +// NEVER validates against the signature. +// +const SecStaticCode::CodeDirectoryMap * +SecStaticCode::codeDirectories(bool check /* = true */) const +{ + if (mCodeDirectories.empty()) { + try { + loadCodeDirectories(mCodeDirectories); + } catch (...) { + if (check) + throw; + // We wanted a NON-checked peek and failed to safely decode the existing CodeDirectories. + // Pretend this is unsigned, but make sure we didn't somehow cache an invalid CodeDirectory. + if (!mCodeDirectories.empty()) { + assert(false); + Syslog::warning("code signing internal problem: mCodeDirectories set despite exception exit"); + MacOSError::throwMe(errSecCSInternalError); + } + } + } else { + return &mCodeDirectories; + } + if (!mCodeDirectories.empty()) { + return &mCodeDirectories; + } + if (check) { + MacOSError::throwMe(errSecCSUnsigned); + } + return NULL; +} + // // Get the CodeDirectory. // Throws (if check==true) or returns NULL (check==false) if there is none. @@ -410,11 +452,10 @@ const CodeDirectory *SecStaticCode::codeDirectory(bool check /* = true */) const if (!mDir) { // pick our favorite CodeDirectory from the choices we've got try { - CodeDirectoryMap candidates; - if (loadCodeDirectories(candidates)) { + CodeDirectoryMap const *candidates = codeDirectories(check); + if (candidates != NULL) { CodeDirectory::HashAlgorithm type = CodeDirectory::bestHashOf(mHashAlgorithms); - mDir = candidates[type]; // and the winner is... - candidates.swap(mCodeDirectories); + mDir = candidates->at(type); // and the winner is... } } catch (...) { if (check) @@ -510,6 +551,26 @@ CFArrayRef SecStaticCode::cdHashes() return mCDHashes; } +// +// Get a dictionary of untruncated cdhashes for all digest types in this signature. +// +CFDictionaryRef SecStaticCode::cdHashesFull() +{ + if (!mCDHashFullDict) { + CFRef cdDict = makeCFMutableDictionary(); + for (auto const &it : mCodeDirectories) { + CodeDirectory::HashAlgorithm alg = it.first; + const CodeDirectory *cd = (const CodeDirectory *)CFDataGetBytePtr(it.second); + CFRef hash = cd->cdhash(false); + if (hash) { + CFDictionaryAddValue(cdDict, CFTempNumber(alg), hash); + } + } + mCDHashFullDict = cdDict.get(); + } + return mCDHashFullDict; +} + // // Return the CMS signature blob; NULL if none found. @@ -639,6 +700,58 @@ CFAbsoluteTime SecStaticCode::signingTimestamp() return mSigningTimestamp; } +#if TARGET_OS_OSX +#define kSecSHA256HashSize 32 +// subject:/C=US/ST=California/L=San Jose/O=Adobe Systems Incorporated/OU=Information Systems/OU=Digital ID Class 3 - Microsoft Software Validation v2/CN=Adobe Systems Incorporated +// issuer :/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 Code Signing 2010 CA +// Not Before: Dec 15 00:00:00 2010 GMT +// Not After : Dec 14 23:59:59 2012 GMT +static const unsigned char ASI_CS_12[] = { + 0x77,0x82,0x9C,0x64,0x33,0x45,0x2E,0x4A,0xD3,0xA8,0xE4,0x6F,0x00,0x6C,0x27,0xEA, + 0xFB,0xD3,0xF2,0x6D,0x50,0xF3,0x6F,0xE0,0xE9,0x6D,0x06,0x59,0x19,0xB5,0x46,0xFF +}; + +bool SecStaticCode::checkfix41082220(OSStatus cssmTrustResult) +{ + // only applicable to revoked results + if (cssmTrustResult != CSSMERR_TP_CERT_REVOKED) { + return false; + } + + // only this leaf certificate + if (CFArrayGetCount(mCertChain) == 0) { + return false; + } + CFRef leafHash(SecCertificateCopySHA256Digest((SecCertificateRef)CFArrayGetValueAtIndex(mCertChain, 0))); + if (memcmp(ASI_CS_12, CFDataGetBytePtr(leafHash), kSecSHA256HashSize) != 0) { + return false; + } + + // detached dmg signature + if (!isDetached() || format() != std::string("disk image")) { + return false; + } + + // sha-1 signed + if (hashAlgorithms().size() != 1 || hashAlgorithm() != kSecCodeSignatureHashSHA1) { + return false; + } + + // not a privileged binary - no TeamID and no entitlements + if (component(cdEntitlementSlot) || teamID()) { + return false; + } + + // no flags and old version + if (codeDirectory()->version != 0x20100 || codeDirectory()->flags != 0) { + return false; + } + + Security::Syslog::warning("CodeSigning: Check-fix enabled for dmg '%s' with identifier '%s' signed with revoked certificates", + mainExecutablePath().c_str(), identifier().c_str()); + return true; +} +#endif // TARGET_OS_OSX // // Verify the CMS signature. @@ -689,14 +802,17 @@ bool SecStaticCode::verifySignature() MacOSError::throwMe(errSecCSSignatureFailed); } - // retrieve auxiliary data bag and verify against current state - CFRef hashBag; - switch (OSStatus rc = CMSDecoderCopySignerAppleCodesigningHashAgility(cms, 0, &hashBag.aref())) { + // retrieve auxiliary v1 data bag and verify against current state + CFRef hashAgilityV1; + switch (OSStatus rc = CMSDecoderCopySignerAppleCodesigningHashAgility(cms, 0, &hashAgilityV1.aref())) { case noErr: - if (hashBag) { - CFRef hashDict = makeCFDictionaryFrom(hashBag); + if (hashAgilityV1) { + CFRef hashDict = makeCFDictionaryFrom(hashAgilityV1); CFArrayRef cdList = CFArrayRef(CFDictionaryGetValue(hashDict, CFSTR("cdhashes"))); CFArrayRef myCdList = this->cdHashes(); + + /* Note that this is not very "agile": There's no way to calculate the exact + * list for comparison if it contains hash algorithms we don't know yet... */ if (cdList == NULL || !CFEqual(cdList, myCdList)) MacOSError::throwMe(errSecCSSignatureFailed); } @@ -707,6 +823,62 @@ bool SecStaticCode::verifySignature() MacOSError::throwMe(rc); } + // retrieve auxiliary v2 data bag and verify against current state + CFRef hashAgilityV2; + switch (OSStatus rc = CMSDecoderCopySignerAppleCodesigningHashAgilityV2(cms, 0, &hashAgilityV2.aref())) { + case noErr: + if (hashAgilityV2) { + /* Require number of code directoris and entries in the hash agility + * dict to be the same size (no stripping out code directories). + */ + if (CFDictionaryGetCount(hashAgilityV2) != mCodeDirectories.size()) { + MacOSError::throwMe(errSecCSSignatureFailed); + } + + /* Require every cdhash of every code directory whose hash + * algorithm we know to be in the agility dictionary. + * + * We check untruncated cdhashes here because we can. + */ + bool foundOurs = false; + for (auto& entry : mCodeDirectories) { + SECOidTag tag = CodeDirectorySet::SECOidTagForAlgorithm(entry.first); + + if (tag == SEC_OID_UNKNOWN) { + // Unknown hash algorithm, ignore. + continue; + } + + CFRef key = makeCFNumber(int(tag)); + CFRef entryCdhash; + entryCdhash = (CFDataRef)CFDictionaryGetValue(hashAgilityV2, (void*)key.get()); + + CodeDirectory const *cd = (CodeDirectory const*)CFDataGetBytePtr(entry.second); + CFRef ourCdhash = cd->cdhash(false); // Untruncated cdhash! + if (!CFEqual(entryCdhash, ourCdhash)) { + MacOSError::throwMe(errSecCSSignatureFailed); + } + + if (entry.first == this->hashAlgorithm()) { + foundOurs = true; + } + } + + /* Require the cdhash of our chosen code directory to be in the dictionary. + * In theory, the dictionary could be full of unsupported cdhashes, but we + * really want ours, which is bound to be supported, to be covered. + */ + if (!foundOurs) { + MacOSError::throwMe(errSecCSSignatureFailed); + } + } + break; + case -1: /* CMS used to return this for "no attribute found", so tolerate it. Now returning noErr/NULL */ + break; + default: + MacOSError::throwMe(rc); + } + // internal signing time (as specified by the signer; optional) mSigningTime = 0; // "not present" marker (nobody could code sign on Jan 1, 2001 :-) switch (OSStatus rc = CMSDecoderCopySignerSigningTime(cms, 0, &mSigningTime)) { @@ -804,6 +976,9 @@ bool SecStaticCode::verifySignature() 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); } @@ -883,7 +1058,7 @@ bool SecStaticCode::verifySignature() } // Did we implicitly trust the signer? - mTrustedSigningCertChain = (trustResult == kSecTrustResultUnspecified); + mTrustedSigningCertChain = (trustResult == kSecTrustResultUnspecified || trustResult == kSecTrustResultProceed); return false; // XXX: Not checking for expired certs #endif @@ -974,7 +1149,7 @@ void SecStaticCode::validateComponent(CodeDirectory::SpecialSlot slot, OSStatus if (codeDirectory()->slotIsPresent(-slot)) // was supposed to be there... MacOSError::throwMe(fail); // ... and is missing } else { - if (!codeDirectory()->validateSlot(CFDataGetBytePtr(data), CFDataGetLength(data), -slot)) + if (!codeDirectory()->validateSlot(CFDataGetBytePtr(data), CFDataGetLength(data), -slot, false)) MacOSError::throwMe(fail); } } @@ -1009,7 +1184,8 @@ void SecStaticCode::validateExecutable() __block bool good = true; CodeDirectory::multipleHashFileData(fd, thisPage, hashAlgorithms(), ^(CodeDirectory::HashAlgorithm type, Security::DynamicHash *hasher) { const CodeDirectory* cd = (const CodeDirectory*)CFDataGetBytePtr(mCodeDirectories[type]); - if (!hasher->verify((*cd)[slot])) + if (!hasher->verify(cd->getSlot(slot, + mValidationFlags & kSecCSValidatePEH))) good = false; }); if (!good) { @@ -1067,7 +1243,9 @@ void SecStaticCode::validateResources(SecCSFlags flags) if (doit) { if (mLimitedAsync == NULL) { - mLimitedAsync = new LimitedAsync(diskRep()->fd().mediumType() == kIOPropertyMediumTypeSolidStateKey); + bool runMultiThreaded = ((flags & kSecCSSingleThreaded) == kSecCSSingleThreaded) ? false : + (diskRep()->fd().mediumType() == kIOPropertyMediumTypeSolidStateKey); + mLimitedAsync = new LimitedAsync(runMultiThreaded); } try { @@ -1292,7 +1470,7 @@ CFDataRef SecStaticCode::copyComponent(CodeDirectory::SpecialSlot slot, CFDataRe const CodeDirectory* cd = this->codeDirectory(); if (CFCopyRef component = this->component(slot)) { if (hash) { - const void *slotHash = (*cd)[slot]; + const void *slotHash = cd->getSlot(slot, false); if (cd->hashSize != CFDataGetLength(hash) || 0 != memcmp(slotHash, CFDataGetBytePtr(hash), cd->hashSize)) { Syslog::notice("copyComponent hash mismatch slot %d length %d", slot, int(CFDataGetLength(hash))); return NULL; // mismatch @@ -1358,12 +1536,12 @@ bool SecStaticCode::checkfix30814861(string path, bool addition) { CFRef inf = diskRepInformation(); try { CFDictionary info(diskRepInformation(), errSecCSNotSupported); - uint32_t platformCmd = - cfNumber(info.get(kSecCodeInfoDiskRepOSPlatform, errSecCSNotSupported), 0); + uint32_t platform = + cfNumber(info.get(kSecCodeInfoDiskRepVersionPlatform, errSecCSNotSupported), 0); uint32_t sdkVersion = - cfNumber(info.get(kSecCodeInfoDiskRepOSSDKVersion, errSecCSNotSupported), 0); + cfNumber(info.get(kSecCodeInfoDiskRepVersionSDK, errSecCSNotSupported), 0); - if (platformCmd != LC_VERSION_MIN_IPHONEOS || sdkVersion >= 0x00090000) { + if (platform != PLATFORM_IOS || sdkVersion >= 0x00090000) { return false; } } catch (const MacOSError &error) { @@ -1722,11 +1900,20 @@ const Requirement *SecStaticCode::defaultDesignatedRequirement() #if TARGET_OS_OSX // full signature: Gin up full context and let DRMaker do its thing validateDirectory(); // need the cert chain + CFRef secureTimestamp; + if (CFAbsoluteTime time = this->signingTimestamp()) { + secureTimestamp.take(CFDateCreate(NULL, time)); + } Requirement::Context context(this->certificates(), this->infoDictionary(), this->entitlements(), this->identifier(), - this->codeDirectory() + this->codeDirectory(), + NULL, + kSecCodeSignatureNoHash, + false, + secureTimestamp, + this->teamID() ); return DRMaker(context).make(); #else @@ -1759,7 +1946,15 @@ bool SecStaticCode::satisfiesRequirement(const Requirement *req, OSStatus failur bool result = false; assert(req); validateDirectory(); - result = req->validates(Requirement::Context(mCertChain, infoDictionary(), entitlements(), codeDirectory()->identifier(), codeDirectory()), failure); + CFRef secureTimestamp; + if (CFAbsoluteTime time = this->signingTimestamp()) { + secureTimestamp.take(CFDateCreate(NULL, time)); + } + result = req->validates(Requirement::Context(mCertChain, infoDictionary(), entitlements(), + codeDirectory()->identifier(), codeDirectory(), + NULL, kSecCodeSignatureNoHash, mRep->appleInternalForcePlatform(), + secureTimestamp, teamID()), + failure); return result; } @@ -1828,12 +2023,16 @@ CFDictionaryRef SecStaticCode::signingInformation(SecCSFlags flags) CFDictionaryAddValue(dict, kSecCodeInfoSource, CFTempString(this->signatureSource())); CFDictionaryAddValue(dict, kSecCodeInfoUnique, this->cdHash()); CFDictionaryAddValue(dict, kSecCodeInfoCdHashes, this->cdHashes()); + CFDictionaryAddValue(dict, kSecCodeInfoCdHashesFull, this->cdHashesFull()); const CodeDirectory* cd = this->codeDirectory(false); CFDictionaryAddValue(dict, kSecCodeInfoDigestAlgorithm, CFTempNumber(cd->hashType)); CFRef digests = makeCFArrayFrom(^CFTypeRef(CodeDirectory::HashAlgorithm type) { return CFTempNumber(type); }, hashAlgorithms()); CFDictionaryAddValue(dict, kSecCodeInfoDigestAlgorithms, digests); if (cd->platform) CFDictionaryAddValue(dict, kSecCodeInfoPlatformIdentifier, CFTempNumber(cd->platform)); + if (cd->runtimeVersion()) { + CFDictionaryAddValue(dict, kSecCodeInfoRuntimeVersion, CFTempNumber(cd->runtimeVersion())); + } // // Deliver any Info.plist only if it looks intact @@ -1916,8 +2115,26 @@ CFDictionaryRef SecStaticCode::signingInformation(SecCSFlags flags) if (CFRef ddict = diskRepInformation()) CFDictionaryAddValue(dict, kSecCodeInfoDiskRepInfo, ddict); } catch (...) { } + if (mNotarizationChecked && !isnan(mNotarizationDate)) { + CFRef date = CFDateCreate(NULL, mNotarizationDate); + if (date) { + CFDictionaryAddValue(dict, kSecCodeInfoNotarizationDate, date.get()); + } else { + secerror("Error creating date from timestamp: %f", mNotarizationDate); + } + } } + if (flags & kSecCSCalculateCMSDigest) { + try { + CFDictionaryAddValue(dict, kSecCodeInfoCMSDigestHashType, CFTempNumber(cmsDigestHashType())); + + CFRef cmsDigest = createCmsDigest(); + if (cmsDigest) { + CFDictionaryAddValue(dict, kSecCodeInfoCMSDigest, cmsDigest.get()); + } + } catch (...) { } + } // // kSecCSContentInformation adds more information about the physical layout @@ -1987,6 +2204,25 @@ void SecStaticCode::staticValidate(SecCSFlags flags, const SecRequirement *req) { setValidationFlags(flags); +#if TARGET_OS_OSX + if (!mStaplingChecked) { + mRep->registerStapledTicket(); + mStaplingChecked = true; + } + + if (mFlags & kSecCSForceOnlineNotarizationCheck) { + if (!mNotarizationChecked) { + if (this->cdHash()) { + bool is_revoked = checkNotarizationServiceForRevocation(this->cdHash(), (SecCSDigestAlgorithm)this->hashAlgorithm(), &mNotarizationDate); + if (is_revoked) { + MacOSError::throwMe(errSecCSRevokedNotarization); + } + } + mNotarizationChecked = true; + } + } +#endif // TARGET_OS_OSX + // initialize progress/cancellation state if (flags & kSecCSReportProgress) prepareProgress(estimateResourceWorkload() + 2); // +1 head, +1 tail @@ -2016,9 +2252,12 @@ void SecStaticCode::staticValidate(SecCSFlags flags, const SecRequirement *req) this->validateResources(flags); // perform strict validation if desired - if (flags & kSecCSStrictValidate) + if (flags & kSecCSStrictValidate) { mRep->strictValidate(codeDirectory(), mTolerateErrors, mValidationFlags); reportProgress(); + } else if (flags & kSecCSStrictValidateStructure) { + mRep->strictValidateStructure(codeDirectory(), mTolerateErrors, mValidationFlags); + } // allow monitor intervention if (CFRef veto = reportEvent(CFSTR("validated"), NULL)) { @@ -2104,10 +2343,35 @@ bool SecStaticCode::isAppleDeveloperCert(CFArrayRef certs) { static const std::string appleDeveloperRequirement = "(" + std::string(WWDRRequirement) + ") or (" + MACWWDRRequirement + ") or (" + developerID + ") or (" + distributionCertificate + ") or (" + iPhoneDistributionCert + ")"; SecPointer req = new SecRequirement(parseRequirement(appleDeveloperRequirement), true); - Requirement::Context ctx(certs, NULL, NULL, "", NULL); + Requirement::Context ctx(certs, NULL, NULL, "", NULL, NULL, kSecCodeSignatureNoHash, false, NULL, ""); return req->requirement()->validates(ctx); } +CFDataRef SecStaticCode::createCmsDigest() +{ + /* + * The CMS digest is a hash of the primary (first, most compatible) code directory, + * but its hash algorithm is fixed and not related to the code directory's + * hash algorithm. + */ + + auto it = codeDirectories()->begin(); + + if (it == codeDirectories()->end()) { + return NULL; + } + + CodeDirectory const * const cd = reinterpret_cast(CFDataGetBytePtr(it->second)); + + RefPointer hash = cd->hashFor(mCMSDigestHashType); + CFMutableDataRef data = CFDataCreateMutable(NULL, hash->digestLength()); + CFDataSetLength(data, hash->digestLength()); + hash->update(cd, cd->length()); + hash->finish(CFDataGetMutableBytePtr(data)); + + return data; +} + } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_codesigning/lib/StaticCode.h b/OSX/libsecurity_codesigning/lib/StaticCode.h index 46dfbd2e0..567268243 100644 --- a/OSX/libsecurity_codesigning/lib/StaticCode.h +++ b/OSX/libsecurity_codesigning/lib/StaticCode.h @@ -106,7 +106,7 @@ class SecStaticCode : public SecCFObject { static SecStaticCode *requiredStatic(SecStaticCodeRef ref); // convert SecCodeRef static SecCode *optionalDynamic(SecStaticCodeRef ref); // extract SecCodeRef or NULL if static - SecStaticCode(DiskRep *rep); + SecStaticCode(DiskRep *rep, uint32_t flags = 0); virtual ~SecStaticCode() throw(); void initializeFromParent(const SecStaticCode& parent); @@ -117,11 +117,15 @@ class SecStaticCode : public SecCFObject { void detachedSignature(CFDataRef sig); // attach an explicitly given detached signature void checkForSystemSignature(); // check for and attach system-supplied detached signature + typedef std::map > CodeDirectoryMap; + const CodeDirectory *codeDirectory(bool check = true) const; + const CodeDirectoryMap *codeDirectories(bool check = true) const; CodeDirectory::HashAlgorithm hashAlgorithm() const { return codeDirectory()->hashType; } CodeDirectory::HashAlgorithms hashAlgorithms() const { return mHashAlgorithms; } CFDataRef cdHash(); CFArrayRef cdHashes(); + CFDictionaryRef cdHashesFull(); CFDataRef signature(); CFAbsoluteTime signingTime(); CFAbsoluteTime signingTimestamp(); @@ -200,12 +204,15 @@ class SecStaticCode : public SecCFObject { bool trustedSigningCertChain() { return mTrustedSigningCertChain; } #endif + void handleOtherArchitectures(void (^handle)(SecStaticCode* other)); + + uint8_t cmsDigestHashType() const { return mCMSDigestHashType; }; + CFDataRef createCmsDigest(); public: void staticValidate(SecCSFlags flags, const SecRequirement *req); void staticValidateCore(SecCSFlags flags, const SecRequirement *req); protected: - typedef std::map > CodeDirectoryMap; bool loadCodeDirectories(CodeDirectoryMap& cdMap) const; protected: @@ -220,16 +227,17 @@ class SecStaticCode : public SecCFObject { static void checkOptionalResource(CFTypeRef key, CFTypeRef value, void *context); bool hasWeakResourceRules(CFDictionaryRef rulesDict, uint32_t version, CFArrayRef allowedOmissions); - void handleOtherArchitectures(void (^handle)(SecStaticCode* other)); - private: void validateOtherVersions(CFURLRef path, SecCSFlags flags, SecRequirementRef req, SecStaticCode *code); bool checkfix30814861(string path, bool addition); + bool checkfix41082220(OSStatus result); ResourceBuilder *mCheckfix30814861builder1; dispatch_once_t mCheckfix30814861builder1_once; private: + static const uint8_t mCMSDigestHashType = kSecCodeSignatureHashSHA256; + // hash of CMS digest (kSecCodeSignatureHash* constant) RefPointer mRep; // on-disk representation mutable CodeDirectoryMap mCodeDirectories; // available CodeDirectory blobs by digest type mutable CFRef mBaseDir; // the primary CodeDirectory blob (whether it's chosen or not) @@ -281,7 +289,8 @@ class SecStaticCode : public SecCFObject { const Requirement *mDesignatedReq; // cached designated req if we made one up CFRef mCDHash; // hash of chosen CodeDirectory CFRef mCDHashes; // hashes of all CodeDirectories (in digest type code order) - + CFRef mCDHashFullDict; // untruncated hashes of CodeDirectories (as dictionary) + bool mGotResourceBase; // asked mRep for resourceBasePath CFRef mResourceBase; // URL form of resource base directory @@ -289,6 +298,11 @@ class SecStaticCode : public SecCFObject { LimitedAsync *mLimitedAsync; // limited async workers for verification + uint32_t mFlags; // flags from creation + bool mNotarizationChecked; // ensure notarization check only performed once + bool mStaplingChecked; // ensure stapling check only performed once + double mNotarizationDate; // the notarization ticket's date, if online check failed + // signature verification outcome (mTrust == NULL => not done yet) CFRef mTrust; // outcome of crypto validation (valid or not) CFRef mCertChain; diff --git a/OSX/libsecurity_codesigning/lib/antlrplugin.cpp b/OSX/libsecurity_codesigning/lib/antlrplugin.cpp index 0e4dee56b..306207aae 100644 --- a/OSX/libsecurity_codesigning/lib/antlrplugin.cpp +++ b/OSX/libsecurity_codesigning/lib/antlrplugin.cpp @@ -49,7 +49,7 @@ class StdioInputStream : public antlr::InputBuffer { class StringInputStream : public antlr::InputBuffer { public: StringInputStream(const string &s) : mInput(s), mPos(mInput.begin()) { } - int getChar() { return (mPos == mInput.end()) ? EOF : *mPos++; } + int getChar() { return (mPos == mInput.end()) ? EOF : static_cast(*mPos++); } private: string mInput; diff --git a/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp b/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp index 8ec8852c6..7c4909702 100644 --- a/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp +++ b/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp @@ -23,6 +23,7 @@ #include "bundlediskrep.h" #include "filediskrep.h" #include "dirscanner.h" +#include "notarization.h" #include #include #include @@ -47,11 +48,12 @@ static std::string findDistFile(const std::string &directory); // We make a CFBundleRef immediately, but everything else is lazy // BundleDiskRep::BundleDiskRep(const char *path, const Context *ctx) - : mBundle(_CFBundleCreateUnique(NULL, CFTempURL(path))) + : mBundle(_CFBundleCreateUnique(NULL, CFTempURL(path))), forcePlatform(false) { if (!mBundle) MacOSError::throwMe(errSecCSBadBundleFormat); setup(ctx); + forcePlatform = mExecRep->appleInternalForcePlatform(); CODESIGN_DISKREP_CREATE_BUNDLE_PATH(this, (char*)path, (void*)ctx, mExecRep); } @@ -59,6 +61,7 @@ BundleDiskRep::BundleDiskRep(CFBundleRef ref, const Context *ctx) { mBundle = ref; // retains setup(ctx); + forcePlatform = mExecRep->appleInternalForcePlatform(); CODESIGN_DISKREP_CREATE_BUNDLE_REF(this, ref, (void*)ctx, mExecRep); } @@ -87,7 +90,7 @@ void BundleDiskRep::setup(const Context *ctx) mInstallerPackage = false; // default mAppLike = false; // pessimism first bool appDisqualified = false; // found reason to disqualify as app - + // capture the path of the main executable before descending into a specific version CFRef mainExecBefore = CFBundleCopyExecutableURL(mBundle); CFRef infoPlistBefore = _CFBundleCopyInfoPlistURL(mBundle); @@ -360,6 +363,45 @@ CFDataRef BundleDiskRep::component(CodeDirectory::SpecialSlot slot) } } +BundleDiskRep::RawComponentMap BundleDiskRep::createRawComponents() +{ + RawComponentMap map; + + /* Those are the slots known to BundleDiskReps. + * Unlike e.g. MachOReps, we cannot handle unknown slots, + * as we won't know their slot <-> filename mapping. + */ + int const slots[] = { + cdCodeDirectorySlot, cdSignatureSlot, cdResourceDirSlot, + cdTopDirectorySlot, cdEntitlementSlot, cdEntitlementDERSlot, + cdRepSpecificSlot}; + + for (int slot = 0; slot < (int)(sizeof(slots)/sizeof(slots[0])); ++slot) { + /* Here, we only handle metaData slots, i.e. slots that + * are explicit files in the _CodeSignature directory. + * Main executable slots (if the main executable is a + * EditableDiskRep) are handled when editing the + * main executable's rep explicitly. + * There is also an Info.plist slot, which is not a + * real part of the code signature. + */ + CFRef data = metaData(slot); + + if (data) { + map[slot] = data; + } + } + + for (CodeDirectory::Slot slot = cdAlternateCodeDirectorySlots; slot < cdAlternateCodeDirectoryLimit; ++slot) { + CFRef data = metaData(slot); + + if (data) { + map[slot] = data; + } + } + + return map; +} // Check that all components of this BundleDiskRep come from either the main // executable or the _CodeSignature directory (not mix-and-match). @@ -471,6 +513,7 @@ CFArrayRef BundleDiskRep::modifiedFiles() checkModifiedFile(files, cdResourceDirSlot); checkModifiedFile(files, cdTopDirectorySlot); checkModifiedFile(files, cdEntitlementSlot); + checkModifiedFile(files, cdEntitlementDERSlot); checkModifiedFile(files, cdRepSpecificSlot); for (CodeDirectory::Slot slot = cdAlternateCodeDirectorySlots; slot < cdAlternateCodeDirectoryLimit; ++slot) checkModifiedFile(files, slot); @@ -575,41 +618,73 @@ CFDictionaryRef BundleDiskRep::defaultResourceRules(const SigningContext &ctx) "'^.*' = #T" // everything is a resource "'^Info\\.plist$' = {omit=#T,weight=10}" // explicitly exclude this for backward compatibility "}}"); - - // new (V2) executable bundle rules - return cfmake("{" // *** the new (V2) world *** - "rules={" // old (V1; legacy) version - "'^version.plist$' = #T" // include version.plist - "%s = #T" // include Resources - "%s = {optional=#T, weight=1000}" // make localizations optional - "%s = {weight=1010}" // ... except for Base.lproj which really isn't optional at all - "%s = {omit=#T, weight=1100}" // exclude all locversion.plist files - "},rules2={" - "'^.*' = #T" // include everything as a resource, with the following exceptions - "'^[^/]+$' = {nested=#T, weight=10}" // files directly in Contents - "'^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/' = {nested=#T, weight=10}" // dynamic repositories - "'.*\\.dSYM($|/)' = {weight=11}" // but allow dSYM directories in code locations (parallel to their code) - "'^(.*/)?\\.DS_Store$' = {omit=#T,weight=2000}" // ignore .DS_Store files - "'^Info\\.plist$' = {omit=#T, weight=20}" // excluded automatically now, but old systems need to be told - "'^version\\.plist$' = {weight=20}" // include version.plist as resource - "'^embedded\\.provisionprofile$' = {weight=20}" // include embedded.provisionprofile as resource - "'^PkgInfo$' = {omit=#T, weight=20}" // traditionally not included - "%s = {weight=20}" // Resources override default nested (widgets) - "%s = {optional=#T, weight=1000}" // make localizations optional - "%s = {weight=1010}" // ... except for Base.lproj which really isn't optional at all - "%s = {omit=#T, weight=1100}" // exclude all locversion.plist files - "}}", - - (string("^") + resources).c_str(), - (string("^") + resources + ".*\\.lproj/").c_str(), - (string("^") + resources + "Base\\.lproj/").c_str(), - (string("^") + resources + ".*\\.lproj/locversion.plist$").c_str(), - - (string("^") + resources).c_str(), - (string("^") + resources + ".*\\.lproj/").c_str(), - (string("^") + resources + "Base\\.lproj/").c_str(), - (string("^") + resources + ".*\\.lproj/locversion.plist$").c_str() - ); + + // new (V2) executable bundle rules + if (!resources.empty()) { + return cfmake("{" // *** the new (V2) world *** + "rules={" // old (V1; legacy) version + "'^version.plist$' = #T" // include version.plist + "%s = #T" // include Resources + "%s = {optional=#T, weight=1000}" // make localizations optional + "%s = {weight=1010}" // ... except for Base.lproj which really isn't optional at all + "%s = {omit=#T, weight=1100}" // exclude all locversion.plist files + "},rules2={" + "'^.*' = #T" // include everything as a resource, with the following exceptions + "'^[^/]+$' = {nested=#T, weight=10}" // files directly in Contents + "'^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/' = {nested=#T, weight=10}" // dynamic repositories + "'.*\\.dSYM($|/)' = {weight=11}" // but allow dSYM directories in code locations (parallel to their code) + "'^(.*/)?\\.DS_Store$' = {omit=#T,weight=2000}" // ignore .DS_Store files + "'^Info\\.plist$' = {omit=#T, weight=20}" // excluded automatically now, but old systems need to be told + "'^version\\.plist$' = {weight=20}" // include version.plist as resource + "'^embedded\\.provisionprofile$' = {weight=20}" // include embedded.provisionprofile as resource + "'^PkgInfo$' = {omit=#T, weight=20}" // traditionally not included + "%s = {weight=20}" // Resources override default nested (widgets) + "%s = {optional=#T, weight=1000}" // make localizations optional + "%s = {weight=1010}" // ... except for Base.lproj which really isn't optional at all + "%s = {omit=#T, weight=1100}" // exclude all locversion.plist files + "}}", + + (string("^") + resources).c_str(), + (string("^") + resources + ".*\\.lproj/").c_str(), + (string("^") + resources + "Base\\.lproj/").c_str(), + (string("^") + resources + ".*\\.lproj/locversion.plist$").c_str(), + + (string("^") + resources).c_str(), + (string("^") + resources + ".*\\.lproj/").c_str(), + (string("^") + resources + "Base\\.lproj/").c_str(), + (string("^") + resources + ".*\\.lproj/locversion.plist$").c_str() + ); + } else { + /* This is a bundle format without a Resources directory, which means we need to omit + * Resources-directory specific rules that would create conflicts. */ + + /* We also declare that flat bundles do not use any nested code rules. + * Embedded, where flat bundles are used, currently does not support them, + * and we have no plans for allowing the replacement of nested code there. + * Should anyone actually intend to use nested code rules in a flat + * bundle, they are free to create their own rules. */ + + return cfmake("{" // *** the new (V2) world *** + "rules={" // old (V1; legacy) version + "'^version.plist$' = #T" // include version.plist + "'^.*' = #T" // include Resources + "'^.*\\.lproj/' = {optional=#T, weight=1000}" // make localizations optional + "'^Base\\.lproj/' = {weight=1010}" // ... except for Base.lproj which really isn't optional at all + "'^.*\\.lproj/locversion.plist$' = {omit=#T, weight=1100}" // exclude all locversion.plist files + "},rules2={" + "'^.*' = #T" // include everything as a resource, with the following exceptions + "'.*\\.dSYM($|/)' = {weight=11}" // but allow dSYM directories in code locations (parallel to their code) + "'^(.*/)?\\.DS_Store$' = {omit=#T,weight=2000}" // ignore .DS_Store files + "'^Info\\.plist$' = {omit=#T, weight=20}" // excluded automatically now, but old systems need to be told + "'^version\\.plist$' = {weight=20}" // include version.plist as resource + "'^embedded\\.provisionprofile$' = {weight=20}" // include embedded.provisionprofile as resource + "'^PkgInfo$' = {omit=#T, weight=20}" // traditionally not included + "'^.*\\.lproj/' = {optional=#T, weight=1000}" // make localizations optional + "'^Base\\.lproj/' = {weight=1010}" // ... except for Base.lproj which really isn't optional at all + "'^.*\\.lproj/locversion.plist$' = {omit=#T, weight=1100}" // exclude all locversion.plist files + "}}" + ); + } } @@ -642,6 +717,14 @@ size_t BundleDiskRep::pageSize(const SigningContext &ctx) // Takes an array of CFNumbers of errors to tolerate. // void BundleDiskRep::strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags) +{ + strictValidateStructure(cd, tolerated, flags); + + // now strict-check the main executable (which won't be an app-like object) + mExecRep->strictValidate(cd, tolerated, flags & ~kSecCSRestrictToAppLike); +} + +void BundleDiskRep::strictValidateStructure(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags) { // scan our metadirectory (_CodeSignature) for unwanted guests if (!(flags & kSecCSQuickCheck)) @@ -661,9 +744,6 @@ void BundleDiskRep::strictValidate(const CodeDirectory* cd, const ToleratedError if (!mAppLike) if (tolerated.find(kSecCSRestrictToAppLike) == tolerated.end()) MacOSError::throwMe(errSecCSNotAppLike); - - // now strict-check the main executable (which won't be an app-like object) - mExecRep->strictValidate(cd, tolerated, flags & ~kSecCSRestrictToAppLike); } void BundleDiskRep::recordStrictError(OSStatus error) @@ -796,8 +876,48 @@ void BundleDiskRep::Writer::component(CodeDirectory::SpecialSlot slot, CFDataRef if (const char *name = CodeDirectory::canonicalSlotName(slot)) { rep->createMeta(); string path = rep->metaPath(name); + +#if TARGET_OS_OSX + // determine AFSC status if we are told to preserve compression + bool conductCompression = false; + cmpInfo cInfo; + if (this->getPreserveAFSC()) { + struct stat statBuffer; + if (stat(path.c_str(), &statBuffer) == 0) { + if (queryCompressionInfo(path.c_str(), &cInfo) == 0) { + if (cInfo.compressionType != 0 && cInfo.compressedSize > 0) { + conductCompression = true; + } + } + } + } +#endif + AutoFileDesc fd(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); fd.writeAll(CFDataGetBytePtr(data), CFDataGetLength(data)); + fd.close(); + +#if TARGET_OS_OSX + // if the original file was compressed, compress the new file after move + if (conductCompression) { + CFMutableDictionaryRef options = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFStringRef val = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d"), cInfo.compressionType); + CFDictionarySetValue(options, kAFSCCompressionTypes, val); + CFRelease(val); + + CompressionQueueContext compressionQueue = CreateCompressionQueue(NULL, NULL, NULL, NULL, options); + + if (!CompressFile(compressionQueue, path.c_str(), NULL)) { + secinfo("bundlediskrep", "%p Failed to queue compression of file %s", this, path.c_str()); + MacOSError::throwMe(errSecCSInternalError); + } + + FinishCompressionAndCleanUp(compressionQueue); + compressionQueue = NULL; + CFRelease(options); + } +#endif + mWrittenFiles.insert(name); } else MacOSError::throwMe(errSecCSBadBundleFormat); @@ -837,8 +957,7 @@ void BundleDiskRep::Writer::flush() execWriter->flush(); purgeMetaDirectory(); } - - + // purge _CodeSignature of all left-over files from any previous signature void BundleDiskRep::Writer::purgeMetaDirectory() { @@ -855,6 +974,11 @@ void BundleDiskRep::Writer::purgeMetaDirectory() } +void BundleDiskRep::registerStapledTicket() +{ + string root = cfStringRelease(copyCanonicalPath()); + registerStapledTicketInBundle(root); +} } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_codesigning/lib/bundlediskrep.h b/OSX/libsecurity_codesigning/lib/bundlediskrep.h index f44a2b1ca..af3e40e2c 100644 --- a/OSX/libsecurity_codesigning/lib/bundlediskrep.h +++ b/OSX/libsecurity_codesigning/lib/bundlediskrep.h @@ -30,6 +30,14 @@ #include "diskrep.h" #include "machorep.h" +#include + +#if TARGET_OS_OSX +__BEGIN_DECLS +#include +__END_DECLS +#endif + namespace Security { namespace CodeSigning { @@ -47,14 +55,16 @@ namespace CodeSigning { // if it is in Mach-O format, or in files in a _CodeSignature directory if not. // This DiskRep supports resource sealing. // -class BundleDiskRep : public DiskRep { +class BundleDiskRep : public DiskRep, public EditableDiskRep { public: BundleDiskRep(const char *path, const Context *ctx = NULL); BundleDiskRep(CFBundleRef ref, const Context *ctx = NULL); ~BundleDiskRep(); CFDataRef component(CodeDirectory::SpecialSlot slot); + RawComponentMap createRawComponents(); CFDataRef identification(); + DiskRep *mainExecRep() const { return mExecRep.get(); }; std::string mainExecutablePath(); CFURLRef copyCanonicalPath(); std::string resourcesRootPath(); @@ -78,8 +88,13 @@ class BundleDiskRep : public DiskRep { size_t pageSize(const SigningContext &ctx); void strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags); + void strictValidateStructure(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags); CFArrayRef allowedResourceOmissions(); + void registerStapledTicket(); + + bool appleInternalForcePlatform() const {return forcePlatform;}; + CFBundleRef bundle() const { return mBundle; } public: @@ -118,6 +133,7 @@ class BundleDiskRep : public DiskRep { bool mComponentsFromExecValid; // mComponentsFromExec is valid (tri-state) std::set mUsedComponents; // remember what components we've retrieved std::set mStrictErrors; // strict validation errors encountered + bool forcePlatform; // treat as anchor apple on apple internal }; diff --git a/OSX/libsecurity_codesigning/lib/cdbuilder.cpp b/OSX/libsecurity_codesigning/lib/cdbuilder.cpp index babfe29c1..7fefc1c5e 100644 --- a/OSX/libsecurity_codesigning/lib/cdbuilder.cpp +++ b/OSX/libsecurity_codesigning/lib/cdbuilder.cpp @@ -50,6 +50,8 @@ CodeDirectory::Builder::Builder(HashAlgorithm digestAlgorithm) mExecSegOffset(0), mExecSegLimit(0), mExecSegFlags(0), + mGeneratePreEncryptHashes(false), + mRuntimeVersion(0), mDir(NULL) { mDigestLength = (uint32_t)MakeHash(this)->digestLength(); @@ -78,13 +80,18 @@ void CodeDirectory::Builder::executable(string path, void CodeDirectory::Builder::reopen(string path, size_t offset, size_t length) { - assert(mExec); // already called executable() + assert(opened()); // already called executable() mExec.close(); mExec.open(path); mExecOffset = offset; mExecLength = length; } +bool CodeDirectory::Builder::opened() +{ + return bool(mExec); +} + // // Set the source for one special slot @@ -121,6 +128,8 @@ CodeDirectory::Scatter *CodeDirectory::Builder::scatter(unsigned count) size_t CodeDirectory::Builder::fixedSize(const uint32_t version) { size_t cdSize = sizeof(CodeDirectory); + if (version < supportsPreEncrypt) + cdSize -= sizeof(mDir->runtime) + sizeof(mDir->preEncryptOffset); if (version < supportsExecSegment) cdSize -= sizeof(mDir->execSegBase) + sizeof(mDir->execSegLimit) + sizeof(mDir->execSegFlags); if (version < supportsCodeLimit64) @@ -157,6 +166,11 @@ size_t CodeDirectory::Builder::size(const uint32_t version) if (mTeamID.size()) offset += mTeamID.size() + 1; // size of teamID (with null byte) offset += (mCodeSlots + mSpecialSlots) * mDigestLength; // hash vector + + if (mGeneratePreEncryptHashes || !mPreservedPreEncryptHashMap.empty()) { + offset += mCodeSlots * mDigestLength; + } + if (offset <= offset0) UnixError::throwMe(ENOEXEC); @@ -187,8 +201,10 @@ CodeDirectory *CodeDirectory::Builder::build() size_t teamIDLength = mTeamID.size() + 1; // Determine the version - if (mExecSegLimit > 0) { + if (mGeneratePreEncryptHashes || !mPreservedPreEncryptHashMap.empty() || mRuntimeVersion) { version = currentVersion; + } else if (mExecSegLimit > 0) { + version = supportsExecSegment; } else if (mExecLength > UINT32_MAX) { version = supportsCodeLimit64; } else if (mTeamID.size()) { @@ -231,6 +247,7 @@ CodeDirectory *CodeDirectory::Builder::build() mDir->execSegBase = mExecSegOffset; mDir->execSegLimit = mExecSegLimit; mDir->execSegFlags = mExecSegFlags; + mDir->runtime = mRuntimeVersion; // locate and fill flex fields size_t offset = fixedSize(mDir->version); @@ -250,18 +267,27 @@ CodeDirectory *CodeDirectory::Builder::build() memcpy(mDir->teamID(), mTeamID.c_str(), teamIDLength); offset += teamIDLength; } + // (add new flexibly-allocated fields here) + /* Pre-encrypt hashes come before normal hashes, so that the kernel can free + * the normal, potentially post-encrypt hashes away easily. */ + if (mGeneratePreEncryptHashes || !mPreservedPreEncryptHashMap.empty()) { + mDir->preEncryptOffset = (uint32_t)offset; + offset += mCodeSlots * mDigestLength; + } + mDir->hashOffset = (uint32_t)(offset + mSpecialSlots * mDigestLength); offset += (mSpecialSlots + mCodeSlots) * mDigestLength; + assert(offset == total); // matches allocated size (void)offset; // fill special slots - memset((*mDir)[(int)-mSpecialSlots], 0, mDigestLength * mSpecialSlots); + memset(mDir->getSlotMutable((int)-mSpecialSlots, false), 0, mDigestLength * mSpecialSlots); for (size_t slot = 1; slot <= mSpecialSlots; ++slot) - memcpy((*mDir)[(int)-slot], specialSlot((SpecialSlot)slot), mDigestLength); + memcpy(mDir->getSlotMutable((int)-slot, false), specialSlot((SpecialSlot)slot), mDigestLength); // fill code slots mExec.seek(mExecOffset); @@ -271,10 +297,23 @@ CodeDirectory *CodeDirectory::Builder::build() if (mPageSize) thisPage = min(thisPage, mPageSize); MakeHash hasher(this); - generateHash(hasher, mExec, (*mDir)[slot], thisPage); + generateHash(hasher, mExec, mDir->getSlotMutable(slot, false), thisPage); + if (mGeneratePreEncryptHashes && mPreservedPreEncryptHashMap.empty()) { + memcpy(mDir->getSlotMutable(slot, true), mDir->getSlot(slot, false), + mDir->hashSize); + } remaining -= thisPage; } assert(remaining == 0); + + PreEncryptHashMap::iterator preEncrypt = + mPreservedPreEncryptHashMap.find(mHashType); + if (preEncrypt != mPreservedPreEncryptHashMap.end()) { + memcpy(mDir->getSlotMutable(0, true), + CFDataGetBytePtr(preEncrypt->second), + mCodeSlots * mDigestLength); + mPreservedPreEncryptHashMap.erase(preEncrypt->first); // Releases the CFData memory. + } // all done. Pass ownership to caller return mDir; diff --git a/OSX/libsecurity_codesigning/lib/cdbuilder.h b/OSX/libsecurity_codesigning/lib/cdbuilder.h index 761dcf631..7137444ce 100644 --- a/OSX/libsecurity_codesigning/lib/cdbuilder.h +++ b/OSX/libsecurity_codesigning/lib/cdbuilder.h @@ -49,6 +49,7 @@ class CodeDirectory::Builder : public RefCount { void executable(string path, size_t pagesize, size_t offset, size_t length); void reopen(string path, size_t offset, size_t length); + bool opened(); void specialSlot(SpecialSlot slot, CFDataRef data); void identifier(const std::string &code) { mIdentifier = code; } @@ -64,6 +65,18 @@ class CodeDirectory::Builder : public RefCount { mExecSegOffset = base; mExecSegLimit = limit; mExecSegFlags = flags; } void addExecSegFlags(uint64_t flags) { mExecSegFlags |= flags; } + typedef std::map > + PreEncryptHashMap; + + void generatePreEncryptHashes(bool pre) { mGeneratePreEncryptHashes = pre; } + void preservePreEncryptHashMap(PreEncryptHashMap preEncryptHashMap) { + mPreservedPreEncryptHashMap = preEncryptHashMap; + } + + void runTimeVersion(uint32_t runtime) { + mRuntimeVersion = runtime; + } + size_t size(const uint32_t version); // calculate size CodeDirectory *build(); // build CodeDirectory and return it size_t fixedSize(const uint32_t version); // calculate fixed size of the CodeDirectory @@ -102,6 +115,11 @@ class CodeDirectory::Builder : public RefCount { uint64_t mExecSegLimit; // limit of executable segment uint64_t mExecSegFlags; // executable segment flags + bool mGeneratePreEncryptHashes; // whether to also generate new pre-encrypt hashes + PreEncryptHashMap mPreservedPreEncryptHashMap; // existing pre-encrypt hashes to be set + + uint32_t mRuntimeVersion; // Hardened Runtime Version + CodeDirectory *mDir; // what we're building }; diff --git a/OSX/libsecurity_codesigning/lib/codedirectory.cpp b/OSX/libsecurity_codesigning/lib/codedirectory.cpp index 1fc4fdddb..4d3c1c800 100644 --- a/OSX/libsecurity_codesigning/lib/codedirectory.cpp +++ b/OSX/libsecurity_codesigning/lib/codedirectory.cpp @@ -79,6 +79,8 @@ const char *CodeDirectory::canonicalSlotName(SpecialSlot slot) return kSecCS_TOPDIRECTORYFILE; case cdEntitlementSlot: return kSecCS_ENTITLEMENTFILE; + case cdEntitlementDERSlot: + return kSecCS_ENTITLEMENTDERFILE; case cdRepSpecificSlot: return kSecCS_REPSPECIFICFILE; default: @@ -105,9 +107,12 @@ unsigned CodeDirectory::slotAttributes(SpecialSlot slot) case cdSignatureSlot: return cdComponentPerArchitecture; // raw case cdEntitlementSlot: + case cdEntitlementDERSlot: return cdComponentIsBlob; // global case cdIdentificationSlot: return cdComponentPerArchitecture; // raw + case cdTicketSlot: + return 0; // global, raw default: return 0; // global, raw } @@ -157,7 +162,9 @@ void CodeDirectory::checkIntegrity() const if (version > currentVersion) secinfo("codedir", "%p version 0x%x newer than current 0x%x", this, uint32_t(version), currentVersion); - + + bool hasPreEncryptHashes = version >= supportsPreEncrypt && preEncryptOffset != 0; + // now check interior offsets for validity if (!stringAt(identOffset)) MacOSError::throwMe(errSecCSSignatureFailed); // identifier out of blob range @@ -165,6 +172,8 @@ void CodeDirectory::checkIntegrity() const MacOSError::throwMe(errSecCSSignatureFailed); // identifier out of blob range if (!contains(hashOffset - int64_t(hashSize) * nSpecialSlots, hashSize * (int64_t(nSpecialSlots) + nCodeSlots))) MacOSError::throwMe(errSecCSSignatureFailed); // hash array out of blob range + if (hasPreEncryptHashes && !contains(preEncryptOffset, hashSize * (int64_t(nCodeSlots)))) + MacOSError::throwMe(errSecCSSignatureFailed); // pre-encrypt array out of blob range if (const Scatter *scatter = this->scatterVector()) { // the optional scatter vector is terminated with an element having (count == 0) unsigned int pagesConsumed = 0; @@ -175,7 +184,8 @@ void CodeDirectory::checkIntegrity() const break; pagesConsumed += scatter->count; } - if (!contains((*this)[pagesConsumed-1], hashSize)) // referenced too many main hash slots + if (!contains(getSlot(pagesConsumed-1, false), hashSize) || + (hasPreEncryptHashes && !contains(getSlot(pagesConsumed-1, true), hashSize))) // referenced too many main hash slots MacOSError::throwMe(errSecCSSignatureFailed); } @@ -197,13 +207,13 @@ void CodeDirectory::checkIntegrity() const // // Validate a slot against data in memory. // -bool CodeDirectory::validateSlot(const void *data, size_t length, Slot slot) const +bool CodeDirectory::validateSlot(const void *data, size_t length, Slot slot, bool preEncrypt) const { secinfo("codedir", "%p validating slot %d", this, int(slot)); MakeHash hasher(this); - Hashing::Byte digest[hasher->digestLength()]; - generateHash(hasher, data, length, digest); - return memcmp(digest, (*this)[slot], hasher->digestLength()) == 0; + vector digest_vector(hasher->digestLength()); + generateHash(hasher, data, length, digest_vector.data()); + return memcmp(digest_vector.data(), getSlot(slot, preEncrypt), hasher->digestLength()) == 0; } @@ -211,12 +221,12 @@ bool CodeDirectory::validateSlot(const void *data, size_t length, Slot slot) con // Validate a slot against the contents of an open file. At most 'length' bytes // will be read from the file. // -bool CodeDirectory::validateSlot(FileDesc fd, size_t length, Slot slot) const +bool CodeDirectory::validateSlot(FileDesc fd, size_t length, Slot slot, bool preEncrypt) const { MakeHash hasher(this); - Hashing::Byte digest[hasher->digestLength()]; - generateHash(hasher, fd, digest, length); - return memcmp(digest, (*this)[slot], hasher->digestLength()) == 0; + vector digest_vector(hasher->digestLength()); + generateHash(hasher, fd, digest_vector.data(), length); + return memcmp(digest_vector.data(), getSlot(slot, preEncrypt), hasher->digestLength()) == 0; } @@ -228,7 +238,7 @@ bool CodeDirectory::validateSlot(FileDesc fd, size_t length, Slot slot) const bool CodeDirectory::slotIsPresent(Slot slot) const { if (slot >= -Slot(nSpecialSlots) && slot < Slot(nCodeSlots)) { - const Hashing::Byte *digest = (*this)[slot]; + const Hashing::Byte *digest = getSlot(slot, false); for (unsigned n = 0; n < hashSize; n++) if (digest[n]) return true; // non-zero digest => present @@ -322,15 +332,17 @@ bool CodeDirectory::verifyMemoryContent(CFDataRef data, const Byte* digest) cons // // Generate the canonical cdhash - the internal hash of the CodeDirectory itself. -// We currently truncate to 20 bytes because that's what the kernel can deal with. +// With 'truncate' truncates to 20 bytes, because that's what's commonly used. // -CFDataRef CodeDirectory::cdhash() const +CFDataRef CodeDirectory::cdhash(bool truncate) const { MakeHash hash(this); - Hashing::Byte digest[hash->digestLength()]; + vector digest_vector(hash->digestLength()); hash->update(this, this->length()); - hash->finish(digest); - return makeCFData(digest, min(hash->digestLength(), size_t(kSecCodeCDHashLength))); + hash->finish(digest_vector.data()); + return makeCFData(digest_vector.data(), + truncate ? min(hash->digestLength(), size_t(kSecCodeCDHashLength)) : + hash->digestLength()); } @@ -380,11 +392,11 @@ std::string CodeDirectory::hexHash(const unsigned char *hash) const std::string CodeDirectory::screeningCode() const { if (slotIsPresent(-cdInfoSlot)) // has Info.plist - return "I" + hexHash((*this)[-cdInfoSlot]); // use Info.plist hash + return "I" + hexHash(getSlot(-cdInfoSlot, false)); // use Info.plist hash if (slotIsPresent(-cdRepSpecificSlot)) // has Info.plist - return "R" + hexHash((*this)[-cdRepSpecificSlot]); // use Info.plist hash + return "R" + hexHash(getSlot(-cdRepSpecificSlot, false)); // use Info.plist hash if (pageSize == 0) // good-enough proxy for "not a Mach-O file" - return "M" + hexHash((*this)[0]); // use hash of main executable + return "M" + hexHash(getSlot(0, false)); // use hash of main executable return "N"; // no suitable screening code } @@ -406,5 +418,6 @@ const SecCodeDirectoryFlagTable kSecCodeDirectoryFlagTable[] = { { "restrict", kSecCodeSignatureRestrict, true }, { "enforcement", kSecCodeSignatureEnforcement, true }, { "library-validation", kSecCodeSignatureLibraryValidation, true }, + { "runtime", kSecCodeSignatureRuntime, true }, { NULL } }; diff --git a/OSX/libsecurity_codesigning/lib/codedirectory.h b/OSX/libsecurity_codesigning/lib/codedirectory.h index 5fdaa3557..eae6649fe 100644 --- a/OSX/libsecurity_codesigning/lib/codedirectory.h +++ b/OSX/libsecurity_codesigning/lib/codedirectory.h @@ -65,7 +65,7 @@ namespace CodeSigning { #define kSecCS_ENTITLEMENTFILE "CodeEntitlements" // entitlement configuration #define kSecCS_REPSPECIFICFILE "CodeRepSpecific" // DiskRep-specific use slot #define kSecCS_TOPDIRECTORYFILE "CodeTopDirectory" // Top-level directory list - +#define kSecCS_ENTITLEMENTDERFILE "CodeEntitlementDER" // DER entitlement representation // // Special hash slot values. In a CodeDirectory, these show up at negative slot @@ -93,6 +93,7 @@ enum { cdTopDirectorySlot = 4, // Application specific slot cdEntitlementSlot = 5, // embedded entitlement configuration cdRepSpecificSlot = 6, // for use by disk rep + cdEntitlementDERSlot = 7, // DER representation of entitlements // (add further primary slot numbers here) cdSlotCount, // total number of special slots (+1 for slot 0) @@ -112,6 +113,7 @@ enum { cdAlternateCodeDirectoryLimit = 0x1005, // 5+1 hashes should be enough for everyone... cdSignatureSlot = 0x10000, // CMS signature cdIdentificationSlot, // identification blob (detached signatures only) + cdTicketSlot, // ticket embedded in signature (DMG only) // (add further virtual slot numbers here) }; @@ -202,8 +204,11 @@ class CodeDirectory: public Blob { Endian execSegLimit; // limit of executable segment Endian execSegFlags; // exec segment flags + Endian runtime; // Runtime version encoded as an unsigned int + Endian preEncryptOffset; // offset of pre-encrypt hash slots + // works with the version field; see comments above - static const uint32_t currentVersion = 0x20400; // "version 2.4" + static const uint32_t currentVersion = 0x20500; // "version 2.5" static const uint32_t compatibilityLimit = 0x2F000; // "version 3 with wiggle room" static const uint32_t earliestVersion = 0x20001; // earliest supported version @@ -211,6 +216,7 @@ class CodeDirectory: public Blob { static const uint32_t supportsTeamID = 0x20200; // first version to support team ID option static const uint32_t supportsCodeLimit64 = 0x20300; // first version to support codeLimit64 static const uint32_t supportsExecSegment = 0x20400; // first version to support exec base and limit + static const uint32_t supportsPreEncrypt = 0x20500; // first version to support pre-encrypt hashes and runtime version void checkIntegrity() const; // throws if inconsistent or unsupported version @@ -228,18 +234,28 @@ class CodeDirectory: public Blob { // main hash array access SpecialSlot maxSpecialSlot() const; - unsigned char *operator [] (Slot slot) + unsigned char *getSlotMutable (Slot slot, bool preEncrypt) { assert(slot >= int(-nSpecialSlots) && slot < int(nCodeSlots)); - return at(hashOffset) + hashSize * slot; + + if (preEncrypt) { + if (version >= supportsPreEncrypt && preEncryptOffset != 0) { + assert(slot >= 0); + return at(preEncryptOffset) + hashSize * slot; + } else { + return NULL; + } + } else { + return at(hashOffset) + hashSize * slot; + } } - - const unsigned char *operator [] (Slot slot) const + + const unsigned char *getSlot (Slot slot, bool preEncrypt) const { - assert(slot >= int(-nSpecialSlots) && slot < int(nCodeSlots)); - return at(hashOffset) + hashSize * slot; + CodeDirectory *cd = const_cast(this); + return const_cast(cd->getSlotMutable(slot, preEncrypt)); } - + // // The main page hash array can be "scattered" across the code file // by specifying an array of Scatter elements, terminated with an @@ -266,9 +282,13 @@ class CodeDirectory: public Blob { uint64_t execSegmentLimit() const { return (version >= supportsExecSegment) ? execSegLimit.get() : 0; } uint64_t execSegmentFlags() const { return (version >= supportsExecSegment) ? execSegFlags.get() : 0; } + const unsigned char *preEncryptHashes() const { return getSlot(0, true); } + + uint32_t runtimeVersion() const {return (version >= supportsPreEncrypt) ? runtime.get() : 0; } + public: - bool validateSlot(const void *data, size_t size, Slot slot) const; // validate memory buffer against page slot - bool validateSlot(UnixPlusPlus::FileDesc fd, size_t size, Slot slot) const; // read and validate file + bool validateSlot(const void *data, size_t size, Slot slot, bool preEncrypted) const; // validate memory buffer against page slot + bool validateSlot(UnixPlusPlus::FileDesc fd, size_t size, Slot slot, bool preEncrypted) const; // read and validate file bool slotIsPresent(Slot slot) const; class Builder; @@ -276,7 +296,7 @@ class CodeDirectory: public Blob { public: static DynamicHash *hashFor(HashAlgorithm hashType); // create a DynamicHash subclass for (hashType) digests DynamicHash *getHash() const { return hashFor(this->hashType); } // make one for me - CFDataRef cdhash() const; + CFDataRef cdhash(bool truncate = true) const; static void multipleHashFileData(UnixPlusPlus::FileDesc fd, size_t limit, HashAlgorithms types, void (^action)(HashAlgorithm type, DynamicHash* hasher)); bool verifyMemoryContent(CFDataRef data, const Byte* digest) const; diff --git a/OSX/libsecurity_codesigning/lib/csgeneric.cpp b/OSX/libsecurity_codesigning/lib/csgeneric.cpp deleted file mode 100644 index e691c4b78..000000000 --- a/OSX/libsecurity_codesigning/lib/csgeneric.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2006-2007,2011-2012 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@ - */ - -// -// csgeneric - generic Code representative -// -#include "csgeneric.h" -#include "cs.h" -#include "StaticCode.h" -#include -#include - -namespace Security { -namespace CodeSigning { - -using MachPlusPlus::Port; - - -// -// Common call-out code for cshosting RPC service -// -#define CALL(host, name, args...) \ - OSStatus result; \ - if (cshosting_client_ ## name (host, mig_get_reply_port(), &result, args)) \ - MacOSError::throwMe(errSecCSNotAHost); \ - MacOSError::check(result); - - -// -// Construct a running process representation -// -GenericCode::GenericCode(SecCode *host, SecGuestRef guestRef) - : SecCode(host), mGuestRef(guestRef) -{ -} - - -// -// Identify a guest by attribute set, and return a new GenericCode representing it. -// This uses cshosting RPCs to ask the host (or its proxy). -// -SecCode *GenericCode::locateGuest(CFDictionaryRef attributes) -{ - if (Port host = hostingPort()) { - CFRef attrData; - void *attrPtr = NULL; size_t attrLength = 0; - if (attributes) { - attrData.take(CFPropertyListCreateXMLData(NULL, attributes)); - attrPtr = (void *)CFDataGetBytePtr(attrData); - attrLength = CFDataGetLength(attrData); - } - GuestChain guestPath; - mach_msg_type_number_t guestPathLength; - mach_port_t subport; - CALL(host, findGuest, guestRef(), attrPtr, (mach_msg_type_number_t)attrLength, - &guestPath, &guestPathLength, &subport); - CODESIGN_GUEST_LOCATE_GENERIC(this, guestPath, guestPathLength, subport); - SecPointer code = this; - for (unsigned n = 0; n < guestPathLength; n++) - code = new GenericCode(code, guestPath[n]); - return code.yield(); - } else - return NULL; // not found, no error -} - - -// -// Identify a guest by returning its StaticCode and running CodeDirectory hash. -// This uses cshosting RPCs to ask the host (or its proxy). -// -SecStaticCode *GenericCode::identifyGuest(SecCode *guest, CFDataRef *cdhashOut) -{ - if (GenericCode *iguest = dynamic_cast(guest)) { - FilePathOut path; - CFRef cdhash; - CFDictionary attributes(errSecCSHostProtocolInvalidAttribute); - identifyGuest(iguest->guestRef(), path, cdhash.aref(), attributes.aref()); - DiskRep::Context ctx; - if (CFNumberRef architecture = attributes.get(kSecGuestAttributeArchitecture)) { - cpu_type_t cpu = cfNumber(architecture); - if (CFNumberRef subarchitecture = attributes.get(kSecGuestAttributeSubarchitecture)) - ctx.arch = Architecture(cpu, cfNumber(subarchitecture)); - else - ctx.arch = Architecture(cpu); - } - SecPointer code = new GenericStaticCode(DiskRep::bestGuess(path, &ctx)); - CODESIGN_GUEST_IDENTIFY_GENERIC(iguest, iguest->guestRef(), code); - if (cdhash) { - CODESIGN_GUEST_CDHASH_GENERIC(iguest, (void *)CFDataGetBytePtr(cdhash), (unsigned)CFDataGetLength(cdhash)); - *cdhashOut = cdhash.yield(); - } - return code.yield(); - } else - MacOSError::throwMe(errSecCSNotAHost); -} - -// helper to drive the identifyGuest hosting IPC and return results as CF objects -void GenericCode::identifyGuest(SecGuestRef guest, char *path, CFDataRef &cdhash, CFDictionaryRef &attributes) -{ - if (Port host = hostingPort()) { - HashDataOut hash; - uint32_t hashLength; - XMLBlobOut attr; - uint32_t attrLength; - CALL(host, identifyGuest, guest, path, hash, &hashLength, &attr, &attrLength); - if (hashLength) - cdhash = makeCFData(hash, hashLength); - if (attrLength) { - CFRef attrData = makeCFData(attr, attrLength); - attributes = makeCFDictionaryFrom(attrData); -#if ROSETTA_TEST_HACK - CFMutableDictionaryRef hattr = makeCFMutableDictionary(attributes); - CFDictionaryAddValue(hattr, kSecGuestAttributeArchitecture, CFTempNumber(CPU_TYPE_POWERPC)); - CFRelease(attributes); - attributes = hattr; -#endif - } - } else - MacOSError::throwMe(errSecCSNotAHost); -} - - -// -// Get the Code Signing Status Word for a Code. -// This uses cshosting RPCs to ask the host (or its proxy). -// -SecCodeStatus GenericCode::getGuestStatus(SecCode *guest) -{ - if (Port host = hostingPort()) { - uint32_t status; - CALL(host, guestStatus, safe_cast(guest)->guestRef(), &status); - return status; - } else - MacOSError::throwMe(errSecCSNotAHost); -} - - -// -// Status changes are transmitted through the cshosting RPCs. -// -void GenericCode::changeGuestStatus(SecCode *iguest, SecCodeStatusOperation operation, CFDictionaryRef arguments) -{ - if (/* GenericCode *guest = */dynamic_cast(iguest)) - switch (operation) { - case kSecCodeOperationNull: - break; - case kSecCodeOperationInvalidate: - case kSecCodeOperationSetHard: - case kSecCodeOperationSetKill: - MacOSError::throwMe(errSecCSUnimplemented); - default: - MacOSError::throwMe(errSecCSUnimplemented); - } - else - MacOSError::throwMe(errSecCSNoSuchCode); -} - - -// -// Return the Hosting Port for this Code. -// May return MACH_PORT_NULL if the code is not a code host. -// Throws if we can't get the hosting port for some reason (and can't positively -// determine that there is none). -// -// Note that we do NOT cache negative outcomes. Being a host is a dynamic property, -// and this Code may not have commenced hosting operations yet. For non- (or not-yet-)hosts -// we simply return NULL. -// -Port GenericCode::hostingPort() -{ - if (!mHostingPort) { - if (staticCode()->codeDirectory()->flags & kSecCodeSignatureHost) { - mHostingPort = getHostingPort(); - CODESIGN_GUEST_HOSTINGPORT(this, mHostingPort); - } - } - return mHostingPort; -} - - -// -// A pure GenericHost has no idea where to get a hosting port from. -// This method must be overridden to get one. -// However, we do handle a contiguous chain of GenericCodes by deferring -// to our next-higher host for it. -// -mach_port_t GenericCode::getHostingPort() -{ - if (GenericCode *genericHost = dynamic_cast(host())) - return genericHost->getHostingPort(); - else - MacOSError::throwMe(errSecCSNotAHost); -} - - -} // CodeSigning -} // Security diff --git a/OSX/libsecurity_codesigning/lib/csgeneric.h b/OSX/libsecurity_codesigning/lib/csgeneric.h deleted file mode 100644 index 0a3a17296..000000000 --- a/OSX/libsecurity_codesigning/lib/csgeneric.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2006,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@ - */ - -// -// csgeneric - generic Code representative -// -#ifndef _H_CSGENERIC -#define _H_CSGENERIC - -#include "Code.h" -#include -#include -#include - -namespace Security { -namespace CodeSigning { - - -// -// A SecCode that represents "generic" code. -// Generic code is, well, generic. It doesn't have any real resources that define it, -// and so it's defined, de facto, by its host. The Code Signing subsystem has no special -// knowledge as to its nature, and so it just asks the host about everything. The asking -// is done via the cshosting Mach RPC protocol, which can be implemented by hosts in whichever -// way they find reasonable. This code doesn't care, as long as someone is answering. -// -// It is all right to subclass GenericCode to inherit access to the cshosting protocol. -// -class GenericCode : public SecCode { -public: - GenericCode(SecCode *host, SecGuestRef guestRef = kSecNoGuest); - - SecCode *locateGuest(CFDictionaryRef attributes); - SecStaticCode *identifyGuest(SecCode *guest, CFDataRef *cdhash); - SecCodeStatus getGuestStatus(SecCode *guest); - void changeGuestStatus(SecCode *guest, SecCodeStatusOperation operation, CFDictionaryRef arguments); - - SecGuestRef guestRef() const { return mGuestRef; } - -protected: - MachPlusPlus::Port hostingPort(); - virtual mach_port_t getHostingPort(); - -private: - void identifyGuest(SecGuestRef guest, char *path, CFDataRef &cdhash, CFDictionaryRef &attributes); - -private: - MachPlusPlus::Port mHostingPort; // cached hosting port for this Code - SecGuestRef mGuestRef; // guest reference -}; - - -// -// We don't need a GenericCode variant of SecStaticCode -// -typedef SecStaticCode GenericStaticCode; - - -} // end namespace CodeSigning -} // end namespace Security - -#endif // !_H_CSGENERIC diff --git a/OSX/libsecurity_codesigning/lib/cskernel.cpp b/OSX/libsecurity_codesigning/lib/cskernel.cpp index 7595bd520..0d1c48522 100644 --- a/OSX/libsecurity_codesigning/lib/cskernel.cpp +++ b/OSX/libsecurity_codesigning/lib/cskernel.cpp @@ -106,7 +106,7 @@ SecCode *KernelCode::locateGuest(CFDictionaryRef attributes) MacOSError::throwMe(errSecCSInvalidAttributeValues); try { - diskRep = new PidDiskRep(pid, infoPlist); + diskRep = new PidDiskRep(pid, audit, infoPlist); } catch (...) { } } diff --git a/OSX/libsecurity_codesigning/lib/csprocess.cpp b/OSX/libsecurity_codesigning/lib/csprocess.cpp index 8e208c069..80b585213 100644 --- a/OSX/libsecurity_codesigning/lib/csprocess.cpp +++ b/OSX/libsecurity_codesigning/lib/csprocess.cpp @@ -37,7 +37,7 @@ namespace CodeSigning { // Construct a running process representation // ProcessCode::ProcessCode(pid_t pid, const audit_token_t* token, PidDiskRep *pidDiskRep /*= NULL */) - : GenericCode(KernelCode::active()), mPid(pid), mPidBased(pidDiskRep) + : SecCode(KernelCode::active()), mPid(pid), mPidBased(pidDiskRep) { if (token) mAudit = new audit_token_t(*token); @@ -46,12 +46,6 @@ ProcessCode::ProcessCode(pid_t pid, const audit_token_t* token, PidDiskRep *pidD } -mach_port_t ProcessCode::getHostingPort() -{ - return SecurityServer::ClientSession().hostingPort(pid()); -} - - int ProcessCode::csops(unsigned int ops, void *addr, size_t size) { // pass pid and audit token both if we have it, or just the pid if we don't @@ -84,7 +78,10 @@ CFDictionaryRef ProcessDynamicCode::infoDictionary() { if (mGuest->pidBased()->supportInfoPlist()) return SecStaticCode::infoDictionary(); - return makeCFDictionary(0); + if (!mEmptyInfoDict) { + mEmptyInfoDict.take(makeCFDictionary(0)); + } + return mEmptyInfoDict; } void ProcessDynamicCode::validateComponent(CodeDirectory::SpecialSlot slot, OSStatus fail /* = errSecCSSignatureFailed */) diff --git a/OSX/libsecurity_codesigning/lib/csprocess.h b/OSX/libsecurity_codesigning/lib/csprocess.h index d41ef23cd..b0a370e42 100644 --- a/OSX/libsecurity_codesigning/lib/csprocess.h +++ b/OSX/libsecurity_codesigning/lib/csprocess.h @@ -27,7 +27,7 @@ #ifndef _H_CSPROCESS #define _H_CSPROCESS -#include "csgeneric.h" +#include "Code.h" #include "StaticCode.h" #include "piddiskrep.h" #include @@ -38,12 +38,9 @@ namespace CodeSigning { // // A SecCode that represents a running UNIX process. -// Processes are identified by pid. +// Processes are identified by pid and audit token. // -// ProcessCode inherits GenericCode's access to the cshosting Mach protocol to -// deal with guests. -// -class ProcessCode : public GenericCode { +class ProcessCode : public SecCode { public: ProcessCode(pid_t pid, const audit_token_t* token, PidDiskRep *pidDiskRep = NULL); ~ProcessCode() throw () { delete mAudit; } @@ -55,8 +52,6 @@ class ProcessCode : public GenericCode { int csops(unsigned int ops, void *addr, size_t size); - mach_port_t getHostingPort(); - private: pid_t mPid; audit_token_t* mAudit; @@ -80,7 +75,7 @@ class ProcessDynamicCode : public SecStaticCode { void validateComponent(CodeDirectory::SpecialSlot slot, OSStatus fail = errSecCSSignatureFailed); private: ProcessCode *mGuest; - + CFRef mEmptyInfoDict; }; } // end namespace CodeSigning diff --git a/OSX/libsecurity_codesigning/lib/csutilities.cpp b/OSX/libsecurity_codesigning/lib/csutilities.cpp index e25e7b581..774b6ee2c 100644 --- a/OSX/libsecurity_codesigning/lib/csutilities.cpp +++ b/OSX/libsecurity_codesigning/lib/csutilities.cpp @@ -24,8 +24,16 @@ // // csutilities - miscellaneous utilities for the code signing implementation // + #include "csutilities.h" +#include +#include +#include +#include +#include +#include #include +#include #include #include #include "requirement.h" @@ -34,6 +42,16 @@ #include #include +extern "C" { + +/* Decode a choice of UTCTime or GeneralizedTime to a CFAbsoluteTime. Return + an absoluteTime if the date was valid and properly decoded. Return + NULL_TIME otherwise. */ +CFAbsoluteTime SecAbsoluteTimeFromDateContent(DERTag tag, const uint8_t *bytes, + size_t length); + +} + namespace Security { namespace CodeSigning { @@ -151,6 +169,65 @@ bool certificateHasPolicy(SecCertificateRef cert, const CSSM_OID &policyOid) SecCertificateReleaseFirstFieldValue(cert, &CSSMOID_PolicyConstraints, data); return matched; } + + +CFDateRef certificateCopyFieldDate(SecCertificateRef cert, const CSSM_OID &policyOid) +{ + CFDataRef oidData = NULL; + CFDateRef value = NULL; + CFDataRef data = NULL; + SecAsn1CoderRef coder = NULL; + CSSM_DATA str = { 0 }; + CFAbsoluteTime time = 0.0; + OSStatus status = 0; + bool isCritical; + + oidData = CFDataCreateWithBytesNoCopy(NULL, policyOid.Data, policyOid.Length, + kCFAllocatorNull); + + if (oidData == NULL) { + goto out; + } + + data = SecCertificateCopyExtensionValue(cert, oidData, &isCritical); + + if (data == NULL) { + goto out; + } + + status = SecAsn1CoderCreate(&coder); + if (status != 0) { + goto out; + } + + // We currently only support UTF8 strings. + status = SecAsn1Decode(coder, CFDataGetBytePtr(data), CFDataGetLength(data), + kSecAsn1UTF8StringTemplate, &str); + if (status != 0) { + goto out; + } + + time = SecAbsoluteTimeFromDateContent(ASN1_GENERALIZED_TIME, + str.Data, str.Length); + + if (time == 0.0) { + goto out; + } + + value = CFDateCreate(NULL, time); +out: + if (coder) { + SecAsn1CoderRelease(coder); + } + if (data) { + CFRelease(data); + } + if (oidData) { + CFRelease(oidData); + } + + return value; +} #endif // diff --git a/OSX/libsecurity_codesigning/lib/csutilities.h b/OSX/libsecurity_codesigning/lib/csutilities.h index 668ffb86b..bd4408cdb 100644 --- a/OSX/libsecurity_codesigning/lib/csutilities.h +++ b/OSX/libsecurity_codesigning/lib/csutilities.h @@ -128,6 +128,7 @@ size_t hashFileData(const char *path, _Hash *hasher) #if TARGET_OS_OSX bool certificateHasField(SecCertificateRef cert, const CSSM_OID &oid); bool certificateHasPolicy(SecCertificateRef cert, const CSSM_OID &policyOid); +CFDateRef certificateCopyFieldDate(SecCertificateRef cert, const CSSM_OID &policyOid); #endif // diff --git a/OSX/libsecurity_codesigning/lib/diskimagerep.cpp b/OSX/libsecurity_codesigning/lib/diskimagerep.cpp index a24b9e597..be2443d12 100644 --- a/OSX/libsecurity_codesigning/lib/diskimagerep.cpp +++ b/OSX/libsecurity_codesigning/lib/diskimagerep.cpp @@ -25,6 +25,7 @@ // diskimagerep - DiskRep representing a single read-only compressed disk image file // #include "diskimagerep.h" +#include "notarization.h" #include "sigblob.h" #include "CodeSigner.h" #include @@ -235,6 +236,15 @@ void DiskImageRep::Writer::addDiscretionary(CodeDirectory::Builder &builder) { } +void DiskImageRep::registerStapledTicket() +{ + CFRef data = NULL; + if (mSigningData) { + data.take(mSigningData->component(cdTicketSlot)); + registerStapledTicketInDMG(data); + } +} + } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_codesigning/lib/diskimagerep.h b/OSX/libsecurity_codesigning/lib/diskimagerep.h index 96a63a2aa..91a091933 100644 --- a/OSX/libsecurity_codesigning/lib/diskimagerep.h +++ b/OSX/libsecurity_codesigning/lib/diskimagerep.h @@ -52,7 +52,8 @@ class DiskImageRep : public SingleDiskRep { void prepareForSigning(SigningContext& state); static bool candidate(UnixPlusPlus::FileDesc &fd); - + void registerStapledTicket(); + public: static CFDataRef identificationFor(MachO *macho); diff --git a/OSX/libsecurity_codesigning/lib/diskrep.cpp b/OSX/libsecurity_codesigning/lib/diskrep.cpp index cc6e389a4..0fd4ede85 100644 --- a/OSX/libsecurity_codesigning/lib/diskrep.cpp +++ b/OSX/libsecurity_codesigning/lib/diskrep.cpp @@ -78,7 +78,6 @@ void DiskRep::Writer::addDiscretionary(CodeDirectory::Builder &) // do nothing } - // // Given a file system path, come up with the most likely correct // disk representation for what's there. @@ -300,6 +299,9 @@ std::string DiskRep::canonicalIdentifier(const std::string &name) return s.substr(0, p); } +void DiskRep::registerStapledTicket() +{ /* do nothing */ } + // // Writers diff --git a/OSX/libsecurity_codesigning/lib/diskrep.h b/OSX/libsecurity_codesigning/lib/diskrep.h index 131f8f68e..1f1a10c5d 100644 --- a/OSX/libsecurity_codesigning/lib/diskrep.h +++ b/OSX/libsecurity_codesigning/lib/diskrep.h @@ -82,6 +82,8 @@ class DiskRep : public RefCount { virtual void flush(); // flush caches (refetch as needed) virtual CFDictionaryRef diskRepInformation(); // information from diskrep + virtual void registerStapledTicket(); + // default values for signing operations virtual std::string recommendedIdentifier(const SigningContext &ctx) = 0; // default identifier virtual CFDictionaryRef defaultResourceRules(const SigningContext &ctx); // default resource rules [none] @@ -90,8 +92,11 @@ class DiskRep : public RefCount { virtual size_t pageSize(const SigningContext &ctx); // default main executable page size [infinite, i.e. no paging] virtual void strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags); // perform strict validation + virtual void strictValidateStructure(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags) { }; // perform structural strict validation virtual CFArrayRef allowedResourceOmissions(); // allowed (default) resource omission rules + virtual bool appleInternalForcePlatform() const {return false;}; + bool mainExecutableIsMachO() { return mainExecutableImage() != NULL; } // shorthands @@ -154,6 +159,27 @@ class DiskRep : public RefCount { static const size_t monolithicPageSize = 0; // default page size for non-Mach-O executables }; +/* + * Editable Disk Reps allow editing of their existing code signature. + * Specifically, they allow for individual components to be replaced, + * while preserving all other components. + * Lots of restrictions apply, e.g. machO signatures' superblobs may + * not change in size, and components covered by the code directory + * cannot be replaced without adjusting the code directory. + * Replacing or adding CMS blobs (having reserved enough size in the + * superblob beforehand) is the original reason this trait exists. + */ +class EditableDiskRep { +public: + typedef std::map> RawComponentMap; + + /* Return all components in raw form. + * Signature editing will add all the components obtained hereby + * back to their specific slots, though some of them may have + * been replaced in the map. + */ + virtual RawComponentMap createRawComponents() = 0; +}; // // Write-access objects. @@ -186,10 +212,18 @@ class DiskRep::Writer : public RefCount { void signature(CFDataRef data) { component(cdSignatureSlot, data); } void codeDirectory(const CodeDirectory *cd, CodeDirectory::SpecialSlot slot) { component(slot, CFTempData(cd->data(), cd->length())); } - + +#if TARGET_OS_OSX + bool getPreserveAFSC() { return mPreserveAFSC; } + void setPreserveAFSC(bool flag) { mPreserveAFSC = flag; } +#endif + private: Architecture mArch; uint32_t mAttributes; +#if TARGET_OS_OSX + bool mPreserveAFSC = false; // preserve AFSC compression +#endif }; // @@ -241,6 +275,7 @@ class FilterRep : public DiskRep { size_t pageSize(const SigningContext &ctx) { return mOriginal->pageSize(ctx); } void strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags) { mOriginal->strictValidate(cd, tolerated, flags); } + void strictValidateStructure(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags) { mOriginal->strictValidateStructure(cd, tolerated, flags); } CFArrayRef allowedResourceOmissions() { return mOriginal->allowedResourceOmissions(); } private: diff --git a/OSX/libsecurity_codesigning/lib/evaluationmanager.cpp b/OSX/libsecurity_codesigning/lib/evaluationmanager.cpp index 2332ca0ed..22317b562 100644 --- a/OSX/libsecurity_codesigning/lib/evaluationmanager.cpp +++ b/OSX/libsecurity_codesigning/lib/evaluationmanager.cpp @@ -196,7 +196,8 @@ void EvaluationTask::performEvaluation(SecAssessmentFlags flags, CFDictionaryRef dispatch_semaphore_t startLock = dispatch_semaphore_create(0); // create the assessment block - dispatch_async(mWorkQueue, dispatch_block_create_with_qos_class(DISPATCH_BLOCK_ENFORCE_QOS_CLASS, QOS_CLASS_UTILITY, 0, ^{ + dispatch_block_t assessmentBlock = + dispatch_block_create_with_qos_class(DISPATCH_BLOCK_ENFORCE_QOS_CLASS, QOS_CLASS_UTILITY, 0, ^{ // signal that the assessment is ready to start dispatch_semaphore_signal(startLock); @@ -236,8 +237,12 @@ void EvaluationTask::performEvaluation(SecAssessmentFlags flags, CFDictionaryRef } catch(...) { mExceptionToRethrow = std::current_exception(); } - - })); + + }); + assert(assessmentBlock != NULL); + + dispatch_async(mWorkQueue, assessmentBlock); + Block_release(assessmentBlock); // wait for the assessment to start dispatch_semaphore_wait(startLock, DISPATCH_TIME_FOREVER); @@ -300,12 +305,19 @@ void EvaluationTask::waitForCompletion(SecAssessmentFlags flags, CFMutableDictio // wait for the assessment to complete; our wait block will queue up behind // the assessment and the copy its results - dispatch_sync(mWorkQueue, dispatch_block_create_with_qos_class (DISPATCH_BLOCK_ENFORCE_QOS_CLASS, qos_class, 0, ^{ - // copy the class result back to the caller - cfDictionaryApplyBlock(mResult.get(), ^(const void *key, const void *value){ - CFDictionaryAddValue(result, key, value); - }); - })); + dispatch_block_t wait_block = dispatch_block_create_with_qos_class + (DISPATCH_BLOCK_ENFORCE_QOS_CLASS, + qos_class, 0, + ^{ + // copy the class result back to the caller + cfDictionaryApplyBlock(mResult.get(), + ^(const void *key, const void *value){ + CFDictionaryAddValue(result, key, value); + }); + }); + assert(wait_block != NULL); + dispatch_sync(mWorkQueue, wait_block); + Block_release(wait_block); } diff --git a/OSX/libsecurity_codesigning/lib/legacydevid.cpp b/OSX/libsecurity_codesigning/lib/legacydevid.cpp new file mode 100644 index 000000000..239d73e45 --- /dev/null +++ b/OSX/libsecurity_codesigning/lib/legacydevid.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2019 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include "legacydevid.h" +#include "SecAssessment.h" +#include "requirement.h" + +#include + +namespace Security { +namespace CodeSigning { + +static const CFStringRef kLegacyPolicyPreferenceDomain = CFSTR("com.apple.security.syspolicy"); +static const CFStringRef kLegacyPolicyAccountCreationCutOff = CFSTR("AccountCreationCutOffDate"); +static const CFStringRef kLegacyPolicySecureTimestampCutOff = CFSTR("SecureTimestampCutOffDate"); +static const CFAbsoluteTime kLegacyPolicyAccountCreationDefaultCutOff = 576374400.0; // seconds from January 1, 2001 to April 7, 2019 GMT +static const CFAbsoluteTime kLegacyPolicySecureTimestampDefaultCutOff = 581040000.0; // seconds from January 1, 2001 to June 1, 2019 GMT + +static CFDateRef +copyCutOffDate(const CFStringRef key, CFAbsoluteTime defaultCutoff) +{ + CFDateRef defaultDate = CFDateCreate(NULL, defaultCutoff); + CFDateRef outputDate = defaultDate; + CFDateRef prefDate = NULL; + + CFTypeRef prefVal = (CFDateRef)CFPreferencesCopyValue(key, + kLegacyPolicyPreferenceDomain, + kCFPreferencesCurrentUser, + kCFPreferencesAnyHost); + if (prefVal && CFGetTypeID(prefVal) == CFDateGetTypeID()) { + prefDate = (CFDateRef)prefVal; + } + + if (prefDate) { + CFComparisonResult res = CFDateCompare(defaultDate, prefDate, NULL); + if (res > 0) { + outputDate = prefDate; + } + } + + CFRetain(outputDate); + + if (prefVal) { + CFRelease(prefVal); + } + if (defaultDate) { + CFRelease(defaultDate); + } + return outputDate; +} + +bool +meetsDeveloperIDLegacyAllowedPolicy(const Requirement::Context *context) +{ + CFRef cd; + CFRef error; + CFRef teamID; + bool meets_legacy_policy = false; + SecCSDigestAlgorithm hashType = kSecCodeSignatureNoHash; + SecCertificateRef cert = NULL; + CFAbsoluteTime accountCreationTime = 0.0; + + if (context == NULL) { + meets_legacy_policy = false; + goto lb_exit; + } + + // First check account creation date in certs + // An account creation date after the cut off must be notarized so it fails the legacy policy. + // No account creation date or an account creation date before the cut off requires additional checking + cert = context->cert(Requirement::leafCert); + if (SecCertificateGetDeveloperIDDate(cert, &accountCreationTime, &error.aref())) { + //There is an account creation date + CFRef accountCreationDate = CFDateCreate(NULL, accountCreationTime); + CFRef accountCreationCutoffDate = copyCutOffDate(kLegacyPolicyAccountCreationCutOff, + kLegacyPolicyAccountCreationDefaultCutOff); + secinfo("meetsDeveloperIDLegacyAllowedPolicy", "Account Creation Date Cutoff: %@", accountCreationCutoffDate.get()); + secinfo("meetsDeveloperIDLegacyAllowedPolicy", "Account Creation date: %@", accountCreationDate.get()); + + CFComparisonResult res = CFDateCompare(accountCreationDate, accountCreationCutoffDate, NULL); + if (res >= 0) { + // The account was created on or after our cut off so it doesn't meet legacy policy + meets_legacy_policy = false; + secinfo("meetsDeveloperIDLegacyAllowedPolicy", "Account creation date %@ is after cut-off %@", accountCreationDate.get(), accountCreationCutoffDate.get()); + goto lb_exit; + } + // Account creation date before the cut off means we fall through + } else { + CFIndex errorCode = CFErrorGetCode(error); + if (errorCode != errSecMissingRequiredExtension) { + secerror("Unexpected error checking account creation date: %ld", errorCode); + meets_legacy_policy = false; + goto lb_exit; + } + // there was no account creation date so fall through + } + + // Next check secure time stamp + if (context->secureTimestamp) { + CFRef secureTimestampCutoffDate = copyCutOffDate(kLegacyPolicySecureTimestampCutOff, + kLegacyPolicySecureTimestampDefaultCutOff); + secinfo("meetsDeveloperIDLegacyAllowedPolicy", "Secure Timestamp Cutoff Date cutoff: %@", secureTimestampCutoffDate.get()); + secinfo("meetsDevleoperIDLegacyAllowedPolicy", "Secure Timestamp: %@", context->secureTimestamp); + CFComparisonResult res = CFDateCompare(context->secureTimestamp, secureTimestampCutoffDate, NULL); + if (res >= 0) { + // Secure timestamp is on or after the cut of so it doesn't meet legacy policy + meets_legacy_policy = false; + secinfo("meetsDeveloperIDLegacyAllowedPolicy", "Secure timestamp %@ is after cut-off %@", context->secureTimestamp, secureTimestampCutoffDate.get()); + } else { + // Secure timestamp is before the cut off so we meet the legacy policy + meets_legacy_policy = true; + } + } + + if (!meets_legacy_policy) { + // Just check against the legacy lists, both by hash and team ID. + if (context->directory) { + cd.take(context->directory->cdhash()); + hashType = (SecCSDigestAlgorithm)context->directory->hashType; + } else if (context->packageChecksum) { + cd = context->packageChecksum; + hashType = context->packageAlgorithm; + } + + if (cd.get() == NULL) { + // No cdhash means we can't check the legacy lists + meets_legacy_policy = false; + goto lb_exit; + } + + if (context->teamIdentifier) { + teamID.take(CFStringCreateWithCString(kCFAllocatorDefault, context->teamIdentifier, kCFStringEncodingUTF8)); + } + + secnotice("legacy_list", "checking the legacy list for %d, %@, %@", hashType, cd.get(), teamID.get()); + #if TARGET_OS_OSX + if (SecAssessmentLegacyCheck(cd, hashType, teamID, &error.aref())) { + meets_legacy_policy = true; + } else { + meets_legacy_policy = false; + if (error.get() != NULL) { + secerror("Error checking with notarization daemon: %ld", CFErrorGetCode(error)); + } + } + #endif + } +lb_exit: + secnotice("legacy_list", "meetsDeveloperIDLegacyAllowedPolicy = %d", meets_legacy_policy); + return meets_legacy_policy; +} + +} +} diff --git a/OSX/libsecurity_codesigning/lib/legacydevid.h b/OSX/libsecurity_codesigning/lib/legacydevid.h new file mode 100644 index 000000000..0c1d6b261 --- /dev/null +++ b/OSX/libsecurity_codesigning/lib/legacydevid.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2019 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#ifndef H_LEGACYLIST +#define H_LEGACYLIST + +#include +#include "requirement.h" + +namespace Security { +namespace CodeSigning { + +bool meetsDeveloperIDLegacyAllowedPolicy(const Requirement::Context *context); + +} // end namespace CodeSigning +} // end namespace Security + +#endif /* H_LEGACYLIST */ diff --git a/OSX/libsecurity_codesigning/lib/machorep.cpp b/OSX/libsecurity_codesigning/lib/machorep.cpp index 0959b5595..02e7faa8b 100644 --- a/OSX/libsecurity_codesigning/lib/machorep.cpp +++ b/OSX/libsecurity_codesigning/lib/machorep.cpp @@ -110,38 +110,31 @@ void MachORep::prepareForSigning(SigningContext &context) { if (context.digestAlgorithms().empty()) { auto_ptr macho(mainExecutableImage()->architecture()); - - if (const version_min_command *version = macho->findMinVersion()) { - uint32_t limit = 0; - switch (macho->flip(version->cmd)) { - case LC_VERSION_MIN_MACOSX: + + uint32_t limit = 0; + switch (macho->platform()) { + case 0: + // If we don't know the platform, we stay agile. + return; + case PLATFORM_MACOS: + // 10.11.4 had first proper sha256 support. limit = (10 << 16 | 11 << 8 | 4 << 0); break; -#if 0 /* need updated libMIS before we can do this switch */ - case LC_VERSION_MIN_IPHONEOS: - limit = (9 << 16 | 3 << 8); - break; - case LC_VERSION_MIN_WATCHOS: - limit = (2 << 16 | 2 << 8); - break; - case LC_VERSION_MIN_TVOS: - limit = (9 << 16 | 2 << 8); + case PLATFORM_TVOS: + case PLATFORM_IOS: + // iOS 11 and tvOS 11 had first proper sha256 support. + limit = (11 << 16 | 0 << 8 | 0 << 0); break; + case PLATFORM_WATCHOS: + // We stay agile on the watch right now. + return; default: + // All other platforms are assumed to be new and support SHA256. break; -#else - case LC_VERSION_MIN_IPHONEOS: - case LC_VERSION_MIN_WATCHOS: - case LC_VERSION_MIN_TVOS: - return; - default: - break; -#endif - } - if (macho->flip(version->version) >= limit) { - // young enough not to need SHA-1 legacy support - context.setDigestAlgorithm(kSecCodeSignatureHashSHA256); - } + } + if (macho->minVersion() >= limit) { + // young enough not to need SHA-1 legacy support + context.setDigestAlgorithm(kSecCodeSignatureHashSHA256); } } } @@ -162,29 +155,9 @@ size_t MachORep::signingLimit() } bool MachORep::needsExecSeg(const MachO& macho) { - if (const version_min_command *version = macho.findMinVersion()) { - uint32_t min = UINT32_MAX; - - switch (macho.flip(version->cmd)) { - case LC_VERSION_MIN_IPHONEOS: - case LC_VERSION_MIN_TVOS: - min = (11 << 16 | 0 << 8); - break; - case LC_VERSION_MIN_WATCHOS: - min = (4 << 16 | 0 << 8); - break; - - default: - /* macOS currently does not get this. */ - return false; - } - - if (macho.flip(version->version) >= min) { - return true; - } - } - - return false; + uint32_t platform = macho.platform(); + // Everything embedded gets an exec segment. + return platform != 0 && platform != PLATFORM_MACOS; } size_t MachORep::execSegBase(const Architecture *arch) @@ -292,6 +265,21 @@ CFDataRef MachORep::component(CodeDirectory::SpecialSlot slot) } } +// +// Retrieve all components, used for signature editing. +// +EditableDiskRep::RawComponentMap MachORep::createRawComponents() +{ + EditableDiskRep::RawComponentMap blobMap; + const EmbeddedSignatureBlob &blobs = *signingData(); + + for (unsigned int i = 0; i < blobs.count(); ++i) { + CodeDirectory::Slot slot = blobs.type(i); + const BlobCore *blob = blobs.blob(i); + blobMap[slot] = blobs.blobData(slot, blob); + } + return blobMap; +} // Retrieve a component from the embedded signature SuperBlob (if present). // This reads the entire signing SuperBlob when first called for an executable, @@ -302,6 +290,18 @@ CFDataRef MachORep::component(CodeDirectory::SpecialSlot slot) // calls wouldn't be slower in the end. // CFDataRef MachORep::embeddedComponent(CodeDirectory::SpecialSlot slot) +{ + if (signingData()) { + return signingData()->component(slot); + } + + // not found + return NULL; +} + + + +EmbeddedSignatureBlob *MachORep::signingData() { if (!mSigningData) { // fetch and cache auto_ptr macho(mainExecutableImage()->architecture()); @@ -311,20 +311,16 @@ CFDataRef MachORep::embeddedComponent(CodeDirectory::SpecialSlot slot) size_t length = macho->flip(cs->datasize); if ((mSigningData = EmbeddedSignatureBlob::readBlob(macho->fd(), macho->offset() + offset, length))) { secinfo("machorep", "%zd signing bytes in %d blob(s) from %s(%s)", - mSigningData->length(), mSigningData->count(), - mainExecutablePath().c_str(), macho->architecture().name()); + mSigningData->length(), mSigningData->count(), + mainExecutablePath().c_str(), macho->architecture().name()); } else { secinfo("machorep", "failed to read signing bytes from %s(%s)", - mainExecutablePath().c_str(), macho->architecture().name()); + mainExecutablePath().c_str(), macho->architecture().name()); MacOSError::throwMe(errSecCSSignatureInvalid); } } } - if (mSigningData) - return mSigningData->component(slot); - - // not found - return NULL; + return mSigningData; } @@ -398,15 +394,28 @@ CFDictionaryRef MachORep::diskRepInformation() auto_ptr macho (mainExecutableImage()->architecture()); CFRef info; - if (const version_min_command *version = macho->findMinVersion()) { - + uint32_t platform = 0; + uint32_t minVersion = 0; + uint32_t sdkVersion = 0; + + if (macho->version(&platform, &minVersion, &sdkVersion)) { + + /* These keys replace the old kSecCodeInfoDiskRepOSPlatform, kSecCodeInfoDiskRepOSVersionMin + * and kSecCodeInfoDiskRepOSSDKVersion. The keys were renamed because we changed what value + * "platform" represents: For the old key, the actual load command (e.g. LC_VERSION_MIN_MACOSX) + * was returned; for the new key, we return one of the PLATFORM_* values used by LC_BUILD_VERSION. + * + * The keys are private and undocumented, and maintaining a translation table between the old and + * new domain would provide little value at high cost, but we do remove the old keys to make + * the change obvious. + */ + info.take(cfmake("{%O = %d,%O = %d,%O = %d}", - kSecCodeInfoDiskRepOSPlatform, macho->flip(version->cmd), - kSecCodeInfoDiskRepOSVersionMin, macho->flip(version->version), - kSecCodeInfoDiskRepOSSDKVersion, macho->flip(version->sdk))); + kSecCodeInfoDiskRepVersionPlatform, platform, + kSecCodeInfoDiskRepVersionMin, minVersion, + kSecCodeInfoDiskRepVersionSDK, sdkVersion)); - if (macho->flip(version->cmd) == LC_VERSION_MIN_MACOSX && - macho->flip(version->sdk) < (10 << 16 | 9 << 8)) + if (platform == PLATFORM_MACOS && sdkVersion < (10 << 16 | 9 << 8)) { info.take(cfmake("{+%O, %O = 'OS X SDK version before 10.9 does not support Library Validation'}", info.get(), diff --git a/OSX/libsecurity_codesigning/lib/machorep.h b/OSX/libsecurity_codesigning/lib/machorep.h index d30ba5379..ef2181bb6 100644 --- a/OSX/libsecurity_codesigning/lib/machorep.h +++ b/OSX/libsecurity_codesigning/lib/machorep.h @@ -45,12 +45,13 @@ namespace CodeSigning { // that it's driven directly from the signing code, with no // abstractions to get in the way. // -class MachORep : public SingleDiskRep { +class MachORep : public SingleDiskRep, public EditableDiskRep { public: MachORep(const char *path, const Context *ctx = NULL); virtual ~MachORep(); CFDataRef component(CodeDirectory::SpecialSlot slot); + RawComponentMap createRawComponents(); CFDataRef identification(); Universal *mainExecutableImage(); void prepareForSigning(SigningContext &context); @@ -68,7 +69,7 @@ class MachORep : public SingleDiskRep { void strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags); void flush(); // flush cache - + static bool candidate(UnixPlusPlus::FileDesc &fd); public: @@ -86,9 +87,10 @@ class MachORep : public SingleDiskRep { private: static bool needsExecSeg(const MachO& macho); + EmbeddedSignatureBlob *signingData(); Universal *mExecutable; // cached Mach-O/Universal reference to mainExecutablePath() - EmbeddedSignatureBlob *mSigningData; // cached signing data from current architecture + mutable EmbeddedSignatureBlob *mSigningData; // cached signing data from current architecture }; diff --git a/OSX/libsecurity_codesigning/lib/notarization.cpp b/OSX/libsecurity_codesigning/lib/notarization.cpp new file mode 100644 index 000000000..fa75c0d02 --- /dev/null +++ b/OSX/libsecurity_codesigning/lib/notarization.cpp @@ -0,0 +1,309 @@ +/* + * 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@ + */ +#include "SecAssessment.h" +#include "notarization.h" +#include + +typedef struct __attribute__((packed)) _package_trailer { + uint8_t magic[4]; + uint16_t version; + uint16_t type; + uint32_t length; + uint8_t reserved[4]; +} package_trailer_t; + +enum TrailerType { + TrailerTypeInvalid = 0, + TrailerTypeTerminator, + TrailerTypeTicket, +}; + +static const char *TrailerMagic = "t8lr"; + +namespace Security { +namespace CodeSigning { + +static void +registerStapledTicketWithSystem(CFDataRef data) +{ + secinfo("notarization", "Registering stapled ticket with system"); + +#if TARGET_OS_OSX + CFErrorRef error = NULL; + if (!SecAssessmentTicketRegister(data, &error)) { + secerror("Error registering stapled ticket: %@", data); + } +#endif // TARGET_OS_OSX +} + +bool +checkNotarizationServiceForRevocation(CFDataRef hash, SecCSDigestAlgorithm hashType, double *date) +{ + bool is_revoked = false; + + secinfo("notarization", "checking with online notarization service for hash: %@", hash); + +#if TARGET_OS_OSX + CFRef error; + if (!SecAssessmentTicketLookup(hash, hashType, kSecAssessmentTicketFlagForceOnlineCheck, date, &error.aref())) { + CFIndex err = CFErrorGetCode(error); + if (err == EACCES) { + secerror("Notarization daemon found revoked hash: %@", hash); + is_revoked = true; + } else { + secerror("Error checking with notarization daemon: %ld", err); + } + } +#endif + + return is_revoked; +} + +bool +isNotarized(const Requirement::Context *context) +{ + CFRef cd; + CFRef error; + bool is_notarized = false; + SecCSDigestAlgorithm hashType = kSecCodeSignatureNoHash; + + if (context == NULL) { + is_notarized = false; + goto lb_exit; + } + + if (context->directory) { + cd.take(context->directory->cdhash()); + hashType = (SecCSDigestAlgorithm)context->directory->hashType; + } else if (context->packageChecksum) { + cd = context->packageChecksum; + hashType = context->packageAlgorithm; + } + + if (cd.get() == NULL) { + // No cdhash means we can't check notarization. + is_notarized = false; + goto lb_exit; + } + + secinfo("notarization", "checking notarization on %d, %@", hashType, cd.get()); + +#if TARGET_OS_OSX + if (SecAssessmentTicketLookup(cd, hashType, kSecAssessmentTicketFlagDefault, NULL, &error.aref())) { + is_notarized = true; + } else { + is_notarized = false; + if (error.get() != NULL) { + secerror("Error checking with notarization daemon: %ld", CFErrorGetCode(error)); + } + } +#endif + +lb_exit: + secinfo("notarization", "isNotarized = %d", is_notarized); + return is_notarized; +} + +void +registerStapledTicketInPackage(const std::string& path) +{ + int fd = 0; + package_trailer_t trailer; + off_t readOffset = 0; + size_t bytesRead = 0; + off_t backSeek = 0; + uint8_t *ticketData = NULL; + boolean_t ticketTrailerFound = false; + CFRef data; + + secinfo("notarization", "Extracting ticket from package: %s", path.c_str()); + + fd = open(path.c_str(), O_RDONLY); + if (fd <= 0) { + secerror("cannot open package for reading"); + goto lb_exit; + } + + bzero(&trailer, sizeof(trailer)); + readOffset = lseek(fd, -sizeof(trailer), SEEK_END); + if (readOffset <= 0) { + secerror("could not scan for first trailer on package (error - %d)", errno); + goto lb_exit; + } + + while (!ticketTrailerFound) { + bytesRead = read(fd, &trailer, sizeof(trailer)); + if (bytesRead != sizeof(trailer)) { + secerror("could not read next trailer from package (error - %d)", errno); + goto lb_exit; + } + + if (memcmp(trailer.magic, TrailerMagic, strlen(TrailerMagic)) != 0) { + // Most packages will not be stapled, so this isn't really an error. + secdebug("notarization", "package did not end in a trailer"); + goto lb_exit; + } + + switch (trailer.type) { + case TrailerTypeTicket: + ticketTrailerFound = true; + break; + case TrailerTypeTerminator: + // Found a terminator before a trailer, so just exit. + secinfo("notarization", "package had a trailer, but no ticket trailers"); + goto lb_exit; + case TrailerTypeInvalid: + secinfo("notarization", "package had an invalid trailer"); + goto lb_exit; + default: + // it's an unsupported trailer type, so skip it. + break; + } + + // If we're here, it's either a ticket or an unknown trailer. In both cases we can definitely seek back to the + // beginning of the data pointed to by this trailer, which is the length of its data and the size of the trailer itself. + backSeek = -1 * (sizeof(trailer) + trailer.length); + if (!ticketTrailerFound) { + // If we didn't find a ticket, we're about to iterate again and want to read the next trailer so seek back an additional + // trailer blob to prepare for reading it. + backSeek -= sizeof(trailer); + } + readOffset = lseek(fd, backSeek, SEEK_CUR); + if (readOffset <= 0) { + secerror("could not scan backwards (%lld) for next trailer on package (error - %d)", backSeek, errno); + goto lb_exit; + } + } + + // If we got here, we have a valid ticket trailer and already seeked back to the beginning of its data. + ticketData = (uint8_t*)malloc(trailer.length); + if (ticketData == NULL) { + secerror("could not allocate memory for ticket"); + goto lb_exit; + } + + bytesRead = read(fd, ticketData, trailer.length); + if (bytesRead != trailer.length) { + secerror("unable to read entire ticket (error - %d)", errno); + goto lb_exit; + } + + data = CFDataCreateWithBytesNoCopy(NULL, ticketData, trailer.length, NULL); + if (data.get() == NULL) { + secerror("unable to create cfdata for notarization"); + goto lb_exit; + } + + secinfo("notarization", "successfully found stapled ticket for: %s", path.c_str()); + registerStapledTicketWithSystem(data); + +lb_exit: + if (fd) { + close(fd); + } + if (ticketData) { + free(ticketData); + } +} + +void +registerStapledTicketInBundle(const std::string& path) +{ + int fd = 0; + struct stat st; + uint8_t *ticketData = NULL; + size_t ticketLength = 0; + size_t bytesRead = 0; + CFRef data; + std::string ticketLocation = path + "/Contents/CodeResources"; + + secinfo("notarization", "Extracting ticket from bundle: %s", path.c_str()); + + fd = open(ticketLocation.c_str(), O_RDONLY); + if (fd <= 0) { + // Only print an error if the file exists, otherwise its an expected early exit case. + if (errno != ENOENT) { + secerror("cannot open stapled file for reading: %d", errno); + } + goto lb_exit; + } + + if (fstat(fd, &st)) { + secerror("unable to stat stapling file: %d", errno); + goto lb_exit; + } + + if ((st.st_mode & S_IFREG) != S_IFREG) { + secerror("stapling is not a regular file"); + goto lb_exit; + } + + if (st.st_size <= INT_MAX) { + ticketLength = (size_t)st.st_size; + } else { + secerror("ticket size was too large: %lld", st.st_size); + goto lb_exit; + } + + ticketData = (uint8_t*)malloc(ticketLength); + if (ticketData == NULL) { + secerror("unable to allocate data for ticket"); + goto lb_exit; + } + + bytesRead = read(fd, ticketData, ticketLength); + if (bytesRead != ticketLength) { + secerror("unable to read entire ticket from bundle"); + goto lb_exit; + } + + data = CFDataCreateWithBytesNoCopy(NULL, ticketData, ticketLength, NULL); + if (data.get() == NULL) { + secerror("unable to create cfdata for notarization"); + goto lb_exit; + } + + secinfo("notarization", "successfully found stapled ticket for: %s", path.c_str()); + registerStapledTicketWithSystem(data); + +lb_exit: + if (fd) { + close(fd); + } + if (ticketData) { + free(ticketData); + } +} + +void +registerStapledTicketInDMG(CFDataRef ticketData) +{ + if (ticketData == NULL) { + return; + } + secinfo("notarization", "successfully found stapled ticket in DMG"); + registerStapledTicketWithSystem(ticketData); +} + +} +} diff --git a/OSX/libsecurity_codesigning/lib/notarization.h b/OSX/libsecurity_codesigning/lib/notarization.h new file mode 100644 index 000000000..21ae3c16c --- /dev/null +++ b/OSX/libsecurity_codesigning/lib/notarization.h @@ -0,0 +1,51 @@ +/* + * 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 _H_NOTARIZATION +#define _H_NOTARIZATION + +#include +#include +#include +#include +#include "requirement.h" + +namespace Security { +namespace CodeSigning { + +// Performs an online check for a ticket, and returns true if a revocation ticket is found. +bool checkNotarizationServiceForRevocation(CFDataRef hash, SecCSDigestAlgorithm hashType, double *date); + +// Performs an offline notarization check for the hash represented in the requirement context +// and returns whether the hash has a valid, unrevoked notarization ticket. +bool isNotarized(const Requirement::Context *context); + +// Representation-specific methods for extracting a stapled ticket and registering +// it with the notarization daemon. +void registerStapledTicketInPackage(const std::string& path); +void registerStapledTicketInBundle(const std::string& path); +void registerStapledTicketInDMG(CFDataRef ticketData); + +} // end namespace CodeSigning +} // end namespace Security + +#endif /* _H_NOTARIZATION */ diff --git a/OSX/libsecurity_codesigning/lib/piddiskrep.cpp b/OSX/libsecurity_codesigning/lib/piddiskrep.cpp index 176fcfb5c..0aeeb81e1 100644 --- a/OSX/libsecurity_codesigning/lib/piddiskrep.cpp +++ b/OSX/libsecurity_codesigning/lib/piddiskrep.cpp @@ -39,7 +39,7 @@ PidDiskRep::setCredentials(const Security::CodeSigning::CodeDirectory *cd) { // save the Info.plist slot if (cd->slotIsPresent(cdInfoSlot)) { - mInfoPlistHash.take(makeCFData((*cd)[cdInfoSlot], cd->hashSize)); + mInfoPlistHash.take(makeCFData(cd->getSlot(cdInfoSlot, false), cd->hashSize)); } } @@ -58,8 +58,12 @@ PidDiskRep::fetchData(void) assert(request != NULL); xpc_dictionary_set_string(request, "command", "fetchData"); xpc_dictionary_set_int64(request, "pid", mPid); + + if (mAudit) { + xpc_dictionary_set_data(request, "audit", mAudit.get(), sizeof(audit_token_t)); + } xpc_dictionary_set_data(request, "infohash", CFDataGetBytePtr(mInfoPlistHash), CFDataGetLength(mInfoPlistHash)); - + xpc_object_t reply = xpc_connection_send_message_with_reply_sync(conn, request); if (reply && xpc_get_type(reply) == XPC_TYPE_DICTIONARY) { const void *data; @@ -89,20 +93,30 @@ PidDiskRep::fetchData(void) } -PidDiskRep::PidDiskRep(pid_t pid, CFDataRef infoPlist) +PidDiskRep::PidDiskRep(pid_t pid, audit_token_t *audit, CFDataRef infoPlist) : mDataFetched(false) { BlobCore header; - CODESIGN_DISKREP_CREATE_KERNEL(this); - + mPid = pid; mInfoPlist = infoPlist; - -// fetchData(); - int rcent = ::csops(pid, CS_OPS_BLOB, &header, sizeof(header)); + if (audit != NULL) { + mAudit.reset(new audit_token_t); + memcpy(mAudit.get(), audit, sizeof(audit_token_t)); + } + + // fetchData(); + + int rcent = EINVAL; + + if (audit != NULL) { + rcent = ::csops_audittoken(pid, CS_OPS_BLOB, &header, sizeof(header), mAudit.get()); + } else { + rcent = ::csops(pid, CS_OPS_BLOB, &header, sizeof(header)); + } if (rcent == 0) - MacOSError::throwMe(errSecCSNoSuchCode); + MacOSError::throwMe(errSecCSNoSuchCode); if (errno != ERANGE) UnixError::throwMe(errno); @@ -112,8 +126,12 @@ PidDiskRep::PidDiskRep(pid_t pid, CFDataRef infoPlist) uint32_t bufferLen = (uint32_t)header.length(); mBuffer = new uint8_t [bufferLen]; - - UnixError::check(::csops(pid, CS_OPS_BLOB, mBuffer, bufferLen)); + + if (audit != NULL) { + UnixError::check(::csops_audittoken(pid, CS_OPS_BLOB, mBuffer, bufferLen, mAudit.get())); + } else { + UnixError::check(::csops(pid, CS_OPS_BLOB, mBuffer, bufferLen)); + } const EmbeddedSignatureBlob *b = (const EmbeddedSignatureBlob *)mBuffer; if (!b->validateBlob(bufferLen)) @@ -185,12 +203,31 @@ UnixPlusPlus::FileDesc &PidDiskRep::fd() string PidDiskRep::mainExecutablePath() { char path[MAXPATHLEN * 2]; + // This is unsafe by pid only, but so is using that path in general. if(::proc_pidpath(mPid, path, sizeof(path)) == 0) UnixError::throwMe(errno); return path; } - + +bool PidDiskRep::appleInternalForcePlatform() const +{ + uint32_t flags = 0; + int rcent = EINVAL; + + if (mAudit != NULL) { + rcent = ::csops_audittoken(mPid, CS_OPS_STATUS, &flags, sizeof(flags), + mAudit.get()); + } else { + rcent = ::csops(mPid, CS_OPS_STATUS, &flags, sizeof(flags)); + } + + if (rcent != 0) { + MacOSError::throwMe(errSecCSNoSuchCode); + } + + return (flags & CS_PLATFORM_BINARY) == CS_PLATFORM_BINARY; +} } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_codesigning/lib/piddiskrep.h b/OSX/libsecurity_codesigning/lib/piddiskrep.h index 766a6bda2..c58430099 100644 --- a/OSX/libsecurity_codesigning/lib/piddiskrep.h +++ b/OSX/libsecurity_codesigning/lib/piddiskrep.h @@ -27,20 +27,17 @@ #ifndef _H_PIDDISKREP #define _H_PIDDISKREP +#include + #include "diskrep.h" namespace Security { namespace CodeSigning { -// -// A KernelDiskRep represents a (the) kernel on disk. -// It has no write support, so we can't sign the kernel, -// which is fine since we unconditionally trust it anyway. -// class PidDiskRep : public DiskRep { public: - PidDiskRep(pid_t pid, CFDataRef infoPlist); + PidDiskRep(pid_t pid, audit_token_t *audit, CFDataRef infoPlist); ~PidDiskRep(); CFDataRef component(CodeDirectory::SpecialSlot slot); @@ -58,10 +55,13 @@ class PidDiskRep : public DiskRep { void setCredentials(const CodeDirectory* cd); + bool appleInternalForcePlatform() const; + private: const BlobCore *blob() { return (const BlobCore *)mBuffer; } void fetchData(void); pid_t mPid; + std::unique_ptr mAudit; uint8_t *mBuffer; CFRef mInfoPlistHash; CFRef mInfoPlist; diff --git a/OSX/libsecurity_codesigning/lib/policydb.cpp b/OSX/libsecurity_codesigning/lib/policydb.cpp index 94d1bbc89..92d9cfa2a 100644 --- a/OSX/libsecurity_codesigning/lib/policydb.cpp +++ b/OSX/libsecurity_codesigning/lib/policydb.cpp @@ -219,12 +219,12 @@ void PolicyDatabase::addFeature(const char *name, const char *value, const char void PolicyDatabase::simpleFeature(const char *feature, void (^perform)()) { + SQLite::Transaction update(*this); if (!hasFeature(feature)) { - SQLite::Transaction update(*this); perform(); addFeature(feature, "upgraded", "upgraded"); - update.commit(); } + update.commit(); } void PolicyDatabase::simpleFeature(const char *feature, const char *sql) @@ -234,6 +234,14 @@ void PolicyDatabase::simpleFeature(const char *feature, const char *sql) perform.execute(); }); } + +void PolicyDatabase::simpleFeatureNoTransaction(const char *feature, void (^perform)()) +{ + if (!hasFeature(feature)) { + perform(); + addFeature(feature, "upgraded", "upgraded"); + } +} void PolicyDatabase::upgradeDatabase() @@ -286,6 +294,142 @@ void PolicyDatabase::upgradeDatabase() simpleFeature("root_only", ^{ UnixError::check(::chmod(dbPath(), S_IRUSR | S_IWUSR)); }); + + simpleFeature("notarized_apps", ^{ + + // Insert a set of notarization requirements for notarized applications and installers, with a priority that will be higher than developer id priorities + // so they are guaranteed to match first. + SQLite::Statement addNotarizedExecutables(*this, + "INSERT INTO authority (type, allow, flags, priority, label, requirement) VALUES (1, 1, 2, 5.0, 'Notarized Developer ID', 'anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists and notarized')"); + addNotarizedExecutables.execute(); + + SQLite::Statement addNotarizedInstallers(*this, + "INSERT INTO authority (type, allow, flags, priority, label, requirement) VALUES (2, 1, 2, 5.0, 'Notarized Developer ID', 'anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and (certificate leaf[field.1.2.840.113635.100.6.1.14] or certificate leaf[field.1.2.840.113635.100.6.1.13]) and notarized')"); + addNotarizedInstallers.execute(); + + // Bump the priority on apple system, apple installer, and mac app store entries so they are evaluated before Developer ID variants. + // This is important because notarized variants meet the requirement of the Developer ID variant and would could match that too. + SQLite::Statement bumpAppleSystemPriority(*this, + "UPDATE authority SET priority = 20.0 WHERE label = 'Apple System'"); + bumpAppleSystemPriority.execute(); + + SQLite::Statement bumpAppleInstallerPriority(*this, + "UPDATE authority SET priority = 20.0 WHERE label = 'Apple Installer'"); + bumpAppleInstallerPriority.execute(); + + SQLite::Statement bumpMacAppStorePriority(*this, + "UPDATE authority SET priority = 10.0 WHERE label = 'Mac App Store'"); + bumpMacAppStorePriority.execute(); + }); + + { + SQLite::Transaction devIdRequirementUpgrades(*this); + + simpleFeatureNoTransaction("legacy_devid", ^{ + auto migrateReq = [](auto db, int type, string req) { + const string legacy = + " and (certificate leaf[timestamp.1.2.840.113635.100.6.1.33] absent or " + "certificate leaf[timestamp.1.2.840.113635.100.6.1.33] < timestamp \"20190408000000Z\")"; + + const string unnotarized = + " and (certificate leaf[timestamp.1.2.840.113635.100.6.1.33] exists and " + "certificate leaf[timestamp.1.2.840.113635.100.6.1.33] >= timestamp \"20190408000000Z\")"; + + SQLite::Statement update(*db, "UPDATE OR IGNORE authority " + "SET requirement = :newreq " + "WHERE requirement = :oldreq " + " AND type = :type " + " AND label = 'Developer ID'"); + update.bind(":oldreq") = req; + update.bind(":type") = type; + update.bind(":newreq") = req + legacy; + update.execute(); + + SQLite::Statement insert(*db, "INSERT OR IGNORE INTO authority " + "(type, requirement, allow, priority, label) " + "VALUES " + "(:type, :req, 0, 4.0, " + "'Unnotarized Developer ID')"); + insert.bind(":type") = type; + insert.bind(":req") = req + unnotarized; + insert.execute(); + }; + + migrateReq(this, 1, "anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists"); + migrateReq(this, 2, "anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and (certificate leaf[field.1.2.840.113635.100.6.1.14] or certificate leaf[field.1.2.840.113635.100.6.1.13])"); + migrateReq(this, 3, "anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists"); + }); + + simpleFeatureNoTransaction("legacy_devid_v2", ^{ + auto migrateReq = [](auto db, int type, string oldreq, string newreq) { + const string legacy = + " and legacy"; + + SQLite::Statement update(*db, "UPDATE OR IGNORE authority " + "SET requirement = :newreq " + "WHERE requirement = :oldreq " + " AND type = :type " + " AND label = 'Developer ID'"); + update.bind(":oldreq") = oldreq; + update.bind(":type") = type; + update.bind(":newreq") = newreq; + update.execute(); + }; + + // App handling has moved to the sunfish path. The legacy keyword won't work well for apps because we don't collect nested code hashes to whitelist them. + migrateReq(this, 2, + "anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and (certificate leaf[field.1.2.840.113635.100.6.1.14] or certificate leaf[field.1.2.840.113635.100.6.1.13]) and (certificate leaf[timestamp.1.2.840.113635.100.6.1.33] absent or certificate leaf[timestamp.1.2.840.113635.100.6.1.33] < timestamp \"20190408000000Z\")", + "anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and (certificate leaf[field.1.2.840.113635.100.6.1.14] or certificate leaf[field.1.2.840.113635.100.6.1.13]) and legacy"); + migrateReq(this, 3, + "anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists and (certificate leaf[timestamp.1.2.840.113635.100.6.1.33] absent or certificate leaf[timestamp.1.2.840.113635.100.6.1.33] < timestamp \"20190408000000Z\")", + "anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists and legacy"); + }); + + simpleFeatureNoTransaction("unnotarized_without_timestamp", ^{ + auto migrateReq = [](auto db, int type, string req) { + const string to_remove = + " and (certificate leaf[timestamp.1.2.840.113635.100.6.1.33] exists and " + "certificate leaf[timestamp.1.2.840.113635.100.6.1.33] >= timestamp \"20190408000000Z\")"; + + SQLite::Statement update(*db, "UPDATE OR IGNORE authority " + "SET requirement = :newreq " + "WHERE requirement = :oldreq " + " AND type = :type " + " AND label = 'Unnotarized Developer ID'"); + update.bind(":oldreq") = req + to_remove; + update.bind(":type") = type; + update.bind(":newreq") = req; + update.execute(); + }; + + migrateReq(this, kAuthorityInstall, "anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and (certificate leaf[field.1.2.840.113635.100.6.1.14] or certificate leaf[field.1.2.840.113635.100.6.1.13])"); + migrateReq(this, kAuthorityOpenDoc, "anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists"); + }); + + devIdRequirementUpgrades.commit(); + } + + simpleFeature("notarized_documents", ^{ + SQLite::Statement addNotarizedDocs(*this, + "INSERT INTO authority (type, allow, flags, priority, label, requirement) " + " VALUES (3, 1, 2, 5.0, 'Notarized Developer ID', " + " 'anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists and notarized')"); + addNotarizedDocs.execute(); + }); + + simpleFeature("notarization_priority_fix", ^{ + auto migrateReq = [](auto db, string label, float priority) { + SQLite::Statement update(*db, + "UPDATE OR IGNORE authority " + "SET priority = :newpriority " + "WHERE label = :label"); + update.bind(":newpriority") = priority; + update.bind(":label") = label; + update.execute(); + }; + migrateReq(this, "Developer ID", 4.0); + migrateReq(this, "Unnotarized Developer ID", 0.0); + }); } @@ -343,14 +487,14 @@ void PolicyDatabase::installExplicitSet(const char *authfile, const char *sigfil // load new data CFIndex count = CFDictionaryGetCount(content); - CFStringRef keys[count]; - CFDictionaryRef values[count]; - CFDictionaryGetKeysAndValues(content, (const void **)keys, (const void **)values); + vector keys_vector(count, NULL); + vector values_vector(count, NULL); + CFDictionaryGetKeysAndValues(content, (const void **)keys_vector.data(), (const void **)values_vector.data()); SQLite::Statement insert(*this, "INSERT INTO authority (type, allow, requirement, label, filter_unsigned, flags, remarks)" " VALUES (:type, 1, :requirement, 'GKE', :filter, :flags, :path)"); for (CFIndex n = 0; n < count; n++) { - CFDictionary info(values[n], errSecCSDbCorrupt); + CFDictionary info(values_vector[n], errSecCSDbCorrupt); uint32_t flags = kAuthorityFlagWhitelist; if (CFNumberRef versionRef = info.get("version")) { int version = cfNumber(versionRef); @@ -461,7 +605,7 @@ void setAssessment(bool masterSwitch) { MutableDictionary *prefsDict = MutableDictionary::CreateMutableDictionary(prefsFile); if (prefsDict == NULL) - prefsDict = new MutableDictionary::MutableDictionary(); + prefsDict = new MutableDictionary(); prefsDict->setValue(SP_ENABLE_KEY, masterSwitch ? SP_ENABLED : SP_DISABLED); prefsDict->writePlistToFile(prefsFile); delete prefsDict; diff --git a/OSX/libsecurity_codesigning/lib/policydb.h b/OSX/libsecurity_codesigning/lib/policydb.h index a4c589201..f9d259be6 100644 --- a/OSX/libsecurity_codesigning/lib/policydb.h +++ b/OSX/libsecurity_codesigning/lib/policydb.h @@ -122,6 +122,7 @@ class PolicyDatabase : public SQLite::Database { void addFeature(const char *feature, const char *value, const char *remarks); void simpleFeature(const char *feature, const char *sql); void simpleFeature(const char *feature, void (^perform)()); + void simpleFeatureNoTransaction(const char *feature, void (^perform)()); void installExplicitSet(const char *auth, const char *sigs); diff --git a/OSX/libsecurity_codesigning/lib/policyengine.cpp b/OSX/libsecurity_codesigning/lib/policyengine.cpp index 1335f6876..a29937164 100644 --- a/OSX/libsecurity_codesigning/lib/policyengine.cpp +++ b/OSX/libsecurity_codesigning/lib/policyengine.cpp @@ -38,17 +38,13 @@ #include "diskrep.h" #include "codedirectory.h" #include "csutilities.h" +#include "notarization.h" #include "StaticCode.h" #include #include "SecCodePriv.h" #undef check // Macro! Yech. -extern "C" { -#include -} - - namespace Security { namespace CodeSigning { @@ -63,7 +59,6 @@ enum { static void authorizeUpdate(SecAssessmentFlags flags, CFDictionaryRef context); -static bool codeInvalidityExceptions(SecStaticCodeRef code, CFMutableDictionaryRef result); static CFTypeRef installerPolicy() CF_RETURNS_RETAINED; @@ -73,10 +68,18 @@ static CFTypeRef installerPolicy() CF_RETURNS_RETAINED; PolicyEngine::PolicyEngine() : PolicyDatabase(NULL, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE) { + try { + mOpaqueWhitelist = new OpaqueWhitelist(); + } catch (...) { + mOpaqueWhitelist = NULL; + secerror("Failed opening the gkopaque database."); + } } PolicyEngine::~PolicyEngine() -{ } +{ + delete mOpaqueWhitelist; +} // @@ -174,8 +177,8 @@ void PolicyEngine::evaluateCodeItem(SecStaticCodeRef code, CFURLRef path, Author SQLite3::int64 disabled = query[6]; // const char *filter = query[7]; // const char *remarks = query[8]; - - secdebug("gk", "considering rule %d(%s) requirement %s", int(id), label ? label : "UNLABELED", reqString); + + secdebug("gk", "considering rule %d(%s) requirement %s", int(id), label ? label : "UNLABELED", reqString); CFRef requirement; MacOSError::check(SecRequirementCreateWithString(CFTempString(reqString), kSecCSDefaultFlags, &requirement.aref())); switch (OSStatus rc = SecStaticCodeCheckValidity(code, kSecCSBasicValidateOnly | kSecCSCheckGatekeeperArchitectures, requirement)) { @@ -189,13 +192,17 @@ void PolicyEngine::evaluateCodeItem(SecStaticCodeRef code, CFURLRef path, Author MacOSError::throwMe(rc); // general error; pass to caller } - // if this rule is disabled, skip it but record the first matching one for posterity - if (disabled && latentID == 0) { - latentID = id; - latentLabel = label ? label : ""; + // If this rule is disabled, do not continue any further and just continue iterating + // until we find one that is enabled. + if (disabled) { + // ...but always record the first matching rule for informational purposes. + if (latentID == 0) { + latentID = id; + latentLabel = label ? label : ""; + } continue; } - + // current rule is first rule (in priority order) that matched. Apply it secnotice("gk", "rule %d applies - allow=%d", int(id), allow); if (nested && allow) // success, nothing to record @@ -262,11 +269,27 @@ void PolicyEngine::evaluateCodeItem(SecStaticCodeRef code, CFURLRef path, Author cfadd(result, "{%O=%B}", kSecAssessmentAssessmentVerdict, false); addAuthority(flags, result, latentLabel.c_str(), latentID); } - + +CFDictionaryRef PolicyEngine::opaqueWhitelistValidationConditionsFor(SecStaticCodeRef code) +{ + return (mOpaqueWhitelist != NULL) ? mOpaqueWhitelist->validationConditionsFor(code) : NULL; +} + +bool PolicyEngine::opaqueWhiteListContains(SecStaticCodeRef code, SecAssessmentFeedback feedback, OSStatus reason) +{ + return (mOpaqueWhitelist != NULL) ? mOpaqueWhitelist->contains(code, feedback, reason) : false; +} + +void PolicyEngine::opaqueWhitelistAdd(SecStaticCodeRef code) +{ + if (mOpaqueWhitelist) { + mOpaqueWhitelist->add(code); + } +} void PolicyEngine::adjustValidation(SecStaticCodeRef code) { - CFRef conditions = mOpaqueWhitelist.validationConditionsFor(code); + CFRef conditions = opaqueWhitelistValidationConditionsFor(code); SecStaticCodeSetValidationConditions(code, conditions); } @@ -364,7 +387,7 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment } CFCopyRef code; - MacOSError::check(SecStaticCodeCreateWithPath(path, kSecCSDefaultFlags, &code.aref())); + MacOSError::check(SecStaticCodeCreateWithPath(path, kSecCSDefaultFlags | kSecCSForceOnlineNotarizationCheck, &code.aref())); SecCSFlags validationFlags = kSecCSEnforceRevocationChecks | kSecCSCheckAllArchitectures; if (!(flags & kSecAssessmentFlagAllowWeak)) @@ -374,15 +397,7 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment // deal with a very special case (broken 10.6/10.7 Applet bundles) OSStatus rc = SecStaticCodeCheckValidity(code, validationFlags | kSecCSBasicValidateOnly, NULL); if (rc == errSecCSSignatureFailed) { - if (!codeInvalidityExceptions(code, result)) { // invalidly signed, no exceptions -> error - if (SYSPOLICY_ASSESS_OUTCOME_BROKEN_ENABLED()) - SYSPOLICY_ASSESS_OUTCOME_BROKEN(cfString(path).c_str(), type, false); - MacOSError::throwMe(rc); - } - // recognized exception - treat as unsigned - if (SYSPOLICY_ASSESS_OUTCOME_BROKEN_ENABLED()) - SYSPOLICY_ASSESS_OUTCOME_BROKEN(cfString(path).c_str(), type, true); - rc = errSecCSUnsigned; + MacOSError::throwMe(rc); } // ad-hoc sign unsigned code @@ -425,7 +440,7 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment } return NULL; })); - + // go for it! SecCSFlags topFlags = validationFlags | kSecCSCheckNestedCode | kSecCSRestrictSymlinks | kSecCSReportProgress; if (type == kAuthorityExecute && !appOk) @@ -465,8 +480,9 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment if (CFEqual(verdict, kCFBooleanFalse)) // nested code rejected by rule book; result was filled out there return; if (CFEqual(verdict, kCFBooleanTrue) && !(flags & kSecAssessmentFlagIgnoreWhitelist)) - if (mOpaqueWhitelist.contains(code, feedback, rc)) + if (opaqueWhiteListContains(code, feedback, rc)) { allow = true; + } } if (allow) { label = "allowed cdhash"; @@ -481,6 +497,18 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment default: MacOSError::throwMe(rc); } + + // Copy notarization date, if present, from code signing information + CFRef info; + OSStatus status = SecCodeCopySigningInformation(code, kSecCSInternalInformation, &info.aref()); + if (status == 0 && info) { + CFDateRef date = (CFDateRef)CFDictionaryGetValue(info, kSecCodeInfoNotarizationDate); + if (date) { + cfadd(result, "{%O=%O}", kSecAssessmentAssessmentNotarizationDate, date); + } + } else { + secerror("Unable to copy signing information: %d", (int)status); + } if (nestedFailure && CFEqual(CFDictionaryGetValue(result, kSecAssessmentAssessmentVerdict), kCFBooleanTrue)) { // structure intact, top level approved, nested code failed policy @@ -543,6 +571,9 @@ void PolicyEngine::evaluateInstall(CFURLRef path, SecAssessmentFlags flags, CFDi if (CFRef certs = xar.copyCertChain()) { CFRef policy = installerPolicy(); CFRef trust; + CFRef checksum; + CFRef teamID; + CFRef requirementContext = makeCFMutableDictionary(); MacOSError::check(SecTrustCreateWithCertificates(certs, policy, &trust.aref())); // MacOSError::check(SecTrustSetAnchorCertificates(trust, cfEmptyArray())); // no anchors MacOSError::check(SecTrustSetOptions(trust, kSecTrustOptionAllowExpired | kSecTrustOptionImplicitAnchors)); @@ -568,6 +599,42 @@ void PolicyEngine::evaluateInstall(CFURLRef path, SecAssessmentFlags flags, CFDi } } + xar.registerStapledNotarization(); + checksum.take(xar.createPackageChecksum()); + if (checksum) { + double notarizationDate = NAN; + + // Force a single online check for the checksum, which is always SHA1. + bool is_revoked = checkNotarizationServiceForRevocation(checksum, kSecCodeSignatureHashSHA1, ¬arizationDate); + if (is_revoked) { + MacOSError::throwMe(errSecCSRevokedNotarization); + } + + // Extract a team identifier from the certificates. This isn't validated and could be spoofed, + // but since the 'legacy' keyword is only used in addition to the Developer ID requirement, + // this is still stafe for now. + SecCertificateRef leaf = SecCertificateRef(CFArrayGetValueAtIndex(certs, 0)); + CFRef orgUnits = SecCertificateCopyOrganizationalUnit(leaf); + if (orgUnits.get() && CFArrayGetCount(orgUnits) == 1) { + teamID = (CFStringRef)CFArrayGetValueAtIndex(orgUnits, 0); + } + + // Create the appropriate requirement context entry to allow notarized requirement check. + CFRef algorithm = makeCFNumber((uint32_t)xar.checksumDigestAlgorithm()); + cfadd(requirementContext, "{%O=%O}", kSecRequirementKeyPackageChecksum, checksum.get()); + cfadd(requirementContext, "{%O=%O}", kSecRequirementKeyChecksumAlgorithm, algorithm.get()); + if (teamID.get()) { + cfadd(requirementContext, "{%O=%O}", kSecRequirementKeyTeamIdentifier, teamID.get()); + } + + if (!isnan(notarizationDate)) { + CFRef date = CFDateCreate(NULL, notarizationDate); + if (date) { + cfadd(result, "{%O=%O}", kSecAssessmentAssessmentNotarizationDate, date.get()); + } + } + } + SQLite::Statement query(*this, "SELECT allow, requirement, id, label, flags, disabled FROM scan_authority" " WHERE type = :type" @@ -580,10 +647,10 @@ void PolicyEngine::evaluateInstall(CFURLRef path, SecAssessmentFlags flags, CFDi const char *label = query[3]; //sqlite_uint64 ruleFlags = query[4]; SQLite3::int64 disabled = query[5]; - + CFRef requirement; MacOSError::check(SecRequirementCreateWithString(CFTempString(reqString), kSecCSDefaultFlags, &requirement.aref())); - switch (OSStatus rc = SecRequirementEvaluate(requirement, chain, NULL, kSecCSDefaultFlags)) { + switch (OSStatus rc = SecRequirementEvaluate(requirement, chain, requirementContext.get(), kSecCSDefaultFlags)) { case errSecSuccess: // success break; case errSecCSReqFailed: // requirement missed, but otherwise okay @@ -1119,17 +1186,6 @@ void PolicyEngine::normalizeTarget(CFRef &target, AuthorityType type, } MacOSError::check(rc); case errSecCSSignatureFailed: - // recover certain cases of broken signatures (well, try) - if (codeInvalidityExceptions(code, NULL)) { - // Ad-hoc sign the code in place (requiring a writable subject). This requires root privileges. - CFRef signer; - CFTemp arguments("{%O=#N}", kSecCodeSignerIdentity); - MacOSError::check(SecCodeSignerCreate(arguments, kSecCSSignOpaque, &signer.aref())); - MacOSError::check(SecCodeSignerAddSignature(signer, code, kSecCSDefaultFlags)); - MacOSError::check(SecCodeCopyDesignatedRequirement(code, kSecCSDefaultFlags, (SecRequirementRef *)&target.aref())); - break; - } - MacOSError::check(rc); default: MacOSError::check(rc); } @@ -1144,33 +1200,10 @@ void PolicyEngine::normalizeTarget(CFRef &target, AuthorityType type, CFStringRef edit = CFStringRef(context.get(kSecAssessmentContextKeyUpdate)); if (type == kAuthorityExecute && CFEqual(edit, kSecAssessmentUpdateOperationAdd)) { // implicitly whitelist the code - mOpaqueWhitelist.add(code); + opaqueWhitelistAdd(code); } } } - -// -// Process special overrides for invalidly signed code. -// This is the (hopefully minimal) concessions we make to keep hurting our customers -// for our own prior mistakes... -// -static bool codeInvalidityExceptions(SecStaticCodeRef code, CFMutableDictionaryRef result) -{ - CFRef info; - MacOSError::check(SecCodeCopySigningInformation(code, kSecCSDefaultFlags, &info.aref())); - if (CFURLRef executable = CFURLRef(CFDictionaryGetValue(info, kSecCodeInfoMainExecutable))) { - SInt32 error; - if (OSAIsRecognizedExecutableURL(executable, &error)) { - if (result) - CFDictionaryAddValue(result, - kSecAssessmentAssessmentAuthorityOverride, CFSTR("ignoring known invalid applet signature")); - return true; - } - } - return false; -} - - } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_codesigning/lib/policyengine.h b/OSX/libsecurity_codesigning/lib/policyengine.h index 9ba82dc2e..87b10df77 100644 --- a/OSX/libsecurity_codesigning/lib/policyengine.h +++ b/OSX/libsecurity_codesigning/lib/policyengine.h @@ -88,7 +88,10 @@ class PolicyEngine : public PolicyDatabase { void recordOutcome(SecStaticCodeRef code, bool allow, AuthorityType type, double expires, SQLite::int64 authority); private: - OpaqueWhitelist mOpaqueWhitelist; + OpaqueWhitelist* mOpaqueWhitelist; + CFDictionaryRef opaqueWhitelistValidationConditionsFor(SecStaticCodeRef code); + bool opaqueWhiteListContains(SecStaticCodeRef code, SecAssessmentFeedback feedback, OSStatus reason); + void opaqueWhitelistAdd(SecStaticCodeRef code); friend class EvaluationManager; friend class EvaluationTask; diff --git a/OSX/libsecurity_codesigning/lib/reqdumper.cpp b/OSX/libsecurity_codesigning/lib/reqdumper.cpp index c971f0ffd..f0fc8dd57 100644 --- a/OSX/libsecurity_codesigning/lib/reqdumper.cpp +++ b/OSX/libsecurity_codesigning/lib/reqdumper.cpp @@ -199,6 +199,15 @@ void Dumper::expr(SyntaxLevel level) case opCertField: print("certificate"); certSlot(); print("["); dotString(); print("]"); match(); break; + case opCertFieldDate: + print("certificate"); certSlot(); print("["); +#if TARGET_OS_OSX + { + const unsigned char *data; size_t length; + getData(data, length); + print("timestamp.%s", CssmOid((unsigned char *)data, length).toOid().c_str()); + } +#endif case opCertGeneric: print("certificate"); certSlot(); print("["); #if TARGET_OS_OSX @@ -236,6 +245,12 @@ void Dumper::expr(SyntaxLevel level) case opPlatform: print("platform = %d", get()); break; + case opNotarized: + print("notarized"); + break; + case opLegacyDevID: + print("legacy"); + break; default: if (op & opGenericFalse) { print(" false /* opcode %d */", op & ~opFlagMask); @@ -271,6 +286,9 @@ void Dumper::match() case matchExists: print(" /* exists */"); break; + case matchAbsent: + print(" absent "); + break; case matchEqual: print(" = "); data(); break; @@ -295,6 +313,21 @@ void Dumper::match() case matchGreaterThan: print(" > "); data(); break; + case matchOn: + print(" = "); timestamp(); + break; + case matchBefore: + print(" < "); timestamp(); + break; + case matchAfter: + print(" > "); timestamp(); + break; + case matchOnOrBefore: + print(" <= "); timestamp(); + break; + case matchOnOrAfter: + print(" >= "); timestamp(); + break; default: print("MATCH OPCODE %d NOT UNDERSTOOD", op); break; @@ -359,6 +392,16 @@ void Dumper::data(PrintMode bestMode /* = isSimple */, bool dotOkay /* = false * break; } } + +void Dumper::timestamp() +{ + CFAbsoluteTime at = static_cast(get()); + CFRef date = CFDateCreate(NULL, at); + + CFRef str = CFCopyDescription(date); + + print("<%s>", cfString(str).c_str()); +} void Dumper::printBytes(const Byte *data, size_t length) { diff --git a/OSX/libsecurity_codesigning/lib/reqdumper.h b/OSX/libsecurity_codesigning/lib/reqdumper.h index 30793fdc0..b2f6b4d16 100644 --- a/OSX/libsecurity_codesigning/lib/reqdumper.h +++ b/OSX/libsecurity_codesigning/lib/reqdumper.h @@ -77,6 +77,7 @@ class Dumper : public Requirement::Reader { isBinary // contains binary bytes (use 0xnnn form) }; void data(PrintMode bestMode = isSimple, bool dotOkay = false); + void timestamp(); void dotString() { data(isSimple, true); } void quotedString() { data(isPrintable); } void hashData(); // H"bytes" diff --git a/OSX/libsecurity_codesigning/lib/reqinterp.cpp b/OSX/libsecurity_codesigning/lib/reqinterp.cpp index b685802b5..4ff172124 100644 --- a/OSX/libsecurity_codesigning/lib/reqinterp.cpp +++ b/OSX/libsecurity_codesigning/lib/reqinterp.cpp @@ -24,6 +24,7 @@ // // reqinterp - Requirement language (exprOp) interpreter // + #include "reqinterp.h" #include "codesigning_dtrace.h" #include @@ -34,6 +35,8 @@ #include #include #include "csutilities.h" +#include "notarization.h" +#include "legacydevid.h" namespace Security { namespace CodeSigning { @@ -157,6 +160,13 @@ bool Requirement::Interpreter::eval(int depth) Match match(*this); return certFieldGeneric(key, match, cert); } + case opCertFieldDate: + { + SecCertificateRef cert = mContext->cert(get()); + string key = getString(); + Match match(*this); + return certFieldDate(key, match, cert); + } case opCertPolicy: { SecCertificateRef cert = mContext->cert(get()); @@ -178,6 +188,14 @@ bool Requirement::Interpreter::eval(int depth) int32_t targetPlatform = get(); return mContext->directory && mContext->directory->platform == targetPlatform; } + case opNotarized: + { + return isNotarized(mContext); + } + case opLegacyDevID: + { + return meetsDeveloperIDLegacyAllowedPolicy(mContext); + } default: // opcode not recognized - handle generically if possible, fail otherwise if (op & (opGenericFalse | opGenericSkip)) { @@ -206,7 +224,7 @@ bool Requirement::Interpreter::infoKeyValue(const string &key, const Match &matc if (mContext->info) // we have an Info.plist if (CFTypeRef value = CFDictionaryGetValue(mContext->info, CFTempString(key))) return match(value); - return false; + return match(kCFNull); } @@ -218,7 +236,7 @@ bool Requirement::Interpreter::entitlementValue(const string &key, const Match & if (mContext->entitlements) // we have an Info.plist if (CFTypeRef value = CFDictionaryGetValue(mContext->entitlements, CFTempString(key))) return match(value); - return false; + return match(kCFNull); } @@ -291,7 +309,26 @@ bool Requirement::Interpreter::certFieldGeneric(const string &key, const Match & bool Requirement::Interpreter::certFieldGeneric(const CssmOid &oid, const Match &match, SecCertificateRef cert) { - return cert && certificateHasField(cert, oid) && match(kCFBooleanTrue); + return cert && match(certificateHasField(cert, oid) ? (CFTypeRef)kCFBooleanTrue : (CFTypeRef)kCFNull); +} + +bool Requirement::Interpreter::certFieldDate(const string &key, const Match &match, SecCertificateRef cert) +{ + // the key is actually a (binary) OID value + CssmOid oid((char *)key.data(), key.length()); + return certFieldDate(oid, match, cert); +} + +bool Requirement::Interpreter::certFieldDate(const CssmOid &oid, const Match &match, SecCertificateRef cert) +{ + CFTypeRef value = cert != NULL ? certificateCopyFieldDate(cert, oid) : NULL; + bool matching = match(value != NULL ? value : kCFNull); + + if (value) { + CFRelease(value); + } + + return matching; } bool Requirement::Interpreter::certFieldPolicy(const string &key, const Match &match, SecCertificateRef cert) @@ -303,7 +340,7 @@ bool Requirement::Interpreter::certFieldPolicy(const string &key, const Match &m bool Requirement::Interpreter::certFieldPolicy(const CssmOid &oid, const Match &match, SecCertificateRef cert) { - return cert && certificateHasPolicy(cert, oid) && match(kCFBooleanTrue); + return cert && match(certificateHasPolicy(cert, oid) ? (CFTypeRef)kCFBooleanTrue : (CFTypeRef)kCFNull); } #endif @@ -371,6 +408,10 @@ bool Requirement::Interpreter::appleLocalAnchored() if (csr_check(CSR_ALLOW_APPLE_INTERNAL)) return false; + if (mContext->forcePlatform) { + return true; + } + static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ additionalTrustedCertificates = getAdditionalTrustedAnchors(); @@ -399,7 +440,7 @@ bool Requirement::Interpreter::appleSigned() return true; } else if (appleLocalAnchored()) { return true; - } + } return false; } @@ -529,6 +570,7 @@ SecTrustSettingsResult Requirement::Interpreter::trustSetting(SecCertificateRef Requirement::Interpreter::Match::Match(Interpreter &interp) { switch (mOp = interp.get()) { + case matchAbsent: case matchExists: break; case matchEqual: @@ -541,6 +583,14 @@ Requirement::Interpreter::Match::Match(Interpreter &interp) case matchGreaterEqual: mValue.take(makeCFString(interp.getString())); break; + case matchOn: + case matchBefore: + case matchAfter: + case matchOnOrBefore: + case matchOnOrAfter: { + mValue.take(CFDateCreate(NULL, interp.getAbsoluteTime())); + break; + } default: // Assume this (unknown) match type has a single data argument. // This gives us a chance to keep the instruction stream aligned. @@ -559,6 +609,10 @@ bool Requirement::Interpreter::Match::operator () (CFTypeRef candidate) const if (!candidate) return false; + if (candidate == kCFNull) { + return mOp == matchAbsent; // only 'absent' matches + } + // interpret an array as matching alternatives (any one succeeds) if (CFGetTypeID(candidate) == CFArrayGetTypeID()) { CFArrayRef array = CFArrayRef(candidate); @@ -569,31 +623,33 @@ bool Requirement::Interpreter::Match::operator () (CFTypeRef candidate) const } switch (mOp) { + case matchAbsent: + return false; // it exists, so it cannot be absent case matchExists: // anything but NULL and boolean false "exists" return !CFEqual(candidate, kCFBooleanFalse); case matchEqual: // equality works for all CF types return CFEqual(candidate, mValue); case matchContains: - if (CFGetTypeID(candidate) == CFStringGetTypeID()) { + if (isStringValue() && CFGetTypeID(candidate) == CFStringGetTypeID()) { CFStringRef value = CFStringRef(candidate); - if (CFStringFindWithOptions(value, mValue, CFRangeMake(0, CFStringGetLength(value)), 0, NULL)) + if (CFStringFindWithOptions(value, cfStringValue(), CFRangeMake(0, CFStringGetLength(value)), 0, NULL)) return true; } return false; case matchBeginsWith: - if (CFGetTypeID(candidate) == CFStringGetTypeID()) { + if (isStringValue() && CFGetTypeID(candidate) == CFStringGetTypeID()) { CFStringRef value = CFStringRef(candidate); - if (CFStringFindWithOptions(value, mValue, CFRangeMake(0, CFStringGetLength(mValue)), 0, NULL)) + if (CFStringFindWithOptions(value, cfStringValue(), CFRangeMake(0, CFStringGetLength(cfStringValue())), 0, NULL)) return true; } return false; case matchEndsWith: - if (CFGetTypeID(candidate) == CFStringGetTypeID()) { + if (isStringValue() && CFGetTypeID(candidate) == CFStringGetTypeID()) { CFStringRef value = CFStringRef(candidate); - CFIndex matchLength = CFStringGetLength(mValue); + CFIndex matchLength = CFStringGetLength(cfStringValue()); CFIndex start = CFStringGetLength(value) - matchLength; if (start >= 0) - if (CFStringFindWithOptions(value, mValue, CFRangeMake(start, matchLength), 0, NULL)) + if (CFStringFindWithOptions(value, cfStringValue(), CFRangeMake(start, matchLength), 0, NULL)) return true; } return false; @@ -605,6 +661,26 @@ bool Requirement::Interpreter::Match::operator () (CFTypeRef candidate) const return inequality(candidate, kCFCompareNumerically, kCFCompareGreaterThan, false); case matchGreaterEqual: return inequality(candidate, kCFCompareNumerically, kCFCompareLessThan, false); + case matchOn: + case matchBefore: + case matchAfter: + case matchOnOrBefore: + case matchOnOrAfter: { + if (!isDateValue() || CFGetTypeID(candidate) != CFDateGetTypeID()) { + return false; + } + + CFComparisonResult res = CFDateCompare((CFDateRef)candidate, cfDateValue(), NULL); + + switch (mOp) { + case matchOn: return res == 0; + case matchBefore: return res < 0; + case matchAfter: return res > 0; + case matchOnOrBefore: return res <= 0; + case matchOnOrAfter: return res >= 0; + default: abort(); + } + } default: // unrecognized match types can never match return false; @@ -615,9 +691,9 @@ bool Requirement::Interpreter::Match::operator () (CFTypeRef candidate) const bool Requirement::Interpreter::Match::inequality(CFTypeRef candidate, CFStringCompareFlags flags, CFComparisonResult outcome, bool negate) const { - if (CFGetTypeID(candidate) == CFStringGetTypeID()) { + if (isStringValue() && CFGetTypeID(candidate) == CFStringGetTypeID()) { CFStringRef value = CFStringRef(candidate); - if ((CFStringCompare(value, mValue, flags) == outcome) == negate) + if ((CFStringCompare(value, cfStringValue(), flags) == outcome) == negate) return true; } return false; diff --git a/OSX/libsecurity_codesigning/lib/reqinterp.h b/OSX/libsecurity_codesigning/lib/reqinterp.h index 452704091..83b2fb02b 100644 --- a/OSX/libsecurity_codesigning/lib/reqinterp.h +++ b/OSX/libsecurity_codesigning/lib/reqinterp.h @@ -62,8 +62,13 @@ class Requirement::Interpreter : public Requirement::Reader { bool inequality(CFTypeRef candidate, CFStringCompareFlags flags, CFComparisonResult outcome, bool negate) const; private: - CFCopyRef mValue; // match value + CFCopyRef mValue; // match value MatchOperation mOp; // type of match + + bool isStringValue() const { return CFGetTypeID(mValue) == CFStringGetTypeID(); } + bool isDateValue() const { return CFGetTypeID(mValue) == CFDateGetTypeID(); } + CFStringRef cfStringValue() const { return isStringValue() ? (CFStringRef)mValue.get() : NULL; } + CFDateRef cfDateValue() const { return isDateValue() ? (CFDateRef)mValue.get() : NULL; } }; protected: @@ -77,6 +82,8 @@ class Requirement::Interpreter : public Requirement::Reader { bool certFieldGeneric(const CssmOid &oid, const Match &match, SecCertificateRef cert); bool certFieldPolicy(const string &key, const Match &match, SecCertificateRef cert); bool certFieldPolicy(const CssmOid &oid, const Match &match, SecCertificateRef cert); + bool certFieldDate(const string &key, const Match &match, SecCertificateRef cert); + bool certFieldDate(const CssmOid &oid, const Match &match, SecCertificateRef cert); #endif bool verifyAnchor(SecCertificateRef cert, const unsigned char *digest); bool appleSigned(); diff --git a/OSX/libsecurity_codesigning/lib/reqmaker.h b/OSX/libsecurity_codesigning/lib/reqmaker.h index a3ac0eedc..0b26c4f95 100644 --- a/OSX/libsecurity_codesigning/lib/reqmaker.h +++ b/OSX/libsecurity_codesigning/lib/reqmaker.h @@ -70,7 +70,7 @@ class Requirement::Maker { void cdhash(SHA1::Digest digest); void cdhash(CFDataRef digest); void platform(int platformIdentifier); - + void copy(const void *data, size_t length) { memcpy(this->alloc(length), data, length); } void copy(const Requirement *req); // inline expand diff --git a/OSX/libsecurity_codesigning/lib/reqreader.cpp b/OSX/libsecurity_codesigning/lib/reqreader.cpp index bb3d74dda..d6f94a11b 100644 --- a/OSX/libsecurity_codesigning/lib/reqreader.cpp +++ b/OSX/libsecurity_codesigning/lib/reqreader.cpp @@ -75,6 +75,15 @@ CFDataRef Requirement::Reader::getHash() return makeCFData(s, length); } +CFAbsoluteTime Requirement::Reader::getAbsoluteTime() +{ + // timestamps are saved as 64bit ints internally for + // portability, but CoreFoundation wants CFAbsoluteTimes, + // which are doubles. + // This cuts off subseconds. + return static_cast(get()); +} + const unsigned char *Requirement::Reader::getSHA1() { const unsigned char *digest; size_t length; diff --git a/OSX/libsecurity_codesigning/lib/reqreader.h b/OSX/libsecurity_codesigning/lib/reqreader.h index 69dc29d0d..55aa2f754 100644 --- a/OSX/libsecurity_codesigning/lib/reqreader.h +++ b/OSX/libsecurity_codesigning/lib/reqreader.h @@ -48,6 +48,7 @@ class Requirement::Reader { std::string getString(); CFDataRef getHash(); + CFAbsoluteTime getAbsoluteTime(); const unsigned char *getSHA1(); template void getData(T *&data, size_t &length) diff --git a/OSX/libsecurity_codesigning/lib/requirement.h b/OSX/libsecurity_codesigning/lib/requirement.h index da9175d40..747128be5 100644 --- a/OSX/libsecurity_codesigning/lib/requirement.h +++ b/OSX/libsecurity_codesigning/lib/requirement.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "codedirectory.h" #include @@ -99,18 +100,26 @@ class Requirement: public Blob { class Requirement::Context { protected: Context() - : certs(NULL), info(NULL), entitlements(NULL), identifier(""), directory(NULL) { } + : certs(NULL), info(NULL), entitlements(NULL), identifier(""), directory(NULL), packageChecksum(NULL), packageAlgorithm(kSecCodeSignatureNoHash), forcePlatform(false), secureTimestamp(NULL) { } public: - Context(CFArrayRef certChain, CFDictionaryRef infoDict, CFDictionaryRef entitlementDict, - const std::string &ident, const CodeDirectory *dir) - : certs(certChain), info(infoDict), entitlements(entitlementDict), identifier(ident), directory(dir) { } + Context(CFArrayRef certChain, CFDictionaryRef infoDict, CFDictionaryRef entitlementDict, const std::string &ident, + const CodeDirectory *dir, CFDataRef packageChecksum, SecCSDigestAlgorithm packageAlgorithm, bool force_platform, CFDateRef secure_timestamp, + const char *teamID) + : certs(certChain), info(infoDict), entitlements(entitlementDict), identifier(ident), directory(dir), + packageChecksum(packageChecksum), packageAlgorithm(packageAlgorithm), forcePlatform(force_platform), + secureTimestamp(secure_timestamp), teamIdentifier(teamID) { } CFArrayRef certs; // certificate chain CFDictionaryRef info; // Info.plist CFDictionaryRef entitlements; // entitlement plist std::string identifier; // signing identifier const CodeDirectory *directory; // CodeDirectory + CFDataRef packageChecksum; // package checksum + SecCSDigestAlgorithm packageAlgorithm; // package checksum algorithm + bool forcePlatform; + CFDateRef secureTimestamp; + const char *teamIdentifier; // team identifier SecCertificateRef cert(int ix) const; // get a cert from the cert chain (NULL if not found) unsigned int certCount() const; // length of cert chain (including root) @@ -150,7 +159,7 @@ enum ExprOp { opCDHash, // match hash of CodeDirectory directly [cd hash] opNot, // logical inverse [expr] opInfoKeyField, // Info.plist key field [string; match suffix] - opCertField, // Certificate field [cert index; field name; match suffix] + opCertField, // Certificate field, existence only [cert index; field name; match suffix] opTrustedCert, // require trust settings to approve one particular cert [cert index] opTrustedCerts, // require trust settings to approve the cert chain opCertGeneric, // Certificate component by OID [cert index; oid; match suffix] @@ -160,6 +169,9 @@ enum ExprOp { opNamedAnchor, // named anchor type opNamedCode, // named subroutine opPlatform, // platform constraint [integer] + opNotarized, // has a developer id+ ticket + opCertFieldDate, // extension value as timestamp [cert index; field name; match suffix] + opLegacyDevID, // meets legacy (pre-notarization required) policy exprOpCount // (total opcode count in use) }; @@ -174,6 +186,12 @@ enum MatchOperation { matchGreaterThan, // greater than (string with numeric comparison) matchLessEqual, // less or equal (string with numeric comparison) matchGreaterEqual, // greater or equal (string with numeric comparison) + matchOn, // on (timestamp comparison) + matchBefore, // before (timestamp comparison) + matchAfter, // after (timestamp comparison) + matchOnOrBefore, // on or before (timestamp comparison) + matchOnOrAfter, // on or after (timestamp comparison) + matchAbsent, // not present (kCFNull) }; diff --git a/OSX/libsecurity_codesigning/lib/resources.cpp b/OSX/libsecurity_codesigning/lib/resources.cpp index 25ddade7c..221e29847 100644 --- a/OSX/libsecurity_codesigning/lib/resources.cpp +++ b/OSX/libsecurity_codesigning/lib/resources.cpp @@ -138,10 +138,15 @@ static bool findStringEndingNoCase(const char *path, const char * end) void ResourceBuilder::scan(Scanner next) { bool first = true; - + while (FTSENT *ent = fts_read(mFTS)) { static const char ds_store[] = ".DS_Store"; - const char *relpath = ent->fts_path + mRoot.size() + 1; // skip prefix + "/" + const char *relpath = ent->fts_path + mRoot.size(); // skip prefix + + if (strlen(relpath) > 0) { + relpath += 1; // skip "/" + } + std::string rp; if (mRelBase != mRoot) { assert(mRelBase == mRoot + "/Contents"); @@ -183,7 +188,7 @@ void ResourceBuilder::scan(Scanner next) secinfo("rdirenum", "entering %s", ent->fts_path); GKBIS_Num_dirs++; - if (!first) { // skip root directory (relpath invalid) + if (!first) { // skip root directory if (Rule *rule = findRule(relpath)) { if (rule->flags & nested) { if (strchr(ent->fts_name, '.')) { // nested, has extension -> treat as nested bundle @@ -286,9 +291,10 @@ CFDataRef ResourceBuilder::hashFile(const char *path, CodeDirectory::HashAlgorit fd.fcntl(F_NOCACHE, true); // turn off page caching (one-pass) RefPointer hasher(CodeDirectory::hashFor(type)); hashFileData(fd, hasher.get()); - Hashing::Byte digest[hasher->digestLength()]; - hasher->finish(digest); - return CFDataCreate(NULL, digest, sizeof(digest)); + vector digest_vector(hasher->digestLength()); + hasher->finish(digest_vector.data()); + return CFDataCreate(NULL, digest_vector.data(), + digest_vector.size() * sizeof(Hashing::Byte)); } @@ -306,9 +312,9 @@ CFMutableDictionaryRef ResourceBuilder::hashFile(const char *path, CodeDirectory CFMutableDictionaryRef resultRef = result; CodeDirectory::multipleHashFileData(fd, 0, types, ^(CodeDirectory::HashAlgorithm type, Security::DynamicHash *hasher) { size_t length = hasher->digestLength(); - Hashing::Byte digest[length]; - hasher->finish(digest); - CFDictionaryAddValue(resultRef, CFTempString(hashName(type)), CFTempData(digest, length)); + vector digest_vector(length); + hasher->finish(digest_vector.data()); + CFDictionaryAddValue(resultRef, CFTempString(hashName(type)), CFTempData(digest_vector.data(), length)); }); return result.yield(); } diff --git a/OSX/libsecurity_codesigning/lib/sigblob.cpp b/OSX/libsecurity_codesigning/lib/sigblob.cpp index 619986a13..ecac7081d 100644 --- a/OSX/libsecurity_codesigning/lib/sigblob.cpp +++ b/OSX/libsecurity_codesigning/lib/sigblob.cpp @@ -34,17 +34,24 @@ namespace CodeSigning { CFDataRef EmbeddedSignatureBlob::component(CodeDirectory::SpecialSlot slot) const { - if (const BlobCore *blob = this->find(slot)) { - if (CodeDirectory::slotAttributes(slot) & cdComponentIsBlob) { - return makeCFData(*blob); // is a native Blob - } else if (const BlobWrapper *wrap = BlobWrapper::specific(blob)) { - return makeCFData(*wrap); - } else { - MacOSError::throwMe(errSecCSSignatureInvalid); - } + const BlobCore *blob = this->find(slot); + + if (blob) { + return blobData(slot, blob); } return NULL; } + +CFDataRef EmbeddedSignatureBlob::blobData(CodeDirectory::SpecialSlot slot, BlobCore const *blob) +{ + if (CodeDirectory::slotAttributes(slot) & cdComponentIsBlob) { + return makeCFData(*blob); // is a native Blob + } else if (const BlobWrapper *wrap = BlobWrapper::specific(blob)) { + return makeCFData(*wrap); + } else { + MacOSError::throwMe(errSecCSSignatureInvalid); + } +} void EmbeddedSignatureBlob::Maker::component(CodeDirectory::SpecialSlot slot, CFDataRef data) @@ -62,6 +69,21 @@ CFDictionaryRef EntitlementBlob::entitlements() const this->length() - sizeof(EntitlementBlob)); } +EntitlementDERBlob *EntitlementDERBlob::alloc(size_t length) { + size_t blobLength = length + sizeof(BlobCore); + if (blobLength < length) { + // overflow + return NULL; + } + + EntitlementDERBlob *b = (EntitlementDERBlob *)malloc(blobLength); + + if (b != NULL) { + b->BlobCore::initialize(kSecCodeMagicEntitlementDER, blobLength); + } + + return b; +} } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_codesigning/lib/sigblob.h b/OSX/libsecurity_codesigning/lib/sigblob.h index 50d8d21d1..392e84041 100644 --- a/OSX/libsecurity_codesigning/lib/sigblob.h +++ b/OSX/libsecurity_codesigning/lib/sigblob.h @@ -43,6 +43,7 @@ namespace CodeSigning { class EmbeddedSignatureBlob : public SuperBlobCore { typedef SuperBlobCore _Core; public: + static CFDataRef blobData(CodeDirectory::SpecialSlot slot, BlobCore const *blob); CFDataRef component(CodeDirectory::SpecialSlot slot) const; class Maker : public _Core::Maker { @@ -74,6 +75,21 @@ class EntitlementBlob : public Blob { CFDictionaryRef entitlements() const; }; +// +// Similar, but in DER representation. +// +class EntitlementDERBlob : public Blob { +public: + static EntitlementDERBlob *alloc(size_t length); + + uint8_t *der() { return data; } + const uint8_t *der() const { return data; } + size_t derLength() const { return BlobCore::length() - sizeof(BlobCore); } + +private: + uint8_t data[0]; +}; + } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_codesigning/lib/signer.cpp b/OSX/libsecurity_codesigning/lib/signer.cpp index fb9e75671..892792386 100644 --- a/OSX/libsecurity_codesigning/lib/signer.cpp +++ b/OSX/libsecurity_codesigning/lib/signer.cpp @@ -24,6 +24,8 @@ // // signer - Signing operation supervisor and controller // +#include "bundlediskrep.h" +#include "der_plist.h" #include "signer.h" #include "resources.h" #include "signerutils.h" @@ -106,6 +108,10 @@ void SecCodeSigner::Signer::remove(SecCSFlags flags) MacOSError::throwMe(errSecCSNotSupported); rep = code->diskRep(); + + if (state.mPreserveAFSC) + rep->writer()->setPreserveAFSC(state.mPreserveAFSC); + if (Universal *fat = state.mNoMachO ? NULL : rep->mainExecutableImage()) { // architecture-sensitive removal MachOEditor editor(rep->writer(), *fat, digestAlgorithms(), rep->mainExecutablePath()); @@ -168,6 +174,8 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags) entitlements = state.mEntitlementData; if (!entitlements && (inherit & kSecCodeSignerPreserveEntitlements)) entitlements = code->component(cdEntitlementSlot); + + generateEntitlementDER = signingFlags() & kSecCSSignGenerateEntitlementDER; // work out the CodeDirectory flags word bool haveCdFlags = false; @@ -198,7 +206,8 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags) } if (!haveCdFlags) cdFlags = 0; - if (state.mSigner == SecIdentityRef(kCFNull)) // ad-hoc signing requested... + if ((state.mSigner == SecIdentityRef(kCFNull)) && + !state.mOmitAdhocFlag) // ad-hoc signing requested... cdFlags |= kSecCodeSignatureAdhoc; // ... so note that // prepare the internal requirements input @@ -291,8 +300,88 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags) if (!rpath.empty()) { buildResources(rrpath, rpath, resourceRules); } + + + + if (inherit & kSecCodeSignerPreservePEH) { + /* We need at least one architecture in all cases because we index our + * PreEncryptionMaps by architecture. However, only machOs have any + * architecture at all, for generic targets there will just be one + * PreEncryptionHashMap. + * So if the main executable is not a machO, we just choose the local + * (signer's) main architecture as dummy value for the first element in our pair. */ + preEncryptMainArch = (code->diskRep()->mainExecutableIsMachO() ? + code->diskRep()->mainExecutableImage()->bestNativeArch() : + Architecture::local()); + + addPreEncryptHashes(preEncryptHashMaps[preEncryptMainArch], code); + + code->handleOtherArchitectures(^(Security::CodeSigning::SecStaticCode *subcode) { + Universal *fat = subcode->diskRep()->mainExecutableImage(); + assert(fat && fat->narrowed()); // handleOtherArchitectures gave us a focused architecture slice. + Architecture arch = fat->bestNativeArch(); // actually, only architecture for this slice. + addPreEncryptHashes(preEncryptHashMaps[arch], subcode); + }); + } + + if (inherit & kSecCodeSignerPreserveRuntime) { + /* We need at least one architecture in all cases because we index our + * RuntimeVersionMaps by architecture. However, only machOs have any + * architecture at all, for generic targets there will just be one + * RuntimeVersionMap. + * So if the main executable is not a machO, we just choose the local + * (signer's) main architecture as dummy value for the first element in our pair. */ + runtimeVersionMainArch = (code->diskRep()->mainExecutableIsMachO() ? + code->diskRep()->mainExecutableImage()->bestNativeArch() : + Architecture::local()); + + addRuntimeVersions(runtimeVersionMap[runtimeVersionMainArch], code); + + code->handleOtherArchitectures(^(Security::CodeSigning::SecStaticCode *subcode) { + Universal *fat = subcode->diskRep()->mainExecutableImage(); + assert(fat && fat->narrowed()); // handleOtherArchitectures gave us a focused architecture slice. + Architecture arch = fat->bestNativeArch(); // actually, only architecture for this slice. + addRuntimeVersions(runtimeVersionMap[arch], subcode); + }); + } +} + +void SecCodeSigner::Signer::addPreEncryptHashes(PreEncryptHashMap &map, SecStaticCode const *code) { + SecStaticCode::CodeDirectoryMap const *cds = code->codeDirectories(); + + if (cds != NULL) { + for(auto const& pair : *cds) { + CodeDirectory::HashAlgorithm const alg = pair.first; + CFDataRef const cddata = pair.second; + + CodeDirectory const * cd = + reinterpret_cast(CFDataGetBytePtr(cddata)); + if (cd->preEncryptHashes() != NULL) { + CFRef preEncrypt = makeCFData(cd->preEncryptHashes(), + cd->nCodeSlots * cd->hashSize); + map[alg] = preEncrypt; + } + } + } } +void SecCodeSigner::Signer::addRuntimeVersions(RuntimeVersionMap &map, const SecStaticCode *code) +{ + SecStaticCode::CodeDirectoryMap const *cds = code->codeDirectories(); + + if (cds != NULL) { + for(auto const& pair : *cds) { + CodeDirectory::HashAlgorithm const alg = pair.first; + CFDataRef const cddata = pair.second; + + CodeDirectory const * cd = + reinterpret_cast(CFDataGetBytePtr(cddata)); + if (cd->runtimeVersion()) { + map[alg] = cd->runtimeVersion(); + } + } + } +} // // Collect the resource seal for a program. @@ -320,7 +409,8 @@ void SecCodeSigner::Signer::buildResources(std::string root, std::string relBase if (!(signingFlags() & kSecCSSignV1)) { CFCopyRef rules2 = cfget(rulesDict, "rules2"); if (!rules2) { - // Clone V1 rules and add default nesting rules at weight 0 (overridden by anything in rules). + // Clone V1 rules and add default nesting rules at weight 0 (overridden by anything in rules, + // because the default weight, according to ResourceBuilder::addRule(), is 1). // V1 rules typically do not cover these places so we'll prevail, but if they do, we defer to them. rules2 = cfmake("{+%O" "'^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/' = {nested=#T, weight=0}" // exclude dynamic repositories @@ -441,6 +531,10 @@ void SecCodeSigner::Signer::signMachO(Universal *fat, const Requirement::Context { // Mach-O executable at the core - perform multi-architecture signing RefPointer writer = rep->writer(); + + if (state.mPreserveAFSC) + writer->setPreserveAFSC(state.mPreserveAFSC); + auto_ptr editor(state.mDetached ? static_cast(new BlobEditor(*fat, *this)) : new MachOEditor(writer, *fat, this->digestAlgorithms(), rep->mainExecutablePath())); @@ -462,15 +556,27 @@ void SecCodeSigner::Signer::signMachO(Universal *fat, const Requirement::Context bool mainBinary = arch.source.get()->type() == MH_EXECUTE; + uint32_t runtimeVersion = 0; + if (cdFlags & kSecCodeSignatureRuntime) { + runtimeVersion = state.mRuntimeVersionOverride ? state.mRuntimeVersionOverride : arch.source.get()->sdkVersion(); + } + arch.ireqs(requirements, rep->defaultRequirements(&arch.architecture, *this), context); if (editor->attribute(writerNoGlobal)) // can't store globally, add per-arch populate(arch); for (auto type = digestAlgorithms().begin(); type != digestAlgorithms().end(); ++type) { + uint32_t runtimeVersionToUse = runtimeVersion; + if ((cdFlags & kSecCodeSignatureRuntime) && runtimeVersionMap.count(arch.architecture)) { + if (runtimeVersionMap[arch.architecture].count(*type)) { + runtimeVersionToUse = runtimeVersionMap[arch.architecture][*type]; + } + } arch.eachDigest(^(CodeDirectory::Builder& builder) { populate(builder, arch, arch.ireqs, arch.source->offset(), arch.source->signingExtent(), mainBinary, rep->execSegBase(&(arch.architecture)), rep->execSegLimit(&(arch.architecture)), - unsigned(digestAlgorithms().size()-1)); + unsigned(digestAlgorithms().size()-1), + preEncryptHashMaps[arch.architecture], runtimeVersionToUse); }); } @@ -502,10 +608,10 @@ void SecCodeSigner::Signer::signMachO(Universal *fat, const Requirement::Context CodeDirectory *cd = builder.build(); cdSet.add(cd); }); - CFRef hashes = cdSet.hashBag(); - CFTemp hashDict("{cdhashes=%O}", hashes.get()); - CFRef hashBag = makeCFData(hashDict.get()); - CFRef signature = signCodeDirectory(cdSet.primary(), hashBag); + + CFRef hashDict = cdSet.hashDict(); + CFRef hashList = cdSet.hashList(); + CFRef signature = signCodeDirectory(cdSet.primary(), hashDict, hashList); // complete the SuperBlob cdSet.populate(&arch); @@ -533,7 +639,10 @@ void SecCodeSigner::Signer::signArchitectureAgnostic(const Requirement::Context // non-Mach-O executable - single-instance signing RefPointer writer = state.mDetached ? (new DetachedBlobWriter(*this)) : rep->writer(); - + + if(state.mPreserveAFSC) + writer->setPreserveAFSC(state.mPreserveAFSC); + CodeDirectorySet cdSet; for (auto type = digestAlgorithms().begin(); type != digestAlgorithms().end(); ++type) { @@ -544,7 +653,9 @@ void SecCodeSigner::Signer::signArchitectureAgnostic(const Requirement::Context populate(builder, *writer, ireqs, rep->signingBase(), rep->signingLimit(), false, // only machOs can currently be main binaries rep->execSegBase(NULL), rep->execSegLimit(NULL), - unsigned(digestAlgorithms().size()-1)); + unsigned(digestAlgorithms().size()-1), + preEncryptHashMaps[preEncryptMainArch], // Only one map, the default. + (cdFlags & kSecCodeSignatureRuntime) ? state.mRuntimeVersionOverride : 0); CodeDirectory *cd = builder.build(); if (!state.mDryRun) @@ -561,10 +672,9 @@ void SecCodeSigner::Signer::signArchitectureAgnostic(const Requirement::Context if (!state.mDryRun) cdSet.populate(writer); - CFRef hashes = cdSet.hashBag(); - CFTemp hashDict("{cdhashes=%O}", hashes.get()); - CFRef hashBag = makeCFData(hashDict.get()); - CFRef signature = signCodeDirectory(cdSet.primary(), hashBag); + CFRef hashDict = cdSet.hashDict(); + CFRef hashList = cdSet.hashList(); + CFRef signature = signCodeDirectory(cdSet.primary(), hashDict, hashList); writer->signature(signature); // commit to storage @@ -591,7 +701,9 @@ void SecCodeSigner::Signer::populate(DiskRep::Writer &writer) void SecCodeSigner::Signer::populate(CodeDirectory::Builder &builder, DiskRep::Writer &writer, InternalRequirements &ireqs, size_t offset, size_t length, bool mainBinary, size_t execSegBase, size_t execSegLimit, - unsigned alternateDigestCount) + unsigned alternateDigestCount, + PreEncryptHashMap const &preEncryptHashMap, + uint32_t runtimeVersion) { // fill the CodeDirectory builder.executable(rep->mainExecutablePath(), pagesize, offset, length); @@ -600,6 +712,9 @@ void SecCodeSigner::Signer::populate(CodeDirectory::Builder &builder, DiskRep::W builder.teamID(teamID); builder.platform(state.mPlatform); builder.execSeg(execSegBase, execSegLimit, mainBinary ? kSecCodeExecSegMainBinary : 0); + builder.generatePreEncryptHashes(signingFlags() & kSecCSSignGeneratePEH); + builder.preservePreEncryptHashMap(preEncryptHashMap); + builder.runTimeVersion(runtimeVersion); if (CFRef data = rep->component(cdInfoSlot)) builder.specialSlot(cdInfoSlot, data); @@ -615,7 +730,17 @@ void SecCodeSigner::Signer::populate(CodeDirectory::Builder &builder, DiskRep::W builder.specialSlot(cdEntitlementSlot, entitlements); if (mainBinary) { - builder.addExecSegFlags(entitlementsToExecSegFlags(entitlements)); + CFRef entitlementDER; + uint64_t execSegFlags = 0; + cookEntitlements(entitlements, generateEntitlementDER, + &execSegFlags, &entitlementDER.aref()); + + if (generateEntitlementDER) { + writer.component(cdEntitlementDERSlot, entitlementDER); + builder.specialSlot(cdEntitlementDERSlot, entitlementDER); + } + + builder.addExecSegFlags(execSegFlags); } } if (CFRef repSpecific = rep->component(cdRepSpecificSlot)) @@ -648,7 +773,9 @@ void SecCodeSigner::Signer::populate(CodeDirectory::Builder &builder, DiskRep::W // // Generate the CMS signature for a (finished) CodeDirectory. // -CFDataRef SecCodeSigner::Signer::signCodeDirectory(const CodeDirectory *cd, CFDataRef hashBag) +CFDataRef SecCodeSigner::Signer::signCodeDirectory(const CodeDirectory *cd, + CFDictionaryRef hashDict, + CFArrayRef hashList) { assert(state.mSigner); CFRef defaultTSContext = NULL; @@ -660,7 +787,7 @@ CFDataRef SecCodeSigner::Signer::signCodeDirectory(const CodeDirectory *cd, CFDa // generate CMS signature CFRef cms; MacOSError::check(CMSEncoderCreate(&cms.aref())); - MacOSError::check(CMSEncoderSetCertificateChainMode(cms, kCMSCertificateChainWithRoot)); + MacOSError::check(CMSEncoderSetCertificateChainMode(cms, kCMSCertificateChainWithRootOrFail)); CMSEncoderAddSigners(cms, state.mSigner); CMSEncoderSetSignerAlgorithm(cms, kCMSEncoderDigestAlgorithmSHA256); MacOSError::check(CMSEncoderSetHasDetachedContent(cms, true)); @@ -671,9 +798,21 @@ CFDataRef SecCodeSigner::Signer::signCodeDirectory(const CodeDirectory *cd, CFDa MacOSError::check(CMSEncoderSetSigningTime(cms, time)); } - if (hashBag) { + if (hashDict != NULL) { + assert(hashList != NULL); + + // V2 Hash Agility + + MacOSError::check(CMSEncoderAddSignedAttributes(cms, kCMSAttrAppleCodesigningHashAgilityV2)); + MacOSError::check(CMSEncoderSetAppleCodesigningHashAgilityV2(cms, hashDict)); + + // V1 Hash Agility + + CFTemp hashDict("{cdhashes=%O}", hashList); + CFRef hashAgilityV1Attribute = makeCFData(hashDict.get()); + MacOSError::check(CMSEncoderAddSignedAttributes(cms, kCMSAttrAppleCodesigningHashAgility)); - MacOSError::check(CMSEncoderSetAppleCodesigningHashAgility(cms, hashBag)); + MacOSError::check(CMSEncoderSetAppleCodesigningHashAgility(cms, hashAgilityV1Attribute)); } MacOSError::check(CMSEncoderUpdateContent(cms, cd, cd->length())); @@ -787,39 +926,279 @@ bool SecCodeSigner::Signer::booleanEntitlement(CFDictionaryRef entDict, CFString return CFBooleanGetValue(entValue); } -uint64_t SecCodeSigner::Signer::entitlementsToExecSegFlags(CFDataRef entitlements) +void SecCodeSigner::Signer::cookEntitlements(CFDataRef entitlements, bool generateDER, + uint64_t *execSegFlags, CFDataRef *entitlementDER) { if (!entitlements) { - return 0; + return; // nothing to do. } - const EntitlementBlob *blob = reinterpret_cast(CFDataGetBytePtr(entitlements)); - - if (blob == NULL || !blob->validateBlob(CFDataGetLength(entitlements))) { - return 0; - } + EntitlementDERBlob *derBlob = NULL; try { + const EntitlementBlob *blob = reinterpret_cast(CFDataGetBytePtr(entitlements)); + + if (blob == NULL || !blob->validateBlob(CFDataGetLength(entitlements))) { + MacOSError::throwMe(errSecCSInvalidEntitlements); + } + CFRef entDict = blob->entitlements(); - uint64_t flags = 0; + if (generateDER) { + CFRef error = NULL; + size_t const der_size = der_sizeof_plist(entDict, &error.aref()); + + if (der_size == 0) { + secerror("Getting DER size for entitlement plist failed: %@", error.get()); + MacOSError::throwMe(errSecCSInvalidEntitlements); + } + + derBlob = EntitlementDERBlob::alloc(der_size); + + if (derBlob == NULL) { + secerror("Cannot allocate buffer for DER entitlements of size %zu", der_size); + MacOSError::throwMe(errSecCSInvalidEntitlements); + } + uint8_t * const der_end = derBlob->der() + der_size; + uint8_t * const der_start = der_encode_plist(entDict, &error.aref(), derBlob->der(), der_end); + + if (der_start != derBlob->der()) { + secerror("Entitlement DER start mismatch (%zu)", (size_t)(der_start - derBlob->der())); + free(derBlob); + MacOSError::throwMe(errSecCSInvalidEntitlements); + } + + *entitlementDER = makeCFData(derBlob, derBlob->length()); + free(derBlob); + derBlob = NULL; + } - flags |= booleanEntitlement(entDict, CFSTR("get-task-allow")) ? kSecCodeExecSegAllowUnsigned : 0; - flags |= booleanEntitlement(entDict, CFSTR("run-unsigned-code")) ? kSecCodeExecSegAllowUnsigned : 0; - flags |= booleanEntitlement(entDict, CFSTR("com.apple.private.cs.debugger")) ? kSecCodeExecSegDebugger : 0; - flags |= booleanEntitlement(entDict, CFSTR("dynamic-codesigning")) ? kSecCodeExecSegJit : 0; - flags |= booleanEntitlement(entDict, CFSTR("com.apple.private.skip-library-validation")) ? kSecCodeExecSegSkipLibraryVal : 0; - flags |= booleanEntitlement(entDict, CFSTR("com.apple.private.amfi.can-load-cdhash")) ? kSecCodeExecSegCanLoadCdHash : 0; - flags |= booleanEntitlement(entDict, CFSTR("com.apple.private.amfi.can-execute-cdhash")) ? kSecCodeExecSegCanExecCdHash : 0; + if (execSegFlags != NULL) { + uint64_t flags = 0; - return flags; + flags |= booleanEntitlement(entDict, CFSTR("get-task-allow")) ? kSecCodeExecSegAllowUnsigned : 0; + flags |= booleanEntitlement(entDict, CFSTR("run-unsigned-code")) ? kSecCodeExecSegAllowUnsigned : 0; + flags |= booleanEntitlement(entDict, CFSTR("com.apple.private.cs.debugger")) ? kSecCodeExecSegDebugger : 0; + flags |= booleanEntitlement(entDict, CFSTR("dynamic-codesigning")) ? kSecCodeExecSegJit : 0; + flags |= booleanEntitlement(entDict, CFSTR("com.apple.private.skip-library-validation")) ? kSecCodeExecSegSkipLibraryVal : 0; + flags |= booleanEntitlement(entDict, CFSTR("com.apple.private.amfi.can-load-cdhash")) ? kSecCodeExecSegCanLoadCdHash : 0; + flags |= booleanEntitlement(entDict, CFSTR("com.apple.private.amfi.can-execute-cdhash")) ? kSecCodeExecSegCanExecCdHash : 0; + + *execSegFlags = flags; + } } catch (const CommonError &err) { - // Not fatal. + free(derBlob); + // Not fatal if we're not asked to generate DER entitlements. + secwarning("failed to parse entitlements: %s", err.what()); - return 0; + if (generateDER) { + throw; + } } } +//// Signature Editing + +void SecCodeSigner::Signer::edit(SecCSFlags flags) +{ + rep = code->diskRep()->base(); + + Universal *fat = state.mNoMachO ? NULL : rep->mainExecutableImage(); + + prepareForEdit(flags); + + if (fat != NULL) { + editMachO(fat); + } else { + editArchitectureAgnostic(); + } +} + +EditableDiskRep *SecCodeSigner::Signer::editMainExecutableRep(DiskRep *rep) +{ + EditableDiskRep *mainExecRep = NULL; + BundleDiskRep *bundleDiskRep = dynamic_cast(rep); + + if (bundleDiskRep) { + mainExecRep = dynamic_cast(bundleDiskRep->mainExecRep()); + } + + return mainExecRep; +} + +void SecCodeSigner::Signer::prepareForEdit(SecCSFlags flags) { + setDigestAlgorithms(code->hashAlgorithms()); + + Universal *machO = (code->diskRep()->mainExecutableIsMachO() ? + code->diskRep()->mainExecutableImage() : NULL); + + /* We need at least one architecture in all cases because we index our + * RawComponentMaps by architecture. However, only machOs have any + * architecture at all, for generic targets there will just be one + * RawComponentMap. + * So if the main executable is not a machO, we just choose the local + * (signer's) main architecture as dummy value for the first element in our pair. */ + editMainArch = (machO != NULL ? machO->bestNativeArch() : Architecture::local()); + + if (machO != NULL) { + if (machO->narrowed()) { + /* --arch gives us a narrowed SecStaticCode, but because + * codesign_allocate always creates or replaces signatures + * for all slices, we must operate on the universal + * SecStaticCode. Instead, we provide --edit-arch to specify + * which slices to edit, the others have their code signature + * copied without modifications. + */ + MacOSError::throwMe(errSecCSNotSupported, + "Signature editing must be performed on universal binary instead of narrow slice (using --edit-arch instead of --arch)."); + } + + if (state.mEditArch && !machO->isUniversal()) { + MacOSError::throwMe(errSecCSInvalidFlags, + "--edit-arch is only valid for universal binaries."); + } + + if (state.mEditCMS && machO->isUniversal() && !state.mEditArch) { + /* Each slice has its own distinct code signature, + * so a CMS blob is only valid for its one slice. + * Therefore, replacing all CMS blobs in all slices + * with the same blob is rather nonsensical, and we refuse. + * + * (Universal binaries with only one slice can exist, + * and in that case the slice to operate on would be + * umambiguous, but we are not treating those binaries + * specially and still want --edit-arch for consistency.) + */ + MacOSError::throwMe(errSecCSNotSupported, + "CMS editing must be performed on specific slice (specified with --edit-arch)."); + } + } + + void (^editArch)(SecStaticCode *code, Architecture arch) = + ^(SecStaticCode *code, Architecture arch) { + EditableDiskRep *editRep = dynamic_cast(code->diskRep()); + + if (editRep == NULL) { + MacOSError::throwMe(errSecCSNotSupported, + "Signature editing not supported for code of this type."); + } + + EditableDiskRep *mainExecRep = editMainExecutableRep(code->diskRep()); + + if (mainExecRep != NULL) { + // Delegate editing to the main executable if it is an EditableDiskRep. + //(Which is the case for machOs.) + editRep = mainExecRep; + } + + editComponents[arch] = std::make_unique(editRep->createRawComponents()); + + if (!state.mEditArch || arch == state.mEditArch) { + if (state.mEditCMS) { + CFDataRef cms = state.mEditCMS.get(); + (*editComponents[arch])[cdSignatureSlot] = cms; + } + } + }; + + editArch(code, editMainArch); + + code->handleOtherArchitectures(^(Security::CodeSigning::SecStaticCode *subcode) { + Universal *fat = subcode->diskRep()->mainExecutableImage(); + assert(fat && fat->narrowed()); // handleOtherArchitectures gave us a focused architecture slice. + Architecture arch = fat->bestNativeArch(); // actually, only architecture for this slice. + editArch(subcode, arch); + }); + + /* The resource dictionary is special, because it is + * considered "global" instead of per architecture. + * For editing, that means it's usually not embedded + * in the main executable's signature if it exists, + * but in the containing disk rep (e.g. the + * CodeResources file if the rep is a Bundle). + */ + resourceDictData = rep->component(cdResourceDirSlot); +} + +void SecCodeSigner::Signer::editMachO(Universal *fat) { + // Mach-O executable at the core - perform multi-architecture signature editing + RefPointer writer = rep->writer(); + + if (state.mPreserveAFSC) + writer->setPreserveAFSC(state.mPreserveAFSC); + + unique_ptr editor(new MachOEditor(writer, *fat, + this->digestAlgorithms(), + rep->mainExecutablePath())); + assert(editor->count() > 0); + + if (resourceDictData && !editor->attribute(writerNoGlobal)) { + // For when the resource dict is "global", e.g. for bundles. + editor->component(cdResourceDirSlot, resourceDictData); + } + + for (MachOEditor::Iterator it = editor->begin(); it != editor->end(); ++it) { + MachOEditor::Arch &arch = *it->second; + arch.source.reset(fat->architecture(it->first)); // transfer ownership + + if (resourceDictData && editor->attribute(writerNoGlobal)) { + // Technically possible to embed a resource dict in the embedded sig. + arch.component(cdResourceDirSlot, resourceDictData); + } + + for (auto const &entry : *editComponents[arch.architecture]) { + CodeDirectory::Slot slot = entry.first; + CFDataRef data = entry.second.get(); + arch.component(slot, data); + } + + /* We must preserve the original superblob's size, as the size is + * also in the macho's load commands, which are itself covered + * by the signature. */ + arch.blobSize = arch.source->signingLength(); + } + + editor->allocate(); + + for (MachOEditor::Iterator it = editor->begin(); it != editor->end(); ++it) { + MachOEditor::Arch &arch = *it->second; + editor->reset(arch); + + if (!state.mDryRun) { + EmbeddedSignatureBlob *blob = arch.make(); + editor->write(arch, blob); // takes ownership of blob + } + } + + if (!state.mDryRun) { + editor->commit(); + } + +} + +void SecCodeSigner::Signer::editArchitectureAgnostic() +{ + if (state.mDryRun) { + return; + + } + // non-Mach-O executable - single-instance signature editing + RefPointer writer = rep->writer(); + + if(state.mPreserveAFSC) + writer->setPreserveAFSC(state.mPreserveAFSC); + + for (auto const &entry : *editComponents[editMainArch]) { + CodeDirectory::Slot slot = entry.first; + CFDataRef data = entry.second.get(); + + writer->component(slot, data); + } + + // commit to storage + writer->flush(); +} + } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_codesigning/lib/signer.h b/OSX/libsecurity_codesigning/lib/signer.h index 65ea50a5d..960cf7960 100644 --- a/OSX/libsecurity_codesigning/lib/signer.h +++ b/OSX/libsecurity_codesigning/lib/signer.h @@ -51,6 +51,7 @@ class SecCodeSigner::Signer : public DiskRep::SigningContext { void sign(SecCSFlags flags); void remove(SecCSFlags flags); + void edit(SecCSFlags flags); SecCodeSigner &state; SecStaticCode * const code; @@ -66,29 +67,60 @@ class SecCodeSigner::Signer : public DiskRep::SigningContext { void prepare(SecCSFlags flags); // set up signing parameters void signMachO(Universal *fat, const Requirement::Context &context); // sign a Mach-O binary void signArchitectureAgnostic(const Requirement::Context &context); // sign anything else + + void prepareForEdit(SecCSFlags flags); // set up signature editing + void editMachO(Universal *fat); // edit a Mach-O binary + void editArchitectureAgnostic(); // edit anything else + + // HashAlgorithm -> PreEncrypt hashes + typedef std::map > + PreEncryptHashMap; + // Architecture -> PreEncryptHashMap + typedef std::map + PreEncryptHashMaps; + // HashAlgorithm -> Hardened Runtime Version + typedef std::map + RuntimeVersionMap; + // Architecture -> RuntimeVersionMap + typedef std::map + RuntimeVersionMaps; + // Architecture -> RawComponentMap + typedef EditableDiskRep::RawComponentMap RawComponentMap; + typedef std::map> + RawComponentMaps; void populate(DiskRep::Writer &writer); // global void populate(CodeDirectory::Builder &builder, DiskRep::Writer &writer, InternalRequirements &ireqs, size_t offset, size_t length, bool mainBinary, size_t execSegBase, size_t execSegLimit, - unsigned alternateDigestCount); // per-architecture - CFDataRef signCodeDirectory(const CodeDirectory *cd, CFDataRef hashBag); + unsigned alternateDigestCount, + const PreEncryptHashMap& preEncryptHashMap, + uint32_t runtimeVersion); // per-architecture + CFDataRef signCodeDirectory(const CodeDirectory *cd, + CFDictionaryRef hashDict, CFArrayRef hashList); uint32_t cdTextFlags(std::string text); // convert text CodeDirectory flags std::string uniqueName() const; // derive unique string from rep protected: + std::string sdkPath(const std::string &path) const; bool isAdhoc() const; SecCSFlags signingFlags() const; private: + static EditableDiskRep *editMainExecutableRep(DiskRep *rep); + + void addPreEncryptHashes(PreEncryptHashMap &map, SecStaticCode const *code); + void addRuntimeVersions(RuntimeVersionMap &map, SecStaticCode const *code); + void considerTeamID(const PreSigningContext& context); std::vector > topSlots(CodeDirectory::Builder &builder) const; static bool booleanEntitlement(CFDictionaryRef entDict, CFStringRef key); - static uint64_t entitlementsToExecSegFlags(CFDataRef entitlements); + static void cookEntitlements(CFDataRef entitlements, bool generateDER, + uint64_t *execSegFlags, CFDataRef *entitlementsDER); protected: void buildResources(std::string root, std::string relBase, CFDictionaryRef rules); @@ -104,12 +136,21 @@ class SecCodeSigner::Signer : public DiskRep::SigningContext { std::string identifier; // signing identifier std::string teamID; // team identifier CFRef entitlements; // entitlements + Architecture preEncryptMainArch; // pre-encrypt main architecture + PreEncryptHashMaps preEncryptHashMaps; // pre-encrypt hashes to keep + Architecture runtimeVersionMainArch; // runtime version main architecture + RuntimeVersionMaps runtimeVersionMap; // runtime versions to keep uint32_t cdFlags; // CodeDirectory flags const Requirements *requirements; // internal requirements ready-to-use size_t pagesize; // size of main executable pages 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 + RawComponentMaps editComponents; // components for signature private: Mutex resourceLock; diff --git a/OSX/libsecurity_codesigning/lib/signerutils.cpp b/OSX/libsecurity_codesigning/lib/signerutils.cpp index 855d1949d..f6da5e936 100644 --- a/OSX/libsecurity_codesigning/lib/signerutils.cpp +++ b/OSX/libsecurity_codesigning/lib/signerutils.cpp @@ -24,17 +24,22 @@ // // signerutils - utilities for signature generation // +#include "csutilities.h" +#include "drmaker.h" +#include "resources.h" #include "signerutils.h" #include "signer.h" -#include "SecCodeSigner.h" + +#include #include #include -#include "resources.h" -#include "csutilities.h" -#include "drmaker.h" + +#include "SecCodeSigner.h" + #include #include #include + #include // for helper validation @@ -98,6 +103,7 @@ ArchEditor::~ArchEditor() ArchEditor::Arch::Arch(const Architecture &arch, CodeDirectory::HashAlgorithms hashTypes) : architecture(arch) { + blobSize = 0; for (auto type = hashTypes.begin(); type != hashTypes.end(); ++type) cdBuilders.insert(make_pair(*type, new CodeDirectory::Builder(*type))); } @@ -162,6 +168,7 @@ MachOEditor::~MachOEditor() delete mNewCode; if (mTempMayExist) ::remove(tempPath.c_str()); // ignore error (can't do anything about it) + this->kill(); } @@ -255,7 +262,11 @@ void MachOEditor::reset(Arch &arch) for (auto type = mHashTypes.begin(); type != mHashTypes.end(); ++type) { arch.eachDigest(^(CodeDirectory::Builder& builder) { - builder.reopen(tempPath, arch.source->offset(), arch.source->signingOffset()); + /* Signature editing may have no need for cd builders, and not + * have opened them, so only reopen them conditionally. */ + if (builder.opened()) { + builder.reopen(tempPath, arch.source->offset(), arch.source->signingOffset()); + } }); } } @@ -306,7 +317,19 @@ void MachOEditor::commit() // copy metadata from original file... copy(sourcePath.c_str(), NULL, COPYFILE_SECURITY | COPYFILE_METADATA); - + +#if TARGET_OS_OSX + // determine AFSC status if we are told to preserve compression + bool conductCompression = false; + cmpInfo cInfo; + if (writer->getPreserveAFSC()) { + if (queryCompressionInfo(sourcePath.c_str(), &cInfo) == 0) { + if (cInfo.compressionType != 0 && cInfo.compressedSize > 0) + conductCompression = true; + } + } +#endif + // ... but explicitly update the timestamps since we did change the file char buf; mFd.read(&buf, sizeof(buf), 0); @@ -315,6 +338,28 @@ void MachOEditor::commit() // move the new file into place UnixError::check(::rename(tempPath.c_str(), sourcePath.c_str())); mTempMayExist = false; // we renamed it away + +#if TARGET_OS_OSX + // if the original file was compressed, compress the new file after move + if (conductCompression) { + CFMutableDictionaryRef options = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFStringRef val = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d"), cInfo.compressionType); + CFDictionarySetValue(options, kAFSCCompressionTypes, val); + CFRelease(val); + + CompressionQueueContext compressionQueue = CreateCompressionQueue(NULL, NULL, NULL, NULL, options); + + if (!CompressFile(compressionQueue, sourcePath.c_str(), NULL)) { + secinfo("signer", "%p Failed to queue compression of file %s", this, sourcePath.c_str()); + MacOSError::throwMe(errSecCSInternalError); + } + FinishCompressionAndCleanUp(compressionQueue); + + compressionQueue = NULL; + CFRelease(options); + } +#endif + } this->writer->flush(); } @@ -416,17 +461,57 @@ const CodeDirectory* CodeDirectorySet::primary() const return mPrimary; } - -CFArrayRef CodeDirectorySet::hashBag() const +CFArrayRef CodeDirectorySet::hashList() const { CFRef hashList = makeCFMutableArray(0); for (auto it = begin(); it != end(); ++it) { - CFRef cdhash = it->second->cdhash(); + CFRef cdhash = it->second->cdhash(true); CFArrayAppendValue(hashList, cdhash); } return hashList.yield(); } +CFDictionaryRef CodeDirectorySet::hashDict() const +{ + CFRef hashDict = makeCFMutableDictionary(); + + for (auto it = begin(); it != end(); ++it) { + SECOidTag tag = CodeDirectorySet::SECOidTagForAlgorithm(it->first); + + if (tag == SEC_OID_UNKNOWN) { + MacOSError::throwMe(errSecCSUnsupportedDigestAlgorithm); + } + + CFRef hashType = makeCFNumber(int(tag)); + CFRef fullCdhash = it->second->cdhash(false); // Full-length cdhash! + CFDictionarySetValue(hashDict, hashType, fullCdhash); + } + + return hashDict.yield(); +} + +SECOidTag CodeDirectorySet::SECOidTagForAlgorithm(CodeDirectory::HashAlgorithm algorithm) { + SECOidTag tag; + + switch (algorithm) { + case kSecCodeSignatureHashSHA1: + tag = SEC_OID_SHA1; + break; + case kSecCodeSignatureHashSHA256: + case kSecCodeSignatureHashSHA256Truncated: // truncated *page* hashes, not cdhash + tag = SEC_OID_SHA256; + break; + case kSecCodeSignatureHashSHA384: + tag = SEC_OID_SHA384; + break; + default: + tag = SEC_OID_UNKNOWN; + } + + return tag; +} + + } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_codesigning/lib/signerutils.h b/OSX/libsecurity_codesigning/lib/signerutils.h index 88cb2055f..1bd01d8ce 100644 --- a/OSX/libsecurity_codesigning/lib/signerutils.h +++ b/OSX/libsecurity_codesigning/lib/signerutils.h @@ -30,11 +30,22 @@ #include "CodeSigner.h" #include "sigblob.h" #include "cdbuilder.h" + +#include + #include #include #include #include +#include + +#if TARGET_OS_OSX +__BEGIN_DECLS +#include +__END_DECLS +#endif + namespace Security { namespace CodeSigning { @@ -75,7 +86,7 @@ class DetachedBlobWriter : public BlobWriter { // // A multi-architecture editing assistant. -// ArchEditor collects (Mach-O) architectures in use, and maintains per-archtitecture +// ArchEditor collects (Mach-O) architectures in use, and maintains per-architecture // data structures. It must be subclassed to express a particular way to handle the signing // data. // @@ -214,8 +225,14 @@ class CodeDirectorySet : public std::map #include @@ -46,6 +47,8 @@ void Xar::open(const char *path) { if ((mXar = ::xar_open(path, READ)) == NULL) return; + + mPath = std::string(path); xar_signature_t sig = ::xar_signature_first(mXar); // read signatures until we find a CMS signature @@ -91,6 +94,69 @@ CFArrayRef Xar::copyCertChain() return NULL; } +void Xar::registerStapledNotarization() +{ + registerStapledTicketInPackage(mPath); +} + +CFDataRef Xar::createPackageChecksum() +{ + xar_signature_t sig = NULL; + + // Always prefer a CMS signature to a class signature and return early + // if no appropriate signature has been found. + if (mSigCMS) { + sig = mSigCMS; + } else if (mSigClassic) { + sig = mSigClassic; + } else { + return NULL; + } + + // Extract the signed data from the xar, which is actually just the checksum + // we use as an identifying hash. + uint8_t *data = NULL; + uint32_t length; + if (xar_signature_copy_signed_data(sig, &data, &length, NULL, NULL, NULL) != 0) { + secerror("Unable to extract package hash for package: %s", mPath.c_str()); + return NULL; + } + + // xar_signature_copy_signed_data returns malloc'd data that can be used without copying + // but must be free'd properly later. + return makeCFDataMalloc(data, length); +} + +SecCSDigestAlgorithm Xar::checksumDigestAlgorithm() +{ + int32_t error = 0; + const char* value = NULL; + unsigned long size = 0; + + if (mXar == NULL) { + secerror("Evaluating checksum digest on bad xar: %s", mPath.c_str()); + return kSecCodeSignatureNoHash; + } + + error = xar_prop_get((xar_file_t)mXar, "checksum/size", &value); + if (error == -1) { + secerror("Unable to extract package checksum size: %s", mPath.c_str()); + return kSecCodeSignatureNoHash; + } + + size = strtoul(value, NULL, 10); + switch (size) { + case CC_SHA1_DIGEST_LENGTH: + return kSecCodeSignatureHashSHA1; + case CC_SHA256_DIGEST_LENGTH: + return kSecCodeSignatureHashSHA256; + case CC_SHA512_DIGEST_LENGTH: + return kSecCodeSignatureHashSHA512; + case CC_MD5_DIGEST_LENGTH: + default: + return kSecCodeSignatureNoHash; + } +} } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_codesigning/lib/xar++.h b/OSX/libsecurity_codesigning/lib/xar++.h index 8d9dccff5..59786e505 100644 --- a/OSX/libsecurity_codesigning/lib/xar++.h +++ b/OSX/libsecurity_codesigning/lib/xar++.h @@ -29,6 +29,7 @@ #include #include +#include "CSCommon.h" extern "C" { #include @@ -49,13 +50,17 @@ class Xar { operator bool() const { return mXar != 0; } bool isSigned() const { return mSigClassic != 0 || mSigCMS != 0; } - + + void registerStapledNotarization(); + CFDataRef createPackageChecksum(); CFArrayRef copyCertChain(); + SecCSDigestAlgorithm checksumDigestAlgorithm(); private: xar_t mXar; xar_signature_t mSigClassic; xar_signature_t mSigCMS; + std::string mPath; }; diff --git a/OSX/libsecurity_codesigning/lib/xpcengine.cpp b/OSX/libsecurity_codesigning/lib/xpcengine.cpp index eb246dd84..d6e37ed9d 100644 --- a/OSX/libsecurity_codesigning/lib/xpcengine.cpp +++ b/OSX/libsecurity_codesigning/lib/xpcengine.cpp @@ -28,6 +28,7 @@ #include #include +#include namespace Security { namespace CodeSigning { @@ -42,20 +43,27 @@ static const char serviceName[] = "com.apple.security.syspolicy"; static dispatch_once_t dispatchInit; // one-time init marker static xpc_connection_t service; // connection to spd static dispatch_queue_t queue; // dispatch queue for service - + +static map *feedbackBlocks; + static void init() { dispatch_once(&dispatchInit, ^void(void) { + feedbackBlocks = new map; const char *name = serviceName; if (const char *env = getenv("SYSPOLICYNAME")) name = env; - queue = dispatch_queue_create("spd-client", 0); + queue = dispatch_queue_create("spd-client", DISPATCH_QUEUE_SERIAL); service = xpc_connection_create_mach_service(name, queue, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED); xpc_connection_set_event_handler(service, ^(xpc_object_t msg) { if (xpc_get_type(msg) == XPC_TYPE_DICTIONARY) { const char *function = xpc_dictionary_get_string(msg, "function"); - if (!strcmp(function, "progress")) { - doProgress(msg); + if (strcmp(function, "progress") == 0) { + try { + doProgress(msg); + } catch (...) { + Syslog::error("Discarding progress handler exception"); + } } } }); @@ -116,9 +124,7 @@ static void copyCFDictionary(const void *key, const void *value, void *ctx) if (CFGetTypeID(value) == CFURLGetTypeID()) { CFRef path = CFURLCopyFileSystemPath(CFURLRef(value), kCFURLPOSIXPathStyle); CFDictionaryAddValue(target, key, path); - } else if (CFEqual(key, kSecAssessmentContextKeyFeedback)) { - CFDictionaryAddValue(target, key, CFTempNumber(uint64_t(value))); - } else { + } else if (!CFEqual(key, kSecAssessmentContextKeyFeedback)) { CFDictionaryAddValue(target, key, value); } } @@ -147,15 +153,46 @@ void xpcEngineAssess(CFURLRef path, SecAssessmentFlags flags, CFDictionaryRef co precheckAccess(path, context); Message msg("assess"); xpc_dictionary_set_string(msg, "path", cfString(path).c_str()); - xpc_dictionary_set_int64(msg, "flags", flags); + xpc_dictionary_set_uint64(msg, "flags", flags); CFRef ctx = makeCFMutableDictionary(); - if (context) + if (context) { CFDictionaryApplyFunction(context, copyCFDictionary, ctx); + } + + SecAssessmentFeedback feedback = (SecAssessmentFeedback)CFDictionaryGetValue(context, kSecAssessmentContextKeyFeedback); + + /* Map the feedback block to a random number for tracking, because we don't want + * to send over a pointer. */ + uint64_t __block feedbackId = 0; + if (feedback) { + dispatch_sync(queue, ^{ + bool added = false; + while (!added) { + /* Simple sequence number would probably be sufficient, + * but making the id unpredictable is also cheap enough here. */ + arc4random_buf(&feedbackId, sizeof(uint64_t)); + if ((*feedbackBlocks)[feedbackId] == NULL /* extremely certain */) { + (*feedbackBlocks)[feedbackId] = feedback; + added = true; + } + } + }); + CFDictionaryAddValue(ctx, kSecAssessmentContextKeyFeedback, CFTempNumber(feedbackId)); + } + CFRef contextData = makeCFData(CFDictionaryRef(ctx)); xpc_dictionary_set_data(msg, "context", CFDataGetBytePtr(contextData), CFDataGetLength(contextData)); msg.send(); + /* Done, feedback block won't be called anymore, + * so remove the feedback mapping from the global map. */ + if (feedback) { + dispatch_sync(queue, ^{ + feedbackBlocks->erase(feedbackId); + }); + } + if (int64_t error = xpc_dictionary_get_int64(msg, "error")) MacOSError::throwMe((int)error); @@ -172,7 +209,18 @@ static void doProgress(xpc_object_t msg) uint64_t total = xpc_dictionary_get_uint64(msg, "total"); uint64_t ref = xpc_dictionary_get_uint64(msg, "ref"); const char *token = xpc_dictionary_get_string(msg, "token"); - SecAssessmentFeedback feedback = SecAssessmentFeedback(ref); + + SecAssessmentFeedback feedback = NULL; + + // doProgress is called on the queue, so no dispatch_sync here. + try { + feedback = feedbackBlocks->at(ref); + } catch (std::out_of_range) { + // Indicates that syspolicyd gave us something it shouldn't have. + Syslog::error("no feedback block registered with ID %lld", ref); + MacOSError::throwMe(errSecCSInternalError); + } + CFTemp info("{current=%d,total=%d}", current, total); Boolean proceed = feedback(kSecAssessmentFeedbackProgress, info); if (!proceed) { @@ -205,7 +253,7 @@ CFDictionaryRef xpcEngineUpdate(CFTypeRef target, SecAssessmentFlags flags, CFDi } else MacOSError::throwMe(errSecCSInvalidObjectRef); } - xpc_dictionary_set_int64(msg, "flags", flags); + xpc_dictionary_set_uint64(msg, "flags", flags); CFRef ctx = makeCFMutableDictionary(); if (context) CFDictionaryApplyFunction(context, copyCFDictionary, ctx); @@ -264,6 +312,68 @@ void xpcEngineCheckDevID(CFBooleanRef* result) *result = xpc_dictionary_get_bool(msg,"result") ? kCFBooleanTrue : kCFBooleanFalse; } +void xpcEngineCheckNotarized(CFBooleanRef* result) +{ + Message msg("check-notarized"); + + msg.send(); + + if (int64_t error = xpc_dictionary_get_int64(msg, "error")) { + MacOSError::throwMe((int)error); + } + + *result = xpc_dictionary_get_bool(msg,"result") ? kCFBooleanTrue : kCFBooleanFalse; +} + +void xpcEngineTicketRegister(CFDataRef ticketData) +{ + Message msg("ticket-register"); + xpc_dictionary_set_data(msg, "ticketData", CFDataGetBytePtr(ticketData), CFDataGetLength(ticketData)); + + msg.send(); + + if (int64_t error = xpc_dictionary_get_int64(msg, "error")) { + MacOSError::throwMe((int)error); + } +} + +void xpcEngineTicketLookup(CFDataRef hashData, SecCSDigestAlgorithm hashType, SecAssessmentTicketFlags flags, double *date) +{ + Message msg("ticket-lookup"); + xpc_dictionary_set_data(msg, "hashData", CFDataGetBytePtr(hashData), CFDataGetLength(hashData)); + xpc_dictionary_set_uint64(msg, "hashType", hashType); + xpc_dictionary_set_uint64(msg, "flags", flags); + + msg.send(); + + if (int64_t error = xpc_dictionary_get_int64(msg, "error")) { + MacOSError::throwMe((int)error); + } + + double local_date = xpc_dictionary_get_double(msg, "date"); + if (date && !isnan(local_date)) { + *date = local_date; + } +} + +void xpcEngineLegacyCheck(CFDataRef hashData, SecCSDigestAlgorithm hashType, CFStringRef teamID) +{ + Message msg("legacy-check"); + xpc_dictionary_set_data(msg, "hashData", CFDataGetBytePtr(hashData), CFDataGetLength(hashData)); + xpc_dictionary_set_uint64(msg, "hashType", hashType); + + // There may not be a team id, so just leave it off if there isn't since xpc_dictionary_set_string + // will return a NULL if the value isn't provided. + if (teamID) { + xpc_dictionary_set_string(msg, "teamID", CFStringGetCStringPtr(teamID, kCFStringEncodingUTF8)); + } + + msg.send(); + + if (int64_t error = xpc_dictionary_get_int64(msg, "error")) { + MacOSError::throwMe((int)error); + } +} } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_codesigning/lib/xpcengine.h b/OSX/libsecurity_codesigning/lib/xpcengine.h index 4e1d485e3..a96b8d792 100644 --- a/OSX/libsecurity_codesigning/lib/xpcengine.h +++ b/OSX/libsecurity_codesigning/lib/xpcengine.h @@ -38,7 +38,11 @@ CFDictionaryRef xpcEngineUpdate(CFTypeRef target, SecAssessmentFlags flags, CFDi bool xpcEngineControl(const char *name); void xpcEngineRecord(CFDictionaryRef info); void xpcEngineCheckDevID(CFBooleanRef* result); +void xpcEngineCheckNotarized(CFBooleanRef* result); +void xpcEngineTicketRegister(CFDataRef ticketData); +void xpcEngineTicketLookup(CFDataRef hashData, SecCSDigestAlgorithm hashType, SecAssessmentTicketFlags flags, double *date); +void xpcEngineLegacyCheck(CFDataRef hashData, SecCSDigestAlgorithm hashType, CFStringRef teamID); } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_codesigning/requirements.grammar b/OSX/libsecurity_codesigning/requirements.grammar index 6f2b827fb..0481a85ce 100644 --- a/OSX/libsecurity_codesigning/requirements.grammar +++ b/OSX/libsecurity_codesigning/requirements.grammar @@ -47,11 +47,25 @@ header "post_include_cpp" { #include "requirement.h" #include "reqmaker.h" #include "csutilities.h" +#include +#include #include #include #include // OID coding +#include using namespace CodeSigning; typedef Requirement::Maker Maker; + +extern "C" { + +/* Decode a choice of UTCTime or GeneralizedTime to a CFAbsoluteTime. Return +an absoluteTime if the date was valid and properly decoded. Return +NULL_TIME otherwise. */ +CFAbsoluteTime SecAbsoluteTimeFromDateContent(DERTag tag, const uint8_t *bytes, + size_t length); + +} + } options { @@ -115,7 +129,12 @@ options { void RequirementParser::certMatchOperation(Maker &maker, int32_t slot, string key) { - if (matchPrefix(key, "subject.")) { + if (const char *oids = matchPrefix(key, "timestamp.")) { + maker.put(opCertFieldDate); + maker.put(slot); + CssmAutoData oid(Allocator::standard()); oid.fromOid(oids); + maker.putData(oid.data(), oid.length()); + } else if (matchPrefix(key, "subject.")) { maker.put(opCertField); maker.put(slot); maker.put(key); @@ -243,6 +262,10 @@ primary[Maker &maker] { maker.cdhash(digest); } | "platform" { int32_t ident; } eql ident=integer { maker.platform(ident); } + | "notarized" + { maker.put(opNotarized); } + | "legacy" + { maker.put(opLegacyDevID); } | LPAREN { string name; } name=identifierString RPAREN { maker.put(opNamedCode); maker.put(name); } ; @@ -306,12 +329,18 @@ entitlementspec[Maker &maker] { string key; } match_suffix[Maker &maker] : empty ( "exists" ) ? { maker.put(matchExists); } + | "absent" + { maker.put(matchAbsent); } | ( EQL | EQQL ) { MatchOperation mop = matchEqual; string value; } ( STAR { mop = matchEndsWith; } ) ? value=datavalue ( STAR { mop = (mop == matchEndsWith) ? matchContains : matchBeginsWith; } ) ? { maker.put(mop); maker.put(value); } + | ( EQL | EQQL ) + { MatchOperation mop = matchOn; int64_t value; } + value=timestamp + { maker.put(mop); maker.put(value); } | SUBS { string value; } value=datavalue { maker.put(matchContains); maker.put(value); } | LESS { string value; } value=datavalue @@ -322,6 +351,14 @@ match_suffix[Maker &maker] { maker.put(matchLessEqual); maker.put(value); } | GE { string value; } value=datavalue { maker.put(matchGreaterEqual); maker.put(value); } + | LESS { int64_t value; } value=timestamp + { maker.put(matchBefore); maker.put(value); } + | GT { int64_t value; } value=timestamp + { maker.put(matchAfter); maker.put(value); } + | LE { int64_t value; } value=timestamp + { maker.put(matchOnOrBefore); maker.put(value); } + | GE { int64_t value; } value=timestamp + { maker.put(matchOnOrAfter); maker.put(value); } ; bracketKey returns [string key] @@ -388,6 +425,11 @@ integer returns [int32_t result] : s:INTEGER { result = int32_t(atol(s->getText().c_str())); } ; +// timestamps +timestamp returns [int64_t result] + : "timestamp" s:STRING { result = (int64_t)SecAbsoluteTimeFromDateContent(ASN1_GENERALIZED_TIME, (uint8_t const *)s->getText().c_str(), s->getText().length()); } + ; + // syntactic cavity generators fluff : SEMI @@ -416,6 +458,10 @@ class RequirementLexer extends Lexer; options { k=2; testLiterals=false; + + // Pass through valid UTF-8 (which excludes hex C0-C1 and F5-FF). + // Byte ranges according to Unicode 11.0, paragraph 3.9 D92. + charVocabulary='\000'..'\277' | '\302'..'\364'; } protected diff --git a/OSX/libsecurity_cryptkit/Info-security_cryptkit.plist b/OSX/libsecurity_cryptkit/Info-security_cryptkit.plist deleted file mode 100644 index 0c67376eb..000000000 --- a/OSX/libsecurity_cryptkit/Info-security_cryptkit.plist +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/OSX/libsecurity_cryptkit/ckutils/Makefile b/OSX/libsecurity_cryptkit/ckutils/Makefile deleted file mode 100644 index e0a50cb5c..000000000 --- a/OSX/libsecurity_cryptkit/ckutils/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# -# Top-level Makefile for ckutils. Allows build or clean -# of all directories in one swoop. -# -SHELL := /bin/zsh - -SUBDIRS= atomTime badsig blobtest cfileTest giantAsmBench giantBench giantDvt - -first: - @foreach i in $(SUBDIRS); \ - echo "=== Making $$i ==="; \ - cd $$i; \ - make || exit; \ - cd ..; \ - end - -clean: - @foreach i in $(SUBDIRS); \ - echo "=== Cleaning $$i ==="; \ - (cd $$i; make clean;) \ - end diff --git a/OSX/libsecurity_cryptkit/ckutils/Makefile.common b/OSX/libsecurity_cryptkit/ckutils/Makefile.common deleted file mode 100644 index 3f83691ef..000000000 --- a/OSX/libsecurity_cryptkit/ckutils/Makefile.common +++ /dev/null @@ -1,88 +0,0 @@ -# -# Common makefile fragment for ckutils. -# This is -included from project-specific Makefiles, assumed -# to be one directory down from this file. -# -# Standard binary locations. Assume LOCAL_BUILD_DIR in environment. -# - -LOCAL_BUILD ?= $(shell echo $(LOCAL_BUILD_DIR)) -ifeq "" "$(LOCAL_BUILD)" - LOCAL_BUILD = . -endif - -CRYPTKIT_SRC= ../../lib - -OFILES= $(CSOURCE:%.c=%.o) $(CPPSOURCE:%.cpp=%.o) -ALL_OFILES= $(OFILES) $(CRYPTKIT_LIB_BIN) - -# -# override with recursive make for e.g. debug build -# -VARIANT_SUFFIX= - -# -# override this with a recursive make to test minimal signature build -# -CRYPTKIT_CONFIG=-DCK_STANDALONE_BUILD - -# -# override with recursive make to link against other binary -# -CRYPTKIT_BINARY=CryptKit - -# -# Assume final load with cc, not ld -# -STD_LIBS= -l$(CRYPTKIT_BINARY)$(VARIANT_SUFFIX) -STD_LIBPATH=-L$(LOCAL_BUILD) -ALL_LIBS= $(STD_LIBS) $(PROJ_LIBS) -ALL_LIBPATHS= $(STD_LIBPATH) $(PROJ_LIBPATH) - -# -# Override this from the make command line to add e.g. -lMallocDebug -# -CMDLINE_LDFLAGS= - -STD_FRAMEWORKS= -STD_FRAME_PATH= -F$(LOCAL_BUILD) -F/usr/local/SecurityPieces/Frameworks - -# -ALL_LDFLAGS= $(CMDLINE_LDFLAGS) $(ALL_LIBS) $(ALL_LIBPATHS) $(STD_FRAME_PATH) $(PROJ_LDFLAGS) - -CC= /usr/bin/gcc - -ALL_FRAMEWORKS= $(STD_FRAMEWORKS) $(PROJ_FRAMEWORKS) - -# CryptKit headers accessed via -STD_INCLUDES= -I$(CRYPTKIT_SRC) -I.. -ALL_INCLUDES= $(STD_INCLUDES) $(PROJ_INCLUDES) -CINCLUDES= $(ALL_INCLUDES) - -WFLAGS= -Wno-four-char-constants -Wall -Werror -Wno-format -Wno-deprecated-declarations -STD_CFLAGS= -g $(VERBOSE) $(CRYPTKIT_CONFIG) - -ALL_CFLAGS= $(CINCLUDES) $(STD_CFLAGS) $(PROJ_CFLAGS) $(WFLAGS) $(STD_FRAME_PATH) - -BUILT_TARGET= $(EXECUTABLE) - -first: $(BUILT_TARGET) - -debug: - echo making debug - make "VARIANT_SUFFIX=_debug" - -smallsig: - make "CRYPTKIT_CONFIG=-DCK_MINIMUM_SIG_BUILD" "CRYPTKIT_BINARY=CryptKitSignature" - -clean: - rm -f $(OFILES) $(EXECUTABLE) $(OTHER_TO_CLEAN) - -$(BUILT_TARGET): $(ALL_OFILES) $(PROJ_DEPENDS) - cc -o $(BUILT_TARGET) $(ALL_OFILES) $(ALL_FRAMEWORKS) $(ALL_LDFLAGS) - -.c.o: - $(CC) $(ALL_CFLAGS) -c -o $*.o $< - -.cpp.o: - $(CC) $(ALL_CFLAGS) -c -o $*.o $< diff --git a/OSX/libsecurity_cryptkit/ckutils/atomTime/Makefile b/OSX/libsecurity_cryptkit/ckutils/atomTime/Makefile deleted file mode 100644 index cef232322..000000000 --- a/OSX/libsecurity_cryptkit/ckutils/atomTime/Makefile +++ /dev/null @@ -1,53 +0,0 @@ -# name of executable to build -EXECUTABLE=atomTime -# C source (.c extension) -CSOURCE= atomTime.c - -SHELL := /bin/zsh - -# project-specific libraries, e.g., -lstdc++ -# -PROJ_LIBS= - -# -# Optional lib search paths -# -PROJ_LIBPATH= - -# -# choose one for cc -# -VERBOSE= -#VERBOSE=-v - -# -# non-standard frameworks (e.g., -framework foo) -# -PROJ_FRAMEWORKS= -framework CoreFoundation - -# -# Other files to remove at 'make clean' time -# -OTHER_TO_CLEAN= - -# -# project-specific includes, with leading -I -# -PROJ_INCLUDES= - -# -# Optional C flags (warnings, optimizations, etc.) -# -PROJ_CFLAGS=-O3 - -# -# Optional link flags (using cc, not ld) -# -PROJ_LDFLAGS= - -# -# Optional dependencies -# -PROJ_DEPENDS= - -include ../Makefile.common diff --git a/OSX/libsecurity_cryptkit/ckutils/atomTime/atomTime.c b/OSX/libsecurity_cryptkit/ckutils/atomTime/atomTime.c deleted file mode 100644 index d4eec1275..000000000 --- a/OSX/libsecurity_cryptkit/ckutils/atomTime/atomTime.c +++ /dev/null @@ -1,662 +0,0 @@ -/* - * atomTime.c - measure performance of mulg, gsquare, feemod, - * gshift{left,right}, elliptic, ellMulProj - */ - -#include "ckconfig.h" -#include "ckutilsPlatform.h" -#include "CryptKitSA.h" -#include "ckutilities.h" /* needs private headers */ -#include "curveParams.h" /* ditto */ -#include "falloc.h" /* ditto */ -#include "elliptic.h" -#include "ellipticProj.h" -#include -#include -#include - -/* default loops for "fast" and "slow" ops respecitively */ -#define LOOPS_DEF_FAST 10000 -#define LOOPS_DEF_SLOW 100 - -#define NUM_BORROW 100 - -/* individual enables - normally all on, disable to zero in on one test */ -#define MULG_ENABLE 1 -#define GSQUARE_ENABLE 1 -#define FEEMOD_ENABLE 1 -#define BORROW_ENABLE 1 -#define SHIFT_ENABLE 1 -#define BINVAUX_ENABLE 1 -#define MAKE_RECIP_ENABLE 1 -#define MODGRECIP_ENABLE 1 -#define KEYGEN_ENABLE 1 -#define ELLIPTIC_ENABLE 1 -#define ELL_SIMPLE_ENABLE 1 - -static void usage(char **argv) -{ - printf("Usage: %s [l=loops_fast] [L=loops_slow] [q(uick)] [D=depth]\n", argv[0]); - exit(1); -} - -/* - * Fill numGiants with random data of length bits. - */ -static void genRandGiants(giant *giants, - unsigned numGiants, - unsigned bits, - feeRand rand) -{ - int i; - giant g; - unsigned char *rdata; - unsigned bytes = (bits + 7) / 8; - giantDigit mask = 0; - unsigned giantMsd = 0; // index of MSD - unsigned log2BitsPerDigit; - unsigned bitsPerDigit; - - /* just to satisfy compiler - make sure it's always called */ - if(giants == NULL) { - return; - } - - log2BitsPerDigit = GIANT_LOG2_BITS_PER_DIGIT; - bitsPerDigit = GIANT_BITS_PER_DIGIT; - - if((bits & 7) != 0) { - /* - * deserializeGiant() has a resolution of one byte. We - * need more resolution - that is, we'll be creating - * giants a little larger than we need, and we'll mask off - * some bits in the giants' m.s. digit. - * This assumes that data fills the giantDigits such - * that if bytes mod GIANT_BYTES_PER_DIGIT != 0, the - * empty byte(s) in the MSD are in the m.s. byte(s). - */ - giantMsd = bits >> log2BitsPerDigit; - mask = (1 << (bits & (bitsPerDigit - 1))) - 1; - } - rdata = fmalloc(bytes); - for(i=0; in[giantMsd] &= mask; - - /* - * We've zeroed out some bits; we might have to - * adjust the sign of the giant as well. Note that - * deserializeGiant always yields positive - * giants.... - */ - for(j=(g->sign - 1); j!=0; j--) { - if(g->n[j] == 0) { - (g->sign)--; - } - else { - break; - } - } - } - } - ffree(rdata); - return; -} - -#if CRYPTKIT_ELL_PROJ_ENABLE -/* - * Assumes the presence of numEllPoints items in *points, and that the - * x coordinate in each point is init'd to a random giant. Uses the x - * coords as seeds to make normalized points of the entire *points array. - */ -static void makePoints(pointProjStruct *points, - unsigned numEllPoints, - curveParams *cp) -{ - int i; - giant seed = newGiant(cp->maxDigits); - - for(i=0; i maxLoops) { - maxLoops = loopsSlow; - } - - /* - * Alloc array of giants big enough for squaring at the largest - * key size, enough of them for 'loops' mulgs - */ - cp = curveParamsForDepth(FEE_DEPTH_LARGEST); - numGiants = maxLoops * 2; // 2 giants per loop - if(loopsSlow > (maxLoops / 4)) { - /* findPointProj needs 4 giants per loop */ - numGiants *= 4; - } - #if CRYPTKIT_ELL_PROJ_ENABLE - numEllGiants = loopsSlow * 2; - numEllPoints = loopsSlow * 2; - #endif - giants = fmalloc(numGiants * sizeof(giant)); - if(giants == NULL) { - printf("malloc failure\n"); - exit(1); - } - for(i=0; imaxDigits); - if(giants[i] == NULL) { - printf("malloc failure\n"); - exit(1); - } - } - freeCurveParams(cp); - - #if CRYPTKIT_ELL_PROJ_ENABLE - /* - * Projective points - two per ellLoop. The giants come from - * giants[]. We reserve an extra giant per point. - * We're assuming that numEllPoints < (4 * numGiants). - */ - points = fmalloc(numEllPoints * sizeof(pointProjStruct)); - if(points == NULL) { - printf("malloc failure\n"); - exit(1); - } - j=0; - for(i=0; icurveType) { - case FCT_Montgomery: - curveType = "FCT_Montgomery"; - break; - case FCT_Weierstrass: - curveType = "FCT_Weierstrass"; - break; - case FCT_General: - curveType = "FCT_General"; - break; - default: - printf("***Unknown curveType!\n"); - exit(1); - } - - switch(cp->primeType) { - case FPT_General: - printf("depth=%d; FPT_General, %s; keysize=%d;\n", - depth, curveType, bitlen(cp->basePrime)); - break; - case FPT_Mersenne: - printf("depth=%d; FPT_Mersenne, %s; q=%d\n", - depth, curveType, cp->q); - break; - default: - printf("depth=%d; FPT_FEE, %s; q=%d k=%d\n", - depth, curveType, cp->q, cp->k); - break; - } - basePrimeLen = bitlen(cp->basePrime); - - /* - * mulg test - * bitlen(giant) <= bitlen(basePrime); - * giants[n+1] *= giants[n] - */ - #if MULG_ENABLE - genRandGiants(giants, numGiants, basePrimeLen, rand); - PLAT_GET_TIME(startTime); - for(i=0; imaxDigits); - } - for(j=0; jbasePrime, giants[i]); - } - PLAT_GET_TIME(endTime); - elapsed = PLAT_GET_US(startTime, endTime); - printf(" binvaux: %12.2f us per op\n", - elapsed / loopsSlow); - #endif /* BINVAUX_ENABLE */ - - /* - * make_recip test - * bitlen(giant) <= bitlen(basePrime); - * make_recip(giants[n], giants[n+1] - */ - #if MAKE_RECIP_ENABLE - genRandGiants(giants, numGiants, basePrimeLen, rand); - PLAT_GET_TIME(startTime); - for(i=0; imaxDigits); - recip = borrowGiant(cp->maxDigits); - genRandGiants(&modGiant, 1, basePrimeLen, rand); - make_recip(modGiant, recip); - - PLAT_GET_TIME(startTime); - for(i=0; imaxDigits); - PLAT_GET_TIME(startTime); - for(i=0; in[0] = 1; - z->sign = 1; - elliptic(giants[i], z, giants[i+1], cp); - } - PLAT_GET_TIME(endTime); - elapsed = PLAT_GET_US(startTime, endTime); - printf(" elliptic: %12.2f us per op\n", - elapsed / (loopsSlow / 2)); - #endif /* ELLIPTIC_ENABLE*/ - - /* - * elliptic_simple test - * bitlen(giant) <= bitlen(basePrime); - * giants[n] *= giants[n+1] (elliptic mult) - */ - #if ELL_SIMPLE_ENABLE - genRandGiants(giants, numGiants, basePrimeLen, rand); - PLAT_GET_TIME(startTime); - for(i=0; icurveType != FCT_Weierstrass) { - goto loopEnd; - } - - #if CRYPTKIT_ELL_PROJ_ENABLE - /* - * ellMulProj test - * bitlen(giant) <= bitlen(basePrime); - * point[n+1] = point[n] * giants[4n+3] - * - * note we're cooking up way more giants than we have to; - * we really only need the x's and k's. But what the heck. - */ - genRandGiants(giants, 4 * numEllPoints, basePrimeLen, rand); - makePoints(points, numEllPoints, cp); - PLAT_GET_TIME(startTime); - for(i=0; i -#import - -static unsigned char *passwdPool; /* all passwords come from here */ -static unsigned char *dataPool; /* plaintext comes from here */ - -#define MAX_DATA_SIZE ((1024 * 1024) + 100) /* bytes */ - -/* - * Defaults. - */ -#define LOOPS_DEF 1 -#define MIN_EXP 2 /* for data size 10**exp */ -#define MAX_EXP 4 -#define PWD_LENGTH 15 /* bytes */ -#define DEPTH_DEFAULT FEE_DEPTH_DEFAULT -#define INCR_DEFAULT 1 /* munge every incr bytes */ - -///#define DEPTH_DEFAULT FEE_DEPTH_5 - -static void usage(char **argv) -{ - printf("usage: %s [options]\n", argv[0]); - printf(" Options:\n"); - printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); - printf(" n=minExp (default=%d)\n", MIN_EXP); - printf(" x=maxExp (default=max=%d)\n", MAX_EXP); - printf(" p=passwdLength (default=%d)\n", PWD_LENGTH); - printf(" D=depth (default=%d)\n", DEPTH_DEFAULT); - printf(" i=increment (default=%d)\n", INCR_DEFAULT); - #if CRYPTKIT_ECDSA_ENABLE - printf(" e (ElGamal only, no ECDSA)\n"); - #endif - printf(" s=seed\n"); - printf(" v(erbose)\n"); - printf(" q(uiet)\n"); - printf(" h(elp)\n"); - exit(1); -} - -/* - * ...min <= return <= max - */ -static int genRand(int min, int max) -{ - - /* note random() only yields a 31-bit number... */ - - if(max == min) /* avoid % 1 ! */ - return(max); - else - return(min + (random() % (max-min+1))); -} - -static unsigned char *genPasswd(unsigned passwdLength) -{ - unsigned *ip = (unsigned *)passwdPool; - unsigned intCount = passwdLength / 4; - int i; - unsigned char *cp; - unsigned residue = passwdLength & 0x3; - - for (i=0; i MAX_ASCII) { - ac = MIN_ASCII; - } - } - break; - case DT_Random: - intCount = size >> 2; - ip = (unsigned *)dataPool; - for(i=0; i MAX_EXP) { - usage(argv); - } - break; - case 'D': - depth = atoi(&argp[2]); - break; - case 'i': - incr = atoi(&argp[2]); - break; - case 's': - seed = atoi(&argp[2]); - seedSpec = 1; - break; - case 'p': - passwdLen = atoi(&argp[2]); - if(passwdLen == 0) { - usage(argv); - } - break; - case 'e': - elGamalOnly = 1; - break; - case 'v': - verbose = 1; - break; - case 'q': - quiet = 1; - break; - case 'h': - default: - usage(argv); - } - } - - if(seedSpec == 0) { - time((long *)(&seed)); - } - srandom(seed); - passwdPool = malloc(passwdLen); - dataPool = malloc(MAX_DATA_SIZE); - - printf("Starting %s test: loops %d seed %d elGamalOnly %d depth %d\n", - argv[0], loops, seed, elGamalOnly, depth); - - #if 0 - /* debug only */ - { - char s[20]; - printf("attach, then CR to continue: "); - gets(s); - } - #endif 0 - - for(loop=1; ; loop++) { - - ptext = genData(minExp, maxExp, DT_Random, &ptextLen); - passwd = genPasswd(passwdLen); - - /* - * Alternate between ECDSA and ElGamal - */ - if(elGamalOnly) { - doECDSA = 0; - doECDSAVfy = 0; - } - else { - if(loop & 1) { - doECDSA = 1; - if(loop & 2) { - doECDSAVfy = 1; - } - else { - doECDSAVfy = 0; - } - } - else { - doECDSA = 0; - doECDSAVfy = 0; - } - } - if(!quiet) { - printf("..loop %d text size %d ECDSA %d ECDSAVfy %d\n", - loop, ptextLen, doECDSA, doECDSAVfy); - } - if(doTest(ptext, ptextLen, passwd, passwdLen, - verbose, quiet, depth, incr, - doECDSA, doECDSAVfy)) { - exit(1); - } - - if(loops && (loop == loops)) { - break; - } - } - if(!quiet) { - printf("%s test complete\n", argv[0]); - } - return 0; -} diff --git a/OSX/libsecurity_cryptkit/ckutils/blobtest/Makefile b/OSX/libsecurity_cryptkit/ckutils/blobtest/Makefile deleted file mode 100644 index c4c789adf..000000000 --- a/OSX/libsecurity_cryptkit/ckutils/blobtest/Makefile +++ /dev/null @@ -1,51 +0,0 @@ -# name of executable to build -EXECUTABLE=blobtest -# C source (.c extension) -CSOURCE= blobtest.c - -# project-specific libraries, e.g., -lstdc++ -# -PROJ_LIBS= - -# -# Optional lib search paths -# -PROJ_LIBPATH= - -# -# choose one for cc -# -VERBOSE= -#VERBOSE=-v - -# -# non-standard frameworks (e.g., -framework foo) -# -PROJ_FRAMEWORKS= - -# -# Other files to remove at 'make clean' time -# -OTHER_TO_CLEAN= - -# -# project-specific includes, with leading -I -# -PROJ_INCLUDES= - -# -# Optional C flags (warnings, optimizations, etc.) -# -PROJ_CFLAGS= - -# -# Optional link flags (using cc, not ld) -# -PROJ_LDFLAGS= - -# -# Optional dependencies -# -PROJ_DEPENDS= - -include ../Makefile.common diff --git a/OSX/libsecurity_cryptkit/ckutils/blobtest/blobtest.c b/OSX/libsecurity_cryptkit/ckutils/blobtest/blobtest.c deleted file mode 100644 index 0f678f8b9..000000000 --- a/OSX/libsecurity_cryptkit/ckutils/blobtest/blobtest.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright (c) 1998,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 "Crypt.h" -#include "falloc.h" -#include -#include -#include -#include "ckutilsPlatform.h" - -#define MIN_PASSWD_LENGTH 4 -#define MAX_PASSWD_LENGTH 20 -#define DEPTH_DEFAULT FEE_DEPTH_DEFAULT - -#undef BOOL -#undef YES -#undef NO -#define BOOL int -#define YES 1 -#define NO 0 - -static unsigned char *passwdPool; - -static unsigned doBlobTest(unsigned minPasswdLen, - unsigned maxPasswdLen, - BOOL verbose, - unsigned depth); -static void usage(char **argv); - -int main(int argc, char **argv) -{ - BOOL seedSpec = NO; // YES ==> user specified - unsigned loopNum; - int arg; - char *argp; - - /* - * User-spec'd variables - */ - unsigned minPasswordLen = MIN_PASSWD_LENGTH; - unsigned maxPasswordLen = MAX_PASSWD_LENGTH; - int seed = 0; - unsigned loops = 1; - BOOL quiet = NO; - BOOL verbose = NO; - unsigned depth = DEPTH_DEFAULT; - - #if macintosh - argc = ccommand(&argv); - #endif - for(arg=1; arg -#include -#include - -static unsigned char *dataPool; /* plaintext comes from here */ - -#undef BOOL -#undef YES -#undef NO -#define BOOL int -#define YES 1 -#define NO 0 - -#define LOOPS_DEF 100 -#define MIN_EXP 2 /* for data size 10**exp */ -#define MAX_EXP 3 /* FEED is very slow with ptext larger than this... */ -#define DEPTH_DEFAULT FEE_DEPTH_DEFAULT -#define MIN_OFFSET 0 -#define MAX_OFFSET 99 - -#define PASSWD_LENGTH 10 - -static void usage(char **argv) -{ - printf("usage: %s [options]\n", argv[0]); - printf("Options:\n"); - printf(" l==loops (default=%d)\n", LOOPS_DEF); - printf(" n=minExp (default=%d)\n", MIN_EXP); - printf(" x=maxExp (default=max=%d)\n", MAX_EXP); - printf(" D=depth (default=%d)\n", DEPTH_DEFAULT); - printf(" N=minOffset (default=%d)\n", MIN_OFFSET); - printf(" q(uiet) v(erbose)\n"); - printf(" h(elp) I(ncrementing offset)\n"); - exit(1); -} - -/* - * ...min <= return <= max - */ -static int genRand(int min, int max) -{ - - /* note random() only yields a 31-bit number... */ - - if(max == min) /* avoid % 1 ! */ - return(max); - else - return(min + (RAND() % (max-min+1))); -} - -/* end of feeLib routines */ - -#define MIN_ASCII ' ' -#define MAX_ASCII '~' - -static void genPasswd(unsigned char *passwd, - unsigned passwdLen, BOOL ascii) -{ - unsigned *ip = (unsigned *)passwd; - unsigned intCount = passwdLen / 4; - int i; - unsigned char *cp; - unsigned residue = passwdLen & 0x3; - char ac; - - if(ascii) { - cp = passwd; - ac = MIN_ASCII; - for(i=0; i MAX_ASCII) { - ac = MIN_ASCII; - } - } - } - else { - for (i=0; i MAX_ASCII) { - ac = MIN_ASCII; - } - } - break; - case DT_Random: - #ifdef __LITTLE_ENDIAN__ - intCount = size >> 2; - ip = (unsigned *)dataPool; - for(i=0; i MAX_OFFSET) { - minOffset = MIN_OFFSET; - } - sizeOffset = minOffset; - break; - case 'x': - maxExp = atoi(&argp[2]); - if(maxExp > MAX_EXP) { - usage(argv); - } - break; - case 's': - seed = atoi(&argp[2]); - seedSpec = YES; - break; - case 'I': - incrOffset = YES; - break; - case 'q': - quiet = YES; - break; - case 'v': - verbose = YES; - break; - case 'h': - default: - usage(argv); - } - } - - if(seedSpec == NO) { - time((unsigned long *)(&seed)); - } - SRAND(seed); - maxSize = dataSizeFromExp(maxExp) + MAX_OFFSET + 8; - dataPool = fmalloc(maxSize); - - printf("Starting cfileTest: loops %d seed %d depth %d\n", - loops, seed, depth); - - for(loop=1; ; loop++) { - - ptext = genData(minExp, maxExp, DT_Random, incrOffset, - minOffset, &ptextLen); - if(!quiet) { - printf("..loop %d plaintext size %d\n", loop, ptextLen); - } - - /* - * Generate a whole bunch of keys - */ - genPasswd(passwd1, PASSWD_LENGTH, NO); // not ascii! - genPasswd(passwd2, PASSWD_LENGTH, NO); - myPrivKey = genPrivKey(passwd1, PASSWD_LENGTH, depth); - theirPrivKey = genPrivKey(passwd2, PASSWD_LENGTH, depth); - myPubKey = genPubKey(myPrivKey); - theirPubKey = genPubKey(theirPrivKey); - - for(encrType=CFE_PublicDES; - encrType<=CFE_FEEDExp; - encrType++) { - - if(verbose) { - printf(" ..%s\n", stringFromEncrType(encrType)); - } - for(doEnc64=0; doEnc64<2; doEnc64++) { - if(verbose) { - printf(" ..doEnc64 %d\n", doEnc64); - } - - if(verbose) { - printf(" ..no sig\n"); - } - doTest(ptext, ptextLen, myPrivKey, myPubKey, - theirPrivKey, theirPubKey, - encrType, doEnc64, SIG_NO, EXPLICIT_NO); - - if(verbose) { - printf(" ..sig, implicit sendPubKey\n"); - } - doTest(ptext, ptextLen, myPrivKey, myPubKey, - theirPrivKey, theirPubKey, - encrType, doEnc64, SIG_YES, EXPLICIT_NO); - - if(verbose) { - printf(" ..sig, explicit sendPubKey\n"); - } - doTest(ptext, ptextLen, myPrivKey, myPubKey, - theirPrivKey, theirPubKey, - encrType, doEnc64, SIG_YES, EXPLICIT_YES); - - if(verbose) { - printf(" ..sig, force error\n"); - } - doTest(ptext, ptextLen, myPrivKey, myPubKey, - theirPrivKey, theirPubKey, - encrType, doEnc64, SIG_YES, EXPLICIT_ERR); - - } /* for doEnc64 */ - } /* for encrType */ - - feePubKeyFree(myPrivKey); - feePubKeyFree(myPubKey); - feePubKeyFree(theirPrivKey); - feePubKeyFree(theirPubKey); - if(loops) { - if(loop == loops) { - break; - } - } - } /* main loop */ - - if(!quiet) { - printf("cfile test complete\n"); - } - return 0; -} diff --git a/OSX/libsecurity_cryptkit/ckutils/ckutilsPlatform.h b/OSX/libsecurity_cryptkit/ckutils/ckutilsPlatform.h deleted file mode 100644 index 66ee7bcb4..000000000 --- a/OSX/libsecurity_cryptkit/ckutils/ckutilsPlatform.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Platform-dependent stuff for ckutils - */ - -#ifndef _CKU_PLATFORM_H_ -#define _CKU_PLATFORM_H_ - -#include -#include - -/* use this for linux compatibility testing */ -//#define linux 1 -/* end linux test */ - -/* - * Make sure endianness is defined... - */ -#if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) - #if macintosh - #define __BIG_ENDIAN__ 1 - #elif defined(i386) || defined(i486) || defined(__i386__) || defined(__i486__) - #define __LITTLE_ENDIAN__ 1 - #else - #error Platform dependent work needed - #endif -#endif /* endian */ - -#ifdef NeXT - #import - #define SRAND(x) srandom(x) - #define RAND() random() -#else NeXT - /* - * Use stdlib only - */ - #define SRAND(x) srand(x) - #define RAND() rand() - #define bcopy(s, d, l) memmove(d, s, l) - #define bzero(s, l) memset(s, 0, l) - #define bcmp(s, d, l) memcmp(s, d, l) -#endif - -#ifdef CK_NT_C_ONLY - -/* - * Standard I/O redirects for WINNT. - */ -#define open(f, b, c) _open(f, b, c) -#define close(f) _close(f) -#define read(f, b, c) _read(f, b, c) -#define write(f, b, c) _write(f, b, c) -#define fstat(f, b) _fstat(f, b) - -#define O_RDONLY _O_RDONLY -#define O_WRONLY _O_WRONLY -#define O_CREAT _O_CREAT -#define O_TRUNC _O_TRUNC - -#endif CK_NT_C_ONLY - -/* - * Platform-dependent timestamp stuff. For now we assume that each platform - * has some kind of struct which maintains a high-resolution clock and - * a function which fills that struct with the current time. - */ -#if macintosh - - #include - - #define PLAT_TIME UnsignedWide - #define PLAT_GET_TIME(pt) Microseconds(&pt) - #define PLAT_GET_US(start,end) (end.lo - start.lo) - -#elif linux - - #include - - #define PLAT_TIME struct timeval - #define PLAT_GET_TIME(pt) gettimeofday(&pt, NULL) - #define PLAT_GET_US(start,end) \ - ( ( ( (end.tv_sec & 0xff) * 1000000) + end.tv_usec) - \ - ( ( (start.tv_sec & 0xff) * 1000000) + start.tv_usec) ) - -#elif NeXT - - #include - - #define PLAT_TIME struct tsval - #define PLAT_GET_TIME(pt) kern_timestamp(&pt) - #define PLAT_GET_US(start,end) (end.low_val - start.low_val) - - -#elif defined(__MACH__) && defined(__APPLE__) - #include - /* time as a double */ - #define PLAT_TIME CFAbsoluteTime - #define PLAT_GET_TIME(pt) pt = CFAbsoluteTimeGetCurrent() - #define PLAT_GET_US(start,end) \ - ((end - start) * 1000000.0) - #define PLAT_GET_NS(start,end) \ - ((end - start) * 1000000000.0) -#else - #error Platform dependent work needed -#endif - -#endif /* _CKU_PLATFORM_H_ */ diff --git a/OSX/libsecurity_cryptkit/ckutils/giantAsmBench/Makefile b/OSX/libsecurity_cryptkit/ckutils/giantAsmBench/Makefile deleted file mode 100644 index e44b24a03..000000000 --- a/OSX/libsecurity_cryptkit/ckutils/giantAsmBench/Makefile +++ /dev/null @@ -1,51 +0,0 @@ -# name of executable to build -EXECUTABLE=giantAsmBench -# C source (.c extension) -CSOURCE= giantAsmBench.c - -# project-specific libraries, e.g., -lstdc++ -# -PROJ_LIBS= - -# -# Optional lib search paths -# -PROJ_LIBPATH= - -# -# choose one for cc -# -VERBOSE= -#VERBOSE=-v - -# -# non-standard frameworks (e.g., -framework foo) -# -PROJ_FRAMEWORKS= -framework CoreFoundation - -# -# Other files to remove at 'make clean' time -# -OTHER_TO_CLEAN= - -# -# project-specific includes, with leading -I -# -PROJ_INCLUDES= - -# -# Optional C flags (warnings, optimizations, etc.) -# -PROJ_CFLAGS= -Os - -# -# Optional link flags (using cc, not ld) -# -PROJ_LDFLAGS= - -# -# Optional dependencies -# -PROJ_DEPENDS= - -include ../Makefile.common diff --git a/OSX/libsecurity_cryptkit/ckutils/giantAsmBench/giantAsmBench.c b/OSX/libsecurity_cryptkit/ckutils/giantAsmBench/giantAsmBench.c deleted file mode 100644 index 2f5a08729..000000000 --- a/OSX/libsecurity_cryptkit/ckutils/giantAsmBench/giantAsmBench.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -#include -#include -#include -#include -#include "ckutilsPlatform.h" -#include -#include - -#define LOOPS_DEF 10000 -#define MIN_SIZE_DEF 1 /* mix digits for vectorMultiply test */ -#define MAX_SIZE_DEF 8 /* max digits */ - - -static void usage(char **argv) -{ - printf("usage: %s [options]\n", argv[0]); - printf(" Options:\n"); - printf(" l=loops (default = %d)\n", LOOPS_DEF); - printf(" n=maxDigits (default = %d)\n", MIN_SIZE_DEF); - printf(" x=maxDigits (default = %d)\n", MAX_SIZE_DEF); - printf(" s=seed\n"); - printf(" h(elp)\n"); - exit(1); -} - -/* - * Fill buffer with random data. Assumes giantDigits is native int size. - */ -static void randDigits(unsigned numDigits, - giantDigit *digits) -{ - int i; - - for(i=0; i -#include "ckutilsPlatform.h" -#include -#include - -#define LOOPS_DEF 100 -#define MIN_SIZE_DEF 4 /* min giant size in bytes */ -#define MAX_SIZE_DEF 32 /* max in bytes */ -#define LOOP_NOTIFY 100 - - -static void usage(char **argv) -{ - printf("usage: %s [options]\n", argv[0]); - printf(" Options:\n"); - printf(" l=loops (default = %d)\n", LOOPS_DEF); - printf(" n=maxBytes (default = %d\n", MIN_SIZE_DEF); - printf(" x=maxBytes (default = %d\n", MAX_SIZE_DEF); - printf(" o (use old 16-bit CryptKit\n"); - printf(" s=seed\n"); - printf(" h(elp)\n"); - exit(1); -} - -/* - * Fill buffer with random data. - */ -static void fillData(unsigned bufSize, - unsigned char *buf) -{ - unsigned *ip; - unsigned intCount; - unsigned residue; - unsigned char *cp; - int i; - - intCount = bufSize >> 2; - ip = (unsigned *)buf; - for(i=0; isign = -g->sign; - } - - /* avoid zero data - too many pitfalls with mod and div */ - while(isZero(g)) { - g->sign = 1; - g->n[0] = RAND(); - } -} - -/* - * Init giant arrays with random data. - */ -static void initRandGiants(unsigned numBytes, - unsigned char *buf, - unsigned numGiants, - giant *g1, - giant *g2) -{ - int i; - - for(i=0; i -#include "ckutilsPlatform.h" -#include -#include - -#define LOOPS_DEF 100 -#define MAX_SIZE_DEF 32 -#define LOOP_NOTIFY 100 - -/* quick test to show modg(1,g) broken */ -#define MODG1_TEST_ENABLE 1 - -static void usage(char **argv) -{ - printf("usage: %s [options]\n", argv[0]); - printf(" Options:\n"); - printf(" l=loops (default = %d)\n", LOOPS_DEF); - printf(" x=maxBytes (default = %d)\n", MAX_SIZE_DEF); - printf(" s=seed\n"); - printf(" h(elp)\n"); - exit(1); -} - -/* - * ...min <= return <= max - */ -static int genRand(int min, int max) -{ - - /* note random() only yields a 31-bit number... */ - - if(max == min) /* avoid % 1 ! */ - return(max); - else - return(min + (RAND() % (max-min+1))); -} - -/* - * Fill buffer with random data, random size from 1 to maxSize. - * Returns size of random data generated. - */ -static unsigned fillData(unsigned maxSize, - unsigned char *data, - int evenOnly) -{ - unsigned *ip; - unsigned intCount; - unsigned residue; - unsigned char *cp; - int i; - unsigned size; - - size = genRand(1, maxSize); - if(evenOnly) { - size &= ~1; - if(size == 1) { - size = 2; - } - } - intCount = size >> 2; - ip = (unsigned *)data; - for(i=0; isign = -g->sign; - } - - /* avoid zero data - too many pitfalls with mod and div */ - if(isZero(g)) { - g->sign = 1; - g->n[0] = 0x77; - } - return g; -} - -static int testError() -{ - char resp[100]; - - printf("Attach via debugger for more info.\n"); - printf("a to abort, c to continue: "); - gets(resp); - return (resp[0] != 'c'); -} - -/* g := |g1| */ -static void gabs(giant g) -{ - if(g->sign < 0) { - g->sign = -g->sign; - } -} - -/* - * Individual tests. API is identical for all tests. - * - * g1, g2 : giants with random data, size, and sign. Tests do not modify - * these. - * scr1, scr2 : scratch giants, big enough for all conceivable ops. Can - * be modified at will. - * Return : 0 for sucess, 1 on error. - */ - -static int compTest(giant g1, giant g2, giant scr1, giant scr2) -{ - gtog(g1, scr1); // scr1 := g1 - gtog(scr1, scr2); - if(gcompg(g1, scr2)) { - printf("gtog/gcompg error\n"); - return testError(); - } - return 0; -} - -static int addSubTest(giant g1, giant g2, giant scr1, giant scr2) -{ - gtog(g1, scr1); // scr1 := g1 - addg(g2, scr1); // scr1 := g1 + g2 - subg(g1, scr1); // scr1 := g1 + g2 - g1 =? g2 - if(gcompg(g2, scr1)) { - printf("addg/subg error\n"); - return testError(); - } - return 0; -} - -#define LARGEST_MUL 0xffff - -static int mulTest(giant g1, giant g2, giant scr1, giant scr2) -{ - int randInt = genRand(1, LARGEST_MUL); - int i; - int rtn = 0; - - int_to_giant(randInt, scr1); // scr1 := randInt - gtog(g1, scr2); // scr2 := g1 - mulg(scr1, scr2); // scr2 := g1 * randInt - - /* now do the same thing with multiple adds */ - int_to_giant(0, scr1); // scr1 := 0 - for(i=0; icapacity - abs(g1->sign) - 1) * - GIANT_BITS_PER_DIGIT; - int shiftCnt = genRand(1, maxShift); - giant scr3 = borrowGiant(scr1->capacity); - int rtn = 0; - - gtog(g1, scr1); // scr1 := g1 - gshiftleft(shiftCnt, scr1); // scr1 := (g1 << shiftCnt) - - gtog(g1, scr2); // scr2 := g1 - if(shiftCnt <= 30) { - int multInt = (1 << shiftCnt); - int_to_giant(multInt, scr3); // scr3 := (1 << shiftCnt) - } - else { - int_to_giant(1, scr3); // scr3 := 1; - gshiftleft(shiftCnt, scr3); // scr3 := (1 << shiftCnt) - } - mulg(scr3, scr2); // scr2 := g1 * (1 << shiftCnt); - if(gcompg(scr1, scr2)) { - printf("shiftCnt %d 0x%x\n", shiftCnt, shiftCnt); - printf("g1 : "); printGiantHex(g1); - printf("scr1 : "); printGiantHex(scr1); - printf("scr2 : "); printGiantHex(scr2); - printf("gshiftleft error\n"); - rtn = testError(); - } - returnGiant(scr3); - return rtn; -} - -static int rshiftTest(giant g1, giant g2, giant scr1, giant scr2) -{ - int maxShift = bitlen(g1) - 1; - int shiftCnt; - giant scr3 = borrowGiant(scr1->capacity); - int rtn = 0; - - /* special case, can't have g1 = 1 */ - if(maxShift == 0) { - #if FEE_DEBUG - printf("...rshiftTest: tweaking g1 = 1\n"); - #endif - g1->n[0] = 2; - shiftCnt = 1; - } - else { - shiftCnt = genRand(1, maxShift); - } - gtog(g1, scr1); // scr1 := g1 - gabs(scr1); // scr1 := |g1| - gtog(scr1, scr2); // scr2 := |g1| - gshiftright(shiftCnt, scr1); // scr1 := (|g1| >> shiftCnt) - - if(shiftCnt <= 30) { - int multInt = (1 << shiftCnt); - int_to_giant(multInt, scr3); // scr3 := (1 << shiftCnt) - } - else { - int_to_giant(1, scr3); // scr3 := 1; - gshiftleft(shiftCnt, scr3); // scr3 := (1 << shiftCnt) - } - divg(scr3, scr2); // scr2 := g1 / (1 << shiftCnt); - if(gcompg(scr1, scr2)) { - printf("shiftCnt %d 0x%x\n", shiftCnt, shiftCnt); - printf("g1 : "); printGiantHex(g1); - printf("scr1 : "); printGiantHex(scr1); - printf("scr2 : "); printGiantHex(scr2); - printf("gshiftright error\n"); - rtn = testError(); - } - returnGiant(scr3); - return rtn; -} - -static int divTest(giant g1, giant g2, giant scr1, giant scr2) -{ - gtog(g1, scr1); // scr1 := g1 - mulg(g2, scr1); // scr1 := g1 * g2 - gtog(g2, scr2); // scr2 := g2 - gabs(scr2); // scr2 := |g2| - divg(scr2, scr1); // scr1 := (g1 * g2) / |g2| - - /* weird case - if g2 is negative, this result is -g1! */ - if(g2->sign < 0) { - scr1->sign = -scr1->sign; - } - if(gcompg(scr1, g1)) { - printf("g1 : "); printGiantHex(g1); - printf("g2 : "); printGiantHex(g1); - printf("scr1 : "); printGiantHex(scr1); - printf("divTest error\n"); - return testError(); - } - return 0; -} - -#define LARGEST_MOD_MUL 0x40 - -static int modTest(giant g1, giant g2, giant scr1, giant scr2) -{ - int randInt = genRand(1, LARGEST_MOD_MUL); - giant scr3 = borrowGiant(scr1->capacity); - /* debug only */ - giant scr4 = borrowGiant(scr1->capacity); - /* end debug */ - int rtn = 0; - - int_to_giant(randInt, scr1); // scr1 := rand - gtog(g1, scr2); - gabs(scr2); // scr2 := |g1| - - /* current modg can't deal with g mod 1 ! */ - if((scr2->sign == 1) && (scr2->n[0] == 1)) { - #if MODG1_TEST_ENABLE - /* assume that this is legal... */ - #if FEE_DEBUG - printf("..modTest: g1 = 1, no tweak\n"); - #endif - #else - printf("..modTest: tweaking g1 = 1\n"); - scr2->n[0] = 0x54; - #endif MODG1_TEST_ENABLE - } - /* end modg workaround */ - - gtog(g2, scr3); - gabs(scr3); // scr3 := |g2| - - /* this will only work if randInt < |g1| */ - if(gcompg(scr1, scr2) >= 0) { - #if FEE_DEBUG - printf("..modTest: tweaking rand, > g1 = "); printGiantHex(g1); - printf(" g2 = "); printGiantHex(g2); - printf(" rand = "); printGiantHex(scr1); - #endif - modg(scr2, scr1); // scr1 := rand mod g1 - if(gcompg(scr1, scr2) >= 0) { - printf("simple modg error\n"); - return testError(); - } - } - - mulg(scr2, scr3); // scr3 := |g1 * g2| - addg(scr1, scr3); // scr3 := (|g1 * g2|) + rand - gtog(scr3, scr4); - modg(scr2, scr3); // scr3 := scr3 mod |g1| =? rand - if(gcompg(scr1, scr3)) { - printf("g1 : "); printGiantHex(g1); - printf("g2 : "); printGiantHex(g2); - printf("rand : 0x%x\n", randInt); - printf("randG : "); printGiantHex(scr1); - printf("scr4 : "); printGiantHex(scr4); - printf("mod : "); printGiantHex(scr3); - printf("modTest error\n"); - rtn = testError(); - } - returnGiant(scr3); - returnGiant(scr4); - return rtn; - - -} - -#if MODG1_TEST_ENABLE -/* quickie test to demonstrate failure of modg(1, g). Known failure - * as of 10 Apr 1998. - * modg(1,g) fixed on 13 Apr 1998, so this should now work. - */ -static int modg1Test(giant g1, giant scr1, giant scr2) -{ - /* test mod(x, 1) */ - scr1->n[0] = 1; - scr1->sign = 1; - gtog(g1, scr2); - modg(scr1, scr2); - if(!isZero(scr2)) { - printf("g1 : "); printGiantHex(g1); - printf("g1 mod 1 : "); printGiantHex(scr2); - return testError(); - } - return 0; -} -#endif MODG1_TEST_ENABLE - -static int mulOnesTest(giant g1, giant g2, giant scr1, giant scr2) -{ - int i; - int rtn = 0; - giant gOnes = borrowGiant(scr1->capacity); - - /* set up a giant with all ones data */ - gOnes->sign = abs(g1->sign); - for(i=0; isign; i++) { - gOnes->n[i] = (giantDigit)(-1); - } - - gtog(gOnes, scr1); // scr1 := gOnes - mulg(g1, scr1); // scr1 := gOnes * g1 - - gtog(g1, scr2); - mulg(gOnes, scr2); - - if(gcompg(scr1, scr2)) { - printf("good prod : "); printGiantHex(scr1); - printf("bad prod : "); printGiantHex(scr2); - printf("mulOnesTest error\n"); - rtn = testError(); - } - return rtn; - -} - -int main(int argc, char **argv) -{ - int arg; - char *argp; - giant g1; // init'd randomly - giant g2; // ditto - giant scr1; // scratch - giant scr2; // ditto - unsigned char *buf; - int loop; - - int loops = LOOPS_DEF; - int seedSpec = 0; - unsigned seed = 0; - unsigned maxSize = MAX_SIZE_DEF; - - initCryptKit(); - - #ifdef macintosh - seedSpec = 1; - seed = 0; - argc = 1; - maxSize = 8; - #endif - - for(arg=1; arg -#include -#include - -#define SIGN_LOOPS_DEF 100 -#define VFY_LOOPS_DEF 100 -#define PRIV_KEY_SIZE_BYTES 32 -#define DIGEST_SIZE_BYTES 20 /* e.g., SHA1 */ -#define NUM_KEYS 10 - -static void usage(char **argv) -{ - printf("Usage: %s [option...]\n", argv[0]); - printf("Options:\n"); - printf(" s=signLoops -- default %d\n", SIGN_LOOPS_DEF); - printf(" v=verifyLoops -- default %d\n", VFY_LOOPS_DEF); - printf(" D=depth -- default is ALL\n"); - exit(1); -} - -typedef struct { - unsigned char *data; - unsigned length; -} FeeData; - -/* - * Fill numDatas with random data of length bits. Caller has mallocd referents. - */ -static void genRandData(FeeData *datas, - unsigned numDatas, - unsigned numBytes, - feeRand rand) -{ - unsigned i; - FeeData *fd; - for(i=0; ilength = numBytes; - feeRandBytes(rand, fd->data, numBytes); - } - return; -} - -static void mallocData( - FeeData *fd, - unsigned numBytes) -{ - fd->data = (unsigned char *)fmalloc(numBytes); - fd->length = numBytes; -} - -/* common random callback */ -feeReturn randCallback( - void *ref, - unsigned char *bytes, - unsigned numBytes) -{ - feeRand frand = (feeRand)ref; - feeRandBytes(frand, bytes, numBytes); - return FR_Success; -} - -int main(int argc, char **argv) -{ - int arg; - char *argp; - unsigned sigLoops = SIGN_LOOPS_DEF; - unsigned vfyLoops = VFY_LOOPS_DEF; - unsigned numKeys = NUM_KEYS; // might be less for very small loops - unsigned depth; - feeRand rand; - - feePubKey keys[NUM_KEYS]; - /* sigLoops copies of each of {digestData, sigData} */ - FeeData *digestData; - FeeData *sigData; - - unsigned seed; - unsigned i; - PLAT_TIME startTime; - PLAT_TIME endTime; - double elapsed; - curveParams *cp; - unsigned minDepth = 0; - unsigned maxDepth = FEE_DEPTH_MAX; - unsigned basePrimeLen; - char *curveType; - feeReturn frtn; - - for(arg=1; arg sigLoops) { - numKeys = sigLoops; - } - digestData = (FeeData *)fmalloc(sizeof(FeeData) * sigLoops); - sigData = (FeeData *)fmalloc(sizeof(FeeData) * sigLoops); - - /* alloc the data, once, for largest private key or "digest" we'll use */ - for(i=0; icurveType) { - case FCT_Montgomery: - curveType = "FCT_Montgomery"; - break; - case FCT_Weierstrass: - curveType = "FCT_Weierstrass"; - break; - case FCT_General: - curveType = "FCT_General"; - break; - default: - printf("***Unknown curveType!\n"); - exit(1); - } - - switch(cp->primeType) { - case FPT_General: - printf("depth=%d; FPT_General, %s; keysize=%d;\n", - depth, curveType, bitlen(cp->basePrime)); - break; - case FPT_Mersenne: - printf("depth=%d; FPT_Mersenne, %s; q=%d\n", - depth, curveType, cp->q); - break; - default: - printf("depth=%d; FPT_FEE, %s; q=%d k=%d\n", - depth, curveType, cp->q, cp->k); - break; - } - basePrimeLen = bitlen(cp->basePrime); - - /* one set of random data as private keys */ - unsigned privSize = (basePrimeLen + 8) / 8; - genRandData(digestData, numKeys, privSize, rand); - - /* generate the keys (no hash - we've got that covered) */ - for(i=0; idata, digst->length, fkey); - if(frtn) { - printf("***Error %d on feeSigSign\n", (int)frtn); - break; - } - frtn = feeSigData(fs, &sig->data, &sig->length); - if(frtn) { - printf("***Error %d on feeSigData\n", (int)frtn); - break; - } - feeSigFree(fs); - } - PLAT_GET_TIME(endTime); - elapsed = PLAT_GET_US(startTime, endTime); - printf(" sign: %12.2f us per op\n", - elapsed / sigLoops); - - /* - * verify - might be doing more of these than we have - * valid signatures..... - */ - unsigned dex=0; - PLAT_GET_TIME(startTime); - for(i=0; idata, sig->length, &fs); - if(frtn) { - printf("***Error %d on feeSigParse\n", (int)frtn); - break; - } - frtn = feeSigVerify(fs, digst->data, digst->length, fkey); - if(frtn) { - printf("***Error %d on feeSigVerify\n", (int)frtn); - break; - } - feeSigFree(fs); - dex++; - if(dex == sigLoops) { - /* that's all the data we have, recycle */ - dex = 0; - } - } - PLAT_GET_TIME(endTime); - elapsed = PLAT_GET_US(startTime, endTime); - printf(" verify: %12.2f us per op\n", - elapsed / vfyLoops); - - freeCurveParams(cp); - /* possibly limited number of signatures.... */ - for(i=0; i - -/* - * These functions are only called from feeCipherFile.c. - */ -feeReturn createRandDES(feePubKey sendPrivKey, // for sig only - feePubKey recvPubKey, - const unsigned char *plainText, - unsigned plainTextLen, - int genSig, // 1 ==> generate signature - unsigned userData, // for caller's convenience - feeCipherFile *cipherFile) // RETURNED if successful -{ - feeRand frand = NULL; - feeReturn frtn; - unsigned char desKey[FEE_DES_MIN_STATE_SIZE]; - unsigned char *encrDesKey = NULL; // FEED encrypted desKey - unsigned encrDesKeyLen; - feeDES des = NULL; - feeFEEDExp feed = NULL; - unsigned char *cipherText = NULL; - unsigned cipherTextLen; - unsigned char *sigData = NULL; - unsigned sigDataLen = 0; - feeCipherFile cfile = NULL; - unsigned char *pubKeyString = NULL; // of sendPrivKey - unsigned pubKeyStringLen = 0; - - if(recvPubKey == NULL) { - return FR_BadPubKey; - } - - /* - * Cons up random DES key and a feeDES object with it - */ - frand = feeRandAlloc(); - if(frand == NULL) { - frtn = FR_Internal; - goto out; - } - feeRandBytes(frand, desKey, FEE_DES_MIN_STATE_SIZE); - des = feeDESNewWithState(desKey, FEE_DES_MIN_STATE_SIZE); - if(des == NULL) { - frtn = FR_Internal; - goto out; - } - - /* - * Encrypt the DES key via FEEDExp - */ - feed = feeFEEDExpNewWithPubKey(recvPubKey, NULL, NULL); - if(feed == NULL) { - frtn = FR_BadPubKey; - goto out; - } - frtn = feeFEEDExpEncrypt(feed, - desKey, - FEE_DES_MIN_STATE_SIZE, - &encrDesKey, - &encrDesKeyLen); - if(frtn) { - goto out; - } - - /* - * Encrypt the plaintext via DES - */ - frtn = feeDESEncrypt(des, - plainText, - plainTextLen, - &cipherText, - &cipherTextLen); - if(frtn) { - goto out; - } - - if(genSig) { - /* - * We generate signature on ciphertext by convention. - */ - if(sendPrivKey == NULL) { - frtn = FR_BadPubKey; - goto out; - } - frtn = feePubKeyCreateSignature(sendPrivKey, - cipherText, - cipherTextLen, - &sigData, - &sigDataLen); - if(frtn) { - goto out; - } - /* - * Sender's public key string - */ - frtn = feePubKeyCreateKeyString(sendPrivKey, - (char **)&pubKeyString, - &pubKeyStringLen); - if(frtn) { - /* - * Huh? - */ - frtn = FR_BadPubKey; - goto out; - } - } - - /* - * Cons up a cipherfile - */ - cfile = feeCFileNewFromCipherText(CFE_RandDES, - cipherText, - cipherTextLen, - pubKeyString, - pubKeyStringLen, - encrDesKey, - encrDesKeyLen, - sigData, - sigDataLen, - userData); - if(cfile == NULL) { - frtn = FR_Internal; - goto out; - } - -out: - /* free alloc'd stuff */ - - if(cipherText) { - ffree(cipherText); - } - if(feed) { - feeFEEDExpFree(feed); - } - if(frand) { - feeRandFree(frand); - } - if(des) { - feeDESFree(des); - } - if(sigData) { - ffree(sigData); - } - if(encrDesKey) { - ffree(encrDesKey); - } - if(pubKeyString) { - ffree(pubKeyString); - } - memset(desKey, 0, FEE_DES_MIN_STATE_SIZE); - *cipherFile = cfile; - return frtn; - -} - -feeReturn decryptRandDES(feeCipherFile cipherFile, - feePubKey recvPrivKey, - feePubKey sendPubKey, // optional - unsigned char **plainText, // RETURNED - unsigned *plainTextLen, // RETURNED - feeSigStatus *sigStatus) // RETURNED -{ - feeReturn frtn = FR_Success; - unsigned char *cipherText = NULL; - unsigned cipherTextLen; - feeFEEDExp feed = NULL; // to decrypt desKey - feeDES des = NULL; // to decrypt cipherText - unsigned char *desKey; - unsigned desKeyLen; - unsigned char *encrDesKey = NULL; // FEED encrypted desKey - unsigned encrDesKeyLen; - unsigned char *sigData = NULL; - unsigned sigDataLen; - unsigned char *sendPubKeyStr = NULL; - unsigned sendPubKeyStrLen = 0; - feePubKey parsedSendPubKey = NULL; - - if(feeCFileEncrType(cipherFile) != CFE_RandDES) { - frtn = FR_Internal; - goto out; - } - - /* - * Get ciphertext and encrypted DES key from cipherFile - */ - cipherText = feeCFileCipherText(cipherFile, &cipherTextLen); - if(cipherText == NULL) { - frtn = FR_BadCipherFile; - goto out; - } - encrDesKey = feeCFileOtherKeyData(cipherFile, &encrDesKeyLen); - if(encrDesKey == NULL) { - frtn = FR_BadCipherFile; - goto out; - } - - /* - * FEED decrypt to get DES key - */ - feed = feeFEEDExpNewWithPubKey(recvPrivKey, NULL, NULL); - if(feed == NULL) { - frtn = FR_BadPubKey; - goto out; - } - frtn = feeFEEDExpDecrypt(feed, - encrDesKey, - encrDesKeyLen, - &desKey, - &desKeyLen); - if(frtn) { - goto out; - } - - /* - * Now DES decrypt the ciphertext - */ - if(desKeyLen != FEE_DES_MIN_STATE_SIZE) { - frtn = FR_BadCipherFile; - goto out; - } - des = feeDESNewWithState(desKey, desKeyLen); - if(des == NULL) { - frtn = FR_Internal; - goto out; - } - frtn = feeDESDecrypt(des, - cipherText, - cipherTextLen, - plainText, - plainTextLen); - if(frtn) { - goto out; - } - - sigData = feeCFileSigData(cipherFile, &sigDataLen); - if(sigData) { - feeReturn sigFrtn; - - if(sendPubKey == NULL) { - /* - * Obtain sender's public key from cipherfile - */ - sendPubKeyStr = feeCFileSendPubKeyData(cipherFile, - &sendPubKeyStrLen); - if(sendPubKeyStr == NULL) { - /* - * Hmm..shouldn't really happen, but let's - * press on. - */ - *sigStatus = SS_PresentNoKey; - goto out; - } - parsedSendPubKey = feePubKeyAlloc(); - frtn = feePubKeyInitFromKeyString(parsedSendPubKey, - (char *)sendPubKeyStr, sendPubKeyStrLen); - if(frtn) { - dbgLog(("parseRandDES: bad sendPubKeyStr\n")); - *sigStatus = SS_PresentNoKey; - goto out; - } - sendPubKey = parsedSendPubKey; - } - sigFrtn = feePubKeyVerifySignature(sendPubKey, - cipherText, - cipherTextLen, - sigData, - sigDataLen); - switch(sigFrtn) { - case FR_Success: - *sigStatus = SS_PresentValid; - break; - default: - *sigStatus = SS_PresentInvalid; - break; - } - } - else { - *sigStatus = SS_NotPresent; - } -out: - if(cipherText) { - ffree(cipherText); - } - if(feed) { - feeFEEDExpFree(feed); - } - if(des) { - feeDESFree(des); - } - if(desKey) { - memset(desKey, 0, desKeyLen); - ffree(desKey); - } - if(encrDesKey) { - ffree(encrDesKey); - } - if(sigData) { - ffree(sigData); - } - if(parsedSendPubKey) { - feePubKeyFree(parsedSendPubKey); - } - if(sendPubKeyStr) { - ffree(sendPubKeyStr); - } - return frtn; -} - -feeReturn createPubDES(feePubKey sendPrivKey, // required - feePubKey recvPubKey, - const unsigned char *plainText, - unsigned plainTextLen, - int genSig, // 1 ==> generate signature - unsigned userData, // for caller's convenience - feeCipherFile *cipherFile) // RETURNED if successful -{ - feeRand frand = NULL; - feeReturn frtn; - unsigned char *desKey; - unsigned desKeyLen; - feeDES des = NULL; - unsigned char *cipherText = NULL; - unsigned cipherTextLen; - unsigned char *sigData = NULL; - unsigned sigDataLen = 0; - feeCipherFile cfile = NULL; - unsigned char *pubKeyString = NULL; - unsigned pubKeyStringLen; - - if((sendPrivKey == NULL) || (recvPubKey == NULL)) { - return FR_BadPubKey; - } - - /* - * Get the public string version of sendPrivKey for embedding in - * cipherfile - */ - frtn = feePubKeyCreateKeyString(sendPrivKey, - (char **)&pubKeyString, - &pubKeyStringLen); - if(frtn) { - goto out; - } - - /* - * Obtain DES key via key exchange and get a feeDES object with it - */ - frtn = feePubKeyCreatePad(sendPrivKey, - recvPubKey, - &desKey, - &desKeyLen); - if(frtn) { - goto out; - } - des = feeDESNewWithState(desKey, desKeyLen); - if(des == NULL) { - frtn = FR_Internal; - goto out; - } - - /* - * Encrypt the plaintext via DES - */ - frtn = feeDESEncrypt(des, - plainText, - plainTextLen, - &cipherText, - &cipherTextLen); - if(frtn) { - goto out; - } - - if(genSig) { - /* - * We generate signature on ciphertext by convention. - */ - frtn = feePubKeyCreateSignature(sendPrivKey, - cipherText, - cipherTextLen, - &sigData, - &sigDataLen); - if(frtn) { - goto out; - } - } - - /* - * Cons up a cipherfile - */ - cfile = feeCFileNewFromCipherText(CFE_PublicDES, - cipherText, - cipherTextLen, - pubKeyString, - pubKeyStringLen, - NULL, // otherKey - 0, - sigData, - sigDataLen, - userData); - if(cfile == NULL) { - frtn = FR_Internal; - goto out; - } - -out: - /* free alloc'd stuff */ - - if(cipherText) { - ffree(cipherText); - } - if(frand) { - feeRandFree(frand); - } - if(des) { - feeDESFree(des); - } - if(desKey) { - ffree(desKey); - } - if(sigData) { - ffree(sigData); - } - if(pubKeyString) { - ffree(pubKeyString); - } - *cipherFile = cfile; - return frtn; - -} - -feeReturn decryptPubDES(feeCipherFile cipherFile, - feePubKey recvPrivKey, - feePubKey sendPubKey, - unsigned char **plainText, // RETURNED - unsigned *plainTextLen, // RETURNED - feeSigStatus *sigStatus) // RETURNED -{ - feeReturn frtn = FR_Success; - unsigned char *cipherText = NULL; - unsigned cipherTextLen; - feeDES des = NULL; // to decrypt cipherText - unsigned char *desKey; - unsigned desKeyLen; - unsigned char *sigData = NULL; - unsigned sigDataLen; - unsigned char *pubKeyString = NULL; - unsigned pubKeyStringLen; - feePubKey decryptPubKey = NULL; // from cipherfile - - if(feeCFileEncrType(cipherFile) != CFE_PublicDES) { - frtn = FR_Internal; - goto out; - } - - /* - * Get ciphertext and sender's public key from cipherFile - */ - cipherText = feeCFileCipherText(cipherFile, &cipherTextLen); - if(cipherText == NULL) { - frtn = FR_BadCipherFile; - goto out; - } - pubKeyString = feeCFileSendPubKeyData(cipherFile, &pubKeyStringLen); - if(pubKeyString == NULL) { - frtn = FR_BadCipherFile; - goto out; - } - decryptPubKey = feePubKeyAlloc(); - frtn = feePubKeyInitFromKeyString(decryptPubKey, - (char *)pubKeyString, - pubKeyStringLen); - if(frtn) { - goto out; - } - - /* - * key exchange to get DES key - */ - frtn = feePubKeyCreatePad(recvPrivKey, - decryptPubKey, - &desKey, - &desKeyLen); - if(frtn) { - goto out; - } - - /* - * Now DES decrypt the ciphertext - */ - if(desKeyLen < FEE_DES_MIN_STATE_SIZE) { - frtn = FR_BadCipherFile; - goto out; - } - des = feeDESNewWithState(desKey, desKeyLen); - if(des == NULL) { - frtn = FR_Internal; - goto out; - } - frtn = feeDESDecrypt(des, - cipherText, - cipherTextLen, - plainText, - plainTextLen); - if(frtn) { - goto out; - } - - sigData = feeCFileSigData(cipherFile, &sigDataLen); - if(sigData) { - feeReturn sigFrtn; - - if(sendPubKey == NULL) { - /* - * Use key embedded in cipherfile - */ - sendPubKey = decryptPubKey; - } - sigFrtn = feePubKeyVerifySignature(sendPubKey, - cipherText, - cipherTextLen, - sigData, - sigDataLen); - switch(sigFrtn) { - case FR_Success: - *sigStatus = SS_PresentValid; - break; - default: - *sigStatus = SS_PresentInvalid; - break; - } - } - else { - *sigStatus = SS_NotPresent; - } -out: - if(cipherText) { - ffree(cipherText); - } - if(des) { - feeDESFree(des); - } - if(desKey) { - ffree(desKey); - } - if(pubKeyString) { - ffree(pubKeyString); - } - if(sigData) { - ffree(sigData); - } - if(decryptPubKey) { - feePubKeyFree(decryptPubKey); - } - return frtn; -} - -#endif /* CRYPTKIT_CIPHERFILE_ENABLE */ - diff --git a/OSX/libsecurity_cryptkit/lib/CipherFileDES.h b/OSX/libsecurity_cryptkit/lib/CipherFileDES.h deleted file mode 100644 index 781398883..000000000 --- a/OSX/libsecurity_cryptkit/lib/CipherFileDES.h +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * CipherFileDES.h - DES-related cipherfile support - * - * Revision History - * ---------------- - * 18 Feb 97 at Apple - * Created. - */ - -#ifndef _CK_CFILEDES_H_ -#define _CK_CFILEDES_H_ - -#include "ckconfig.h" - -#if CRYPTKIT_CIPHERFILE_ENABLE - -#include "Crypt.h" -#include "feeCipherFile.h" -#include "CipherFileTypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -feeReturn createRandDES(feePubKey sendPrivKey, - feePubKey recvPubKey, - const unsigned char *plainText, - unsigned plainTextLen, - int genSig, // 1 ==> generate signature - unsigned userData, // for caller's convenience - feeCipherFile *cipherFile); // RETURNED if successful -feeReturn decryptRandDES(feeCipherFile cipherFile, - feePubKey recvPrivKey, - feePubKey sendPubKey, - unsigned char **plainText, // RETURNED - unsigned *plainTextLen, // RETURNED - feeSigStatus *sigStatus); // RETURNED -feeReturn createPubDES(feePubKey sendPrivKey, // required - feePubKey recvPubKey, // required - const unsigned char *plainText, - unsigned plainTextLen, - int genSig, // 1 ==> generate signature - unsigned userData, // for caller's convenience - feeCipherFile *cipherFile); // RETURNED if successful -feeReturn decryptPubDES(feeCipherFile cipherFile, - feePubKey recvPrivKey, - feePubKey sendPubKey, // optional - unsigned char **plainText, // RETURNED - unsigned *plainTextLen, // RETURNED - feeSigStatus *sigStatus); // RETURNED - -#ifdef __cplusplus -} -#endif - -#endif /* CRYPTKIT_CIPHERFILE_ENABLE*/ - -#endif /*_CK_CFILEDES_H_*/ diff --git a/OSX/libsecurity_cryptkit/lib/CipherFileFEED.c b/OSX/libsecurity_cryptkit/lib/CipherFileFEED.c deleted file mode 100644 index ce9e075ad..000000000 --- a/OSX/libsecurity_cryptkit/lib/CipherFileFEED.c +++ /dev/null @@ -1,460 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * CipherFileFEED.c - FEED and FEEDExp related cipherfile support - * - * Revision History - * ---------------- - * 24 Jun 97 at Apple - * Fixed memory leaks via sigData - * 18 Feb 97 at Apple - * Split off from feeCipherFile.c - */ - -#include "ckconfig.h" - -#if CRYPTKIT_CIPHERFILE_ENABLE - -#include "Crypt.h" -#include "CipherFileFEED.h" -#include "falloc.h" -#include "feeDebug.h" - -feeReturn createFEED(feePubKey sendPrivKey, // required - feePubKey recvPubKey, - const unsigned char *plainText, - unsigned plainTextLen, - int genSig, // 1 ==> generate signature - unsigned userData, // for caller's convenience - feeCipherFile *cipherFile) // RETURNED if successful -{ - feeReturn frtn; - feeFEED feed = NULL; - unsigned char *cipherText = NULL; - unsigned cipherTextLen; - unsigned char *sigData = NULL; - unsigned sigDataLen = 0; - feeCipherFile cfile = NULL; - unsigned char *pubKeyString = NULL; // of sendPrivKey - unsigned pubKeyStringLen = 0; - - if((sendPrivKey == NULL) || (recvPubKey == NULL)) { - return FR_BadPubKey; - } - - /* - * FEED encrypt plaintext - */ - feed = feeFEEDNewWithPubKey(sendPrivKey, recvPubKey, FF_ENCRYPT, NULL, NULL); - if(feed == NULL) { - frtn = FR_BadPubKey; - goto out; - } - frtn = feeFEEDEncrypt(feed, - plainText, - plainTextLen, - &cipherText, - &cipherTextLen); - if(frtn) { - goto out; - } - - /* - * Sender's public key string - */ - frtn = feePubKeyCreateKeyString(sendPrivKey, - (char **)&pubKeyString, - &pubKeyStringLen); - if(frtn) { - /* - * Huh? - */ - frtn = FR_BadPubKey; - goto out; - } - - if(genSig) { - /* - * We generate signature on ciphertext by convention. - */ - frtn = feePubKeyCreateSignature(sendPrivKey, - cipherText, - cipherTextLen, - &sigData, - &sigDataLen); - if(frtn) { - goto out; - } - } - - /* - * Cons up a cipherfile - */ - cfile = feeCFileNewFromCipherText(CFE_FEED, - cipherText, - cipherTextLen, - pubKeyString, - pubKeyStringLen, - NULL, - 0, - sigData, - sigDataLen, - userData); - if(cfile == NULL) { - frtn = FR_Internal; - goto out; - } - -out: - /* free alloc'd stuff */ - - if(cipherText) { - ffree(cipherText); - } - if(feed) { - feeFEEDFree(feed); - } - if(pubKeyString) { - ffree(pubKeyString); - } - if(sigData) { - ffree(sigData); - } - *cipherFile = cfile; - return frtn; - -} - -feeReturn decryptFEED(feeCipherFile cipherFile, - feePubKey recvPrivKey, - feePubKey sendPubKey, // optional - unsigned char **plainText, // RETURNED - unsigned *plainTextLen, // RETURNED - feeSigStatus *sigStatus) // RETURNED -{ - feeReturn frtn = FR_Success; - unsigned char *cipherText = NULL; - unsigned cipherTextLen; - feeFEED feed = NULL; - unsigned char *sigData = NULL; - unsigned sigDataLen; - unsigned char *sendPubKeyStr = NULL; - unsigned sendPubKeyStrLen = 0; - feePubKey parsedSendPubKey = NULL; - - if(feeCFileEncrType(cipherFile) != CFE_FEED) { - frtn = FR_Internal; - goto out; - } -//printf("decryptFEED\n"); -//printf("privKey:\n"); printPubKey(recvPrivKey); -//printf("pubKey:\n"); printPubKey(sendPubKey); - /* - * Get ciphertext and sender's public key from cipherFile - */ - cipherText = feeCFileCipherText(cipherFile, &cipherTextLen); - if(cipherText == NULL) { - frtn = FR_BadCipherFile; - goto out; - } - sendPubKeyStr = feeCFileSendPubKeyData(cipherFile, &sendPubKeyStrLen); - if(sendPubKeyStr == NULL) { - frtn = FR_BadCipherFile; - goto out; - } - parsedSendPubKey = feePubKeyAlloc(); - frtn = feePubKeyInitFromKeyString(parsedSendPubKey, - (char *)sendPubKeyStr, - sendPubKeyStrLen); - if(frtn) { - frtn = FR_BadCipherFile; - goto out; - } -//printf("parsedSendPubKey:\n"); printPubKey(parsedSendPubKey); - - /* - * FEED decrypt - */ - feed = feeFEEDNewWithPubKey(recvPrivKey, parsedSendPubKey, FF_DECRYPT, NULL, NULL); - if(feed == NULL) { - frtn = FR_BadPubKey; - goto out; - } - frtn = feeFEEDDecrypt(feed, - cipherText, - cipherTextLen, - plainText, - plainTextLen); - if(frtn) { - goto out; - } - - sigData = feeCFileSigData(cipherFile, &sigDataLen); - if(sigData) { - feeReturn sigFrtn; - - if(sendPubKey == NULL) { - /* - * use embedded sender's public key - */ - sendPubKey = parsedSendPubKey; - } - sigFrtn = feePubKeyVerifySignature(sendPubKey, - cipherText, - cipherTextLen, - sigData, - sigDataLen); - switch(sigFrtn) { - case FR_Success: - *sigStatus = SS_PresentValid; - break; - default: - *sigStatus = SS_PresentInvalid; - break; - } - } - else { - *sigStatus = SS_NotPresent; - } -out: - if(cipherText) { - ffree(cipherText); - } - if(feed) { - feeFEEDFree(feed); - } - if(sigData) { - ffree(sigData); - } - if(parsedSendPubKey) { - feePubKeyFree(parsedSendPubKey); - } - if(sendPubKeyStr) { - ffree(sendPubKeyStr); - } - return frtn; -} - -feeReturn createFEEDExp(feePubKey sendPrivKey, // for sig only - feePubKey recvPubKey, - const unsigned char *plainText, - unsigned plainTextLen, - int genSig, // 1 ==> generate signature - unsigned userData, // for caller's convenience - feeCipherFile *cipherFile) // RETURNED if successful -{ - feeReturn frtn; - feeFEEDExp feed = NULL; - unsigned char *cipherText = NULL; - unsigned cipherTextLen; - unsigned char *sigData = NULL; - unsigned sigDataLen = 0; - feeCipherFile cfile = NULL; - unsigned char *pubKeyString = NULL; // of sendPrivKey, for sig - unsigned pubKeyStringLen = 0; - - if(recvPubKey == NULL) { - return FR_BadPubKey; - } - - /* - * FEEDExp encrypt plaintext - */ - feed = feeFEEDExpNewWithPubKey(recvPubKey, NULL, NULL); - if(feed == NULL) { - frtn = FR_BadPubKey; - goto out; - } - frtn = feeFEEDExpEncrypt(feed, - plainText, - plainTextLen, - &cipherText, - &cipherTextLen); - if(frtn) { - goto out; - } - - if(genSig) { - if(sendPrivKey == NULL) { - frtn = FR_IllegalArg; - goto out; - } - /* - * We generate signature on ciphertext by convention. - */ - frtn = feePubKeyCreateSignature(sendPrivKey, - cipherText, - cipherTextLen, - &sigData, - &sigDataLen); - if(frtn) { - goto out; - } - /* - * Sender's public key string - */ - frtn = feePubKeyCreateKeyString(sendPrivKey, - (char **)&pubKeyString, - &pubKeyStringLen); - if(frtn) { - /* - * Huh? - */ - frtn = FR_BadPubKey; - goto out; - } - } - - /* - * Cons up a cipherfile - */ - cfile = feeCFileNewFromCipherText(CFE_FEEDExp, - cipherText, - cipherTextLen, - pubKeyString, - pubKeyStringLen, - NULL, - 0, - sigData, - sigDataLen, - userData); - if(cfile == NULL) { - frtn = FR_Internal; - goto out; - } - -out: - /* free alloc'd stuff */ - - if(cipherText) { - ffree(cipherText); - } - if(feed) { - feeFEEDExpFree(feed); - } - if(sigData) { - ffree(sigData); - } - if(pubKeyString) { - ffree(pubKeyString); - } - *cipherFile = cfile; - return frtn; - -} - -feeReturn decryptFEEDExp(feeCipherFile cipherFile, - feePubKey recvPrivKey, - feePubKey sendPubKey, // optional - unsigned char **plainText, // RETURNED - unsigned *plainTextLen, // RETURNED - feeSigStatus *sigStatus) // RETURNED -{ - feeReturn frtn = FR_Success; - unsigned char *cipherText = NULL; - unsigned cipherTextLen; - feeFEEDExp feed = NULL; - unsigned char *sigData = NULL; - unsigned sigDataLen; - unsigned char *sendPubKeyStr = NULL; - unsigned sendPubKeyStrLen = 0; - feePubKey parsedSendPubKey = NULL; - - if(feeCFileEncrType(cipherFile) != CFE_FEEDExp) { - frtn = FR_Internal; - goto out; - } - - /* - * Get ciphertext from cipherFile - */ - cipherText = feeCFileCipherText(cipherFile, &cipherTextLen); - if(cipherText == NULL) { - frtn = FR_BadCipherFile; - goto out; - } - - /* - * FEEDExp decrypt - */ - feed = feeFEEDExpNewWithPubKey(recvPrivKey, NULL, NULL); - if(feed == NULL) { - frtn = FR_BadPubKey; - goto out; - } - frtn = feeFEEDExpDecrypt(feed, - cipherText, - cipherTextLen, - plainText, - plainTextLen); - if(frtn) { - goto out; - } - - sigData = feeCFileSigData(cipherFile, &sigDataLen); - if(sigData) { - feeReturn sigFrtn; - - if(sendPubKey == NULL) { - /* - * use embedded sender's public key - */ - sendPubKeyStr = feeCFileSendPubKeyData(cipherFile, - &sendPubKeyStrLen); - if(sendPubKeyStr == NULL) { - frtn = FR_BadCipherFile; - goto out; - } - parsedSendPubKey = feePubKeyAlloc(); - frtn = feePubKeyInitFromKeyString(parsedSendPubKey, - (char *)sendPubKeyStr, sendPubKeyStrLen); - if(frtn) { - frtn = FR_BadCipherFile; - goto out; - } - sendPubKey = parsedSendPubKey; - } - sigFrtn = feePubKeyVerifySignature(sendPubKey, - cipherText, - cipherTextLen, - sigData, - sigDataLen); - switch(sigFrtn) { - case FR_Success: - *sigStatus = SS_PresentValid; - break; - default: - *sigStatus = SS_PresentInvalid; - break; - } - } - else { - *sigStatus = SS_NotPresent; - } -out: - if(cipherText) { - ffree(cipherText); - } - if(feed) { - feeFEEDExpFree(feed); - } - if(sigData) { - ffree(sigData); - } - if(parsedSendPubKey) { - feePubKeyFree(parsedSendPubKey); - } - if(sendPubKeyStr) { - ffree(sendPubKeyStr); - } - return frtn; -} - -#endif /* CRYPTKIT_CIPHERFILE_ENABLE */ diff --git a/OSX/libsecurity_cryptkit/lib/CipherFileFEED.h b/OSX/libsecurity_cryptkit/lib/CipherFileFEED.h deleted file mode 100644 index 5e6890bc6..000000000 --- a/OSX/libsecurity_cryptkit/lib/CipherFileFEED.h +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * CipherFileFEED.h - FEED and FEEDExp related cipherfile support - * - * Revision History - * ---------------- - * 18 Feb 97 at Apple - * Created. - */ - -#ifndef _CK_CFILEFEED_H_ -#define _CK_CFILEFEED_H_ - -#include "ckconfig.h" - -#if CRYPTKIT_CIPHERFILE_ENABLE - -#include "Crypt.h" -#include "feeCipherFile.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Private functions. - */ -feeReturn createFEED(feePubKey sendPrivKey, - feePubKey recvPubKey, - const unsigned char *plainText, - unsigned plainTextLen, - int genSig, // 1 ==> generate signature - unsigned userData, // for caller's convenience - feeCipherFile *cipherFile); // RETURNED if successful -feeReturn decryptFEED(feeCipherFile cipherFile, - feePubKey recvPrivKey, - feePubKey sendPubKey, - unsigned char **plainText, // RETURNED - unsigned *plainTextLen, // RETURNED - feeSigStatus *sigStatus); // RETURNED -feeReturn createFEEDExp(feePubKey sendPrivKey, - feePubKey recvPubKey, - const unsigned char *plainText, - unsigned plainTextLen, - int genSig, // 1 ==> generate signature - unsigned userData, // for caller's convenience - feeCipherFile *cipherFile); // RETURNED if successful -feeReturn decryptFEEDExp(feeCipherFile cipherFile, - feePubKey recvPrivKey, - feePubKey sendPubKey, // optional - unsigned char **plainText, // RETURNED - unsigned *plainTextLen, // RETURNED - feeSigStatus *sigStatus); // RETURNED - -#ifdef __cplusplus -} -#endif - -#endif /* CRYPTKIT_CIPHERFILE_ENABLE */ - -#endif /*_CK_CFILEFEED_H_*/ diff --git a/OSX/libsecurity_cryptkit/lib/CipherFileTypes.h b/OSX/libsecurity_cryptkit/lib/CipherFileTypes.h deleted file mode 100644 index e0307dc93..000000000 --- a/OSX/libsecurity_cryptkit/lib/CipherFileTypes.h +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * CipherFileTypes.h - * - * Revision History - * ---------------- - * 8/24/98 ap - * Added tags around #endif comment. - * 19 Feb 97 at NeXT - * Created. - */ - -#ifndef _CK_CFILETYPES_H_ -#define _CK_CFILETYPES_H_ - -#include "ckconfig.h" - -#if CRYPTKIT_CIPHERFILE_ENABLE - -#include "feeCipherFile.h" - -/* - * Type of encryption used in a CipherFile. - */ -typedef enum { - - /* - * DES encryption using pad created via public key exchange; sender's - * public key is embedded. - */ - CFE_PublicDES = 1, - - /* - * Random DES key used for encryption. The DES key is encrypted via - * FEEDExp using recipient's public key; the result is embedded in the - * CipherFile. Sender's public key is embedded only if - * signature is generated. - */ - CFE_RandDES = 2, - - /* - * 1:1 FEED encryption. Sender's public key is embedded. - */ - CFE_FEED = 3, - - /* - * 2:1 FEED encryption. Sender's public key is embedded only if signature - * is generated. - */ - CFE_FEEDExp = 4, - - /* - * User-defined cipherfile. - */ - CFE_Other = 5 - -} cipherFileEncrType; - - -/* - * Signature status upon decryption of a CipherFile. - */ -typedef enum { - - SS_NotPresent = 0, // Signature not present. - SS_PresentValid = 1, // Signature present and valid. - SS_PresentNoKey = 2, // Signature present, but no public key - // available to validate it. - SS_PresentInvalid = 3 // Signature present and invalid. - -} feeSigStatus; - -#endif /* CRYPTKIT_CIPHERFILE_ENABLE */ - -#endif /* _CK_CFILETYPES_H_ */ diff --git a/OSX/libsecurity_cryptkit/lib/Crypt.h b/OSX/libsecurity_cryptkit/lib/Crypt.h index 29a47d587..cabb04210 100644 --- a/OSX/libsecurity_cryptkit/lib/Crypt.h +++ b/OSX/libsecurity_cryptkit/lib/Crypt.h @@ -23,26 +23,7 @@ #ifndef _CK_CRYPT_H_ #define _CK_CRYPT_H_ -#ifdef macintosh - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#else - #include -#include #include #include #include @@ -55,6 +36,4 @@ #include #include -#endif - #endif /* _CK_CRYPT_H_ */ diff --git a/OSX/libsecurity_cryptkit/lib/CryptKit.h b/OSX/libsecurity_cryptkit/lib/CryptKit.h deleted file mode 100644 index 6c6f2bc55..000000000 --- a/OSX/libsecurity_cryptkit/lib/CryptKit.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * CryptKit.h created by blaine on Thu 22-Feb-1996 - */ - -// Encryption related protocols and types -#include -#include - -// Classes -#include -#include -#include -#include -#include - -// Misc. Functions -#include -#include -#include diff --git a/OSX/libsecurity_cryptkit/lib/CryptKitAsn1.h b/OSX/libsecurity_cryptkit/lib/CryptKitAsn1.h index a4bfc2994..510806fcb 100644 --- a/OSX/libsecurity_cryptkit/lib/CryptKitAsn1.h +++ b/OSX/libsecurity_cryptkit/lib/CryptKitAsn1.h @@ -7,7 +7,6 @@ #include "ckconfig.h" -#if CRYPTKIT_DER_ENABLE #include #include @@ -133,6 +132,4 @@ extern const SecAsn1Template FEEPrivateKeyASN1Template[]; } #endif -#endif /* CRYPTKIT_DER_ENABLE */ - #endif /* _CRYPT_KIT_ASN1_H_ */ diff --git a/OSX/libsecurity_cryptkit/lib/CryptKitDER.cpp b/OSX/libsecurity_cryptkit/lib/CryptKitDER.cpp index f8cabe31b..bb9db9966 100644 --- a/OSX/libsecurity_cryptkit/lib/CryptKitDER.cpp +++ b/OSX/libsecurity_cryptkit/lib/CryptKitDER.cpp @@ -24,7 +24,6 @@ #include "ckconfig.h" -#if CRYPTKIT_DER_ENABLE #include #include @@ -37,6 +36,7 @@ #include #include #include +#include #define PRINT_SIG_GIANTS 0 #define PRINT_CURVE_PARAMS 0 @@ -1241,4 +1241,3 @@ feeReturn feeDERDecodePKCS8PrivateKey( return frtn; } -#endif /* CRYPTKIT_DER_ENABLE */ diff --git a/OSX/libsecurity_cryptkit/lib/CryptKitDER.h b/OSX/libsecurity_cryptkit/lib/CryptKitDER.h index 28b6ed035..f193e39b8 100644 --- a/OSX/libsecurity_cryptkit/lib/CryptKitDER.h +++ b/OSX/libsecurity_cryptkit/lib/CryptKitDER.h @@ -27,8 +27,6 @@ #include -#if CRYPTKIT_DER_ENABLE - #include #include #include @@ -192,7 +190,6 @@ feeReturn feeDERDecodePKCS8PrivateKey( } #endif -#endif /* CRYPTKIT_DER_ENABLE */ #endif /* _CRYPTKIT_DER_H_ */ diff --git a/OSX/libsecurity_cryptkit/lib/CryptKitSA.h b/OSX/libsecurity_cryptkit/lib/CryptKitSA.h deleted file mode 100644 index b5a902c89..000000000 --- a/OSX/libsecurity_cryptkit/lib/CryptKitSA.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (c) 1998-2004,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - ***************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include diff --git a/OSX/libsecurity_cryptkit/lib/ECDSA_Profile.h b/OSX/libsecurity_cryptkit/lib/ECDSA_Profile.h index eb7a7cc96..54149b92e 100644 --- a/OSX/libsecurity_cryptkit/lib/ECDSA_Profile.h +++ b/OSX/libsecurity_cryptkit/lib/ECDSA_Profile.h @@ -29,8 +29,6 @@ #include "ckconfig.h" -#if CRYPTKIT_ECDSA_ENABLE - #include "feeDebug.h" #ifdef FEE_DEBUG @@ -86,5 +84,4 @@ extern unsigned vfyStep7; #endif /* ECDSA_PROFILE */ -#endif /* CRYPTKIT_ECDSA_ENABLE */ #endif /* _CK_ECDSA_PROFILE_H_ */ diff --git a/OSX/libsecurity_cryptkit/lib/ECDSA_Verify_Prefix.h b/OSX/libsecurity_cryptkit/lib/ECDSA_Verify_Prefix.h deleted file mode 100644 index 3c52bde54..000000000 --- a/OSX/libsecurity_cryptkit/lib/ECDSA_Verify_Prefix.h +++ /dev/null @@ -1,6 +0,0 @@ -/* - * Prefix file for ECDSA Verify build. - * - * This symbol disables features not needed for ECDSA verify. - */ -#define ECDSA_VERIFY_ONLY 1 diff --git a/OSX/libsecurity_cryptkit/lib/HmacSha1Legacy.c b/OSX/libsecurity_cryptkit/lib/HmacSha1Legacy.c index 83e776197..a24f04385 100644 --- a/OSX/libsecurity_cryptkit/lib/HmacSha1Legacy.c +++ b/OSX/libsecurity_cryptkit/lib/HmacSha1Legacy.c @@ -24,8 +24,6 @@ #include "ckconfig.h" -#if CRYPTKIT_HMAC_LEGACY - #include "HmacSha1Legacy.h" #include "ckSHA1.h" #include @@ -162,4 +160,3 @@ OSStatus hmacLegacyFinal( return errSecSuccess; } -#endif /* CRYPTKIT_HMAC_LEGACY */ diff --git a/OSX/libsecurity_cryptkit/lib/HmacSha1Legacy.h b/OSX/libsecurity_cryptkit/lib/HmacSha1Legacy.h index 691ca5bb7..733f9118d 100644 --- a/OSX/libsecurity_cryptkit/lib/HmacSha1Legacy.h +++ b/OSX/libsecurity_cryptkit/lib/HmacSha1Legacy.h @@ -30,8 +30,6 @@ #include #endif -#if CRYPTKIT_HMAC_LEGACY - #include #ifdef __cplusplus @@ -64,6 +62,4 @@ OSStatus hmacLegacyFinal( } #endif -#endif /* CRYPTKIT_HMAC_LEGACY */ - #endif /* __HMAC_SHA1_LEGACY__ */ diff --git a/OSX/libsecurity_cryptkit/lib/NSCipherFile.h b/OSX/libsecurity_cryptkit/lib/NSCipherFile.h deleted file mode 100644 index 13f103c53..000000000 --- a/OSX/libsecurity_cryptkit/lib/NSCipherFile.h +++ /dev/null @@ -1,111 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * NSCipherFile.h - ObjC wrapper for feeCipherFile - * - * Revision History - * ---------------- - * 28 Oct 96 at NeXT - * Created. - */ - -#import -#import - -@interface NSCipherFile : NSObject -{ - void *_priv; -} - -/* - * Alloc and return an autoreleased NSCipherFile object associated with - * the specified data. - */ -+ newFromCipherText : (NSData *)cipherText - encrType : (cipherFileEncrType)encrType - sendPubKeyData : (NSData *)sendPubKeyData - otherKeyData : (NSData *)otherKeyData - sigData : (NSData *)sigData // optional; nil means no signature - userData : (unsigned)userData; // for caller's convenience - -/* - * Obtain the contents of a feeCipherFile as NSData. - */ -- (NSData *)dataRepresentation; - -/* - * Alloc and return an autoreleased NSCipherFile object given a data - * representation. - */ -+ newFromDataRepresentation : (NSData *)dataRep; - -/* - * Given an NSCipherFile object, obtain its constituent parts. - */ -- (cipherFileEncrType)encryptionType; -- (NSData *)cipherText; -- (NSData *)sendPubKeyData; -- (NSData *)otherKeyData; -- (NSData *)sigData; -- (unsigned)userData; - -/* - * High-level cipherFile support. - */ - -/* - * Obtain the data representation of a NSCipherFile given the specified - * plainText and cipherFileEncrType. - * Receiver's public key is required for all encrTypes; sender's private - * key is required for signature generation and also for encrType - * CFE_PublicDES and CFE_FEED. - */ -+(feeReturn)createCipherFileForPrivKey : (NSFEEPublicKey *)sendPrivKey - recvPubKey : (NSFEEPublicKey *)recvPubKey - encrType : (cipherFileEncrType)encrType - plainText : (NSData *)plainText - genSig : (BOOL)genSig - doEnc64 : (BOOL)doEnc64 // YES ==> perform enc64 - userData : (unsigned)userData // for caller's convenience - cipherFileData : (NSData **)cipherFileData; // RETURNED - -/* - * Parse and decrypt a data representation of an NSCipherFile object. - * - * recvPrivKey is required in all cases. If sendPubKey is present, - * sendPubKey - rather than the embedded sender's public key - will be - * used for signature validation. - */ -+ (feeReturn)parseCipherFileData : (NSFEEPublicKey *)recvPrivKey - sendPubKey : (NSFEEPublicKey *)sendPubKey - cipherFileData : (NSData *)cipherFileData - doDec64 : (BOOL)doDec64 - encrType : (cipherFileEncrType *)encrType // RETURNED - plainText : (NSData **)plainText // RETURNED - sigStatus : (feeSigStatus *)sigStatus // RETURNED - sigSigner : (NSString **)sigSigner // RETURNED - userData : (unsigned *)userData; // RETURNED - -/* - * Parse and decrypt an NSCipherFile object obtained via - * +newFromDataRepresentation. - * - * recvPrivKey is required in all cases. If sendPubKey is present, - * sendPubKey - rather than the embedded sender's public key - will be - * used for signature validation. - */ -- (feeReturn)decryptCipherFileData : (NSFEEPublicKey *)recvPrivKey - sendPubKey : (NSFEEPublicKey *)sendPubKey - plainText : (NSData **)plainText // RETURNED - sigStatus : (feeSigStatus *)sigStatus // RETURNED - sigSigner : (NSString **)sigSigner; // RETURNED - - -@end diff --git a/OSX/libsecurity_cryptkit/lib/NSCipherFile.m b/OSX/libsecurity_cryptkit/lib/NSCipherFile.m deleted file mode 100644 index 93598d723..000000000 --- a/OSX/libsecurity_cryptkit/lib/NSCipherFile.m +++ /dev/null @@ -1,360 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * NSCipherFile.m - ObjC wrapper for feeCipherFile - * - * Revision History - * ---------------- - * 28 Oct 96 at NeXT - * Created. - */ - -#import "NSCipherFile.h" -#import "feeCipherFile.h" -#import "falloc.h" -#import "NSFEEPublicKeyPrivate.h" /* for -feePubKey */ - -/* - * Private instance data. - */ -typedef struct { - feeCipherFile cfile; -} _cfPriv; - -@implementation NSCipherFile - -- (void)dealloc -{ - if(_priv) { - _cfPriv *cfPriv = _priv; - if(cfPriv->cfile) { - feeCFileFree(cfPriv->cfile); - } - } - [super dealloc]; -} - -/* - * Alloc and return an autoreleased NSCipherFile object associated with - * the specified data. - */ -+ newFromCipherText : (NSData *)cipherText - encrType : (cipherFileEncrType)encrType - sendPubKeyData : (NSData *)sendPubKeyData - otherKeyData : (NSData *)otherKeyData - sigData : (NSData *)sigData // optional; nil means no signature - userData : (unsigned)userData // for caller's convenience -{ - NSCipherFile *result; - _cfPriv *cfPriv; - - result = [[self alloc] autorelease]; - result->_priv = cfPriv = fmalloc(sizeof(_cfPriv)); - cfPriv->cfile = feeCFileNewFromCipherText(encrType, - [cipherText bytes], - [cipherText length], - [sendPubKeyData bytes], - [sendPubKeyData length], - [otherKeyData bytes], - [otherKeyData length], - [sigData bytes], - [sigData length], - userData); - if(cfPriv->cfile) { - return result; - } - else { - return nil; - } -} - -/* - * Obtain the contents of a feeCipherFile as NSData. - */ -- (NSData *)dataRepresentation -{ - _cfPriv *cfPriv = _priv; - NSData *result; - const unsigned char *rep; - unsigned repLen; - feeReturn frtn; - - if(cfPriv == NULL) { - return nil; - } - frtn = feeCFileDataRepresentation(cfPriv->cfile, - &rep, - &repLen); - if(frtn) { - return nil; - } - result = [NSData dataWithBytesNoCopy:(unsigned char *)rep - length:repLen]; - return result; -} - -/* - * Alloc and return an autoreleased NSCipherFile object given a data - * representation. - */ -+ newFromDataRepresentation : (NSData *)dataRep -{ - NSCipherFile *result; - _cfPriv *cfPriv; - feeReturn frtn; - - result = [[self alloc] autorelease]; - result->_priv = cfPriv = fmalloc(sizeof(_cfPriv)); - frtn = feeCFileNewFromDataRep([dataRep bytes], - [dataRep length], - &cfPriv->cfile); - if(frtn) { - return nil; - } - else { - return result; - } -} - -/* - * Given an NSCipherFile object, obtain its constituent parts. - */ -- (cipherFileEncrType)encryptionType -{ - _cfPriv *cfPriv = _priv; - - if(cfPriv == NULL) { - return CFE_Other; - } - return feeCFileEncrType(cfPriv->cfile); -} - -- (NSData *)cipherText -{ - _cfPriv *cfPriv = _priv; - const unsigned char *ctext; - unsigned ctextLen; - - if(cfPriv == NULL) { - return nil; - } - ctext = feeCFileCipherText(cfPriv->cfile, &ctextLen); - return [NSData dataWithBytesNoCopy:(unsigned char *)ctext - length:ctextLen]; -} - -- (NSData *)sendPubKeyData -{ - _cfPriv *cfPriv = _priv; - const unsigned char *key; - unsigned keyLen; - - if(cfPriv == NULL) { - return nil; - } - key = feeCFileSendPubKeyData(cfPriv->cfile, &keyLen); - if(key) { - return [NSData dataWithBytesNoCopy:(unsigned char *)key - length:keyLen]; - } - else { - return nil; - } -} - -- (NSData *)otherKeyData -{ - _cfPriv *cfPriv = _priv; - const unsigned char *key; - unsigned keyLen; - - if(cfPriv == NULL) { - return nil; - } - key = feeCFileOtherKeyData(cfPriv->cfile, &keyLen); - if(key) { - return [NSData dataWithBytesNoCopy:(unsigned char *)key - length:keyLen]; - } - else { - return nil; - } -} - -- (NSData *)sigData -{ - _cfPriv *cfPriv = _priv; - const unsigned char *sig; - unsigned sigLen; - - if(cfPriv == NULL) { - return nil; - } - sig = feeCFileSigData(cfPriv->cfile, &sigLen); - if(sig) { - return [NSData dataWithBytesNoCopy:(unsigned char *)sig - length:sigLen]; - } - else { - return nil; - } -} - -- (unsigned)userData -{ - _cfPriv *cfPriv = _priv; - - if(cfPriv == NULL) { - return 0; - } - return feeCFileUserData(cfPriv->cfile); -} - -/* - * High-level cipherFile support. - */ - -/* - * Create a cipherfile of specified cipherFileEncrType for given plaintext. - */ -+(feeReturn)createCipherFileForPrivKey : (NSFEEPublicKey *)sendPrivKey - recvPubKey : (NSFEEPublicKey *)recvPubKey - encrType : (cipherFileEncrType)encrType - plainText : (NSData *)plainText - genSig : (BOOL)genSig - doEnc64 : (BOOL)doEnc64 // YES ==> perform enc64 - userData : (unsigned)userData // for caller's convenience - cipherFileData : (NSData **)cipherFileData // RETURNED -{ - feeReturn frtn; - unsigned char *cfileData; - unsigned cfileDataLen; - feePubKey privKey = NULL; - - if(sendPrivKey) { - privKey = [sendPrivKey feePubKey]; - } - frtn = createCipherFile(privKey, - [recvPubKey feePubKey], - encrType, - [plainText bytes], - [plainText length], - genSig, - doEnc64, - userData, - &cfileData, - &cfileDataLen); - if(frtn) { - return frtn; - } - *cipherFileData = - [NSData dataWithBytesNoCopy:(unsigned char *)cfileData - length:cfileDataLen]; - return frtn; -} - -/* - * Parse and decrypt a data representation of an NSCipherFile object. - */ -+ (feeReturn)parseCipherFileData : (NSFEEPublicKey *)recvPrivKey - sendPubKey : (NSFEEPublicKey *)sendPubKey - cipherFileData : (NSData *)cipherFileData - doDec64 : (BOOL)doDec64 - encrType : (cipherFileEncrType *)encrType // RETURNED - plainText : (NSData **)plainText // RETURNED - sigStatus : (feeSigStatus *)sigStatus // RETURNED - sigSigner : (NSString **)sigSigner // RETURNED - userData : (unsigned *)userData // RETURNED -{ - feeReturn frtn; - unsigned char *ptext; - unsigned ptextLen; - feeUnichar *signer; - unsigned signerLen; - feePubKey _pubKey = NULL; - - if(recvPrivKey == nil) { - return FR_IllegalArg; // always required - } - if(sendPubKey) { - _pubKey = [sendPubKey feePubKey]; - } - - frtn = parseCipherFile([recvPrivKey feePubKey], - _pubKey, - [cipherFileData bytes], - [cipherFileData length], - doDec64, - encrType, - &ptext, - &ptextLen, - sigStatus, - &signer, - &signerLen, - userData); - if(frtn) { - return frtn; - } - *plainText = [NSData dataWithBytesNoCopy:ptext length:ptextLen]; - *sigSigner = [NSString stringWithCharacters:signer length:signerLen]; - ffree(signer); - return frtn; -} - -/* - * Parse and decrypt an NSCipherFile object obtained via - * +newFromDataRepresentation. - * - * recvPrivKey is required in all cases. If sendPubKey is present, - * sendPubKey - rather than the embedded sender's public key - will be - * used for signature validation. - */ -- (feeReturn)decryptCipherFileData : (NSFEEPublicKey *)recvPrivKey - sendPubKey : (NSFEEPublicKey *)sendPubKey - plainText : (NSData **)plainText // RETURNED - sigStatus : (feeSigStatus *)sigStatus // RETURNED - sigSigner : (NSString **)sigSigner // RETURNED -{ - _cfPriv *cfPriv = _priv; - feeReturn frtn; - unsigned char *ptext; - unsigned ptextLen; - feeUnichar *signer; - unsigned signerLen; - feePubKey _pubKey = NULL; - - if(cfPriv == NULL) { - return FR_IllegalArg; - } - if(recvPrivKey == nil) { - return FR_IllegalArg; // always required - } - if(sendPubKey) { - _pubKey = [sendPubKey feePubKey]; - } - - frtn = decryptCipherFile(cfPriv->cfile, - [recvPrivKey feePubKey], - _pubKey, - &ptext, - &ptextLen, - sigStatus, - &signer, - &signerLen); - if(frtn) { - return frtn; - } - *plainText = [NSData dataWithBytesNoCopy:ptext length:ptextLen]; - *sigSigner = [NSString stringWithCharacters:signer length:signerLen]; - ffree(signer); - return frtn; - -} -@end diff --git a/OSX/libsecurity_cryptkit/lib/NSCryptors.h b/OSX/libsecurity_cryptkit/lib/NSCryptors.h deleted file mode 100644 index 33935a7dd..000000000 --- a/OSX/libsecurity_cryptkit/lib/NSCryptors.h +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * NSCryptors.h - common cryptographic protocols - * - * Revision History - * ---------------- - * ??? 1994 Blaine Garst at NeXT - * Created. - */ - - -#import -#import -#import - - -/************ Utilities ******************************************/ - -#ifdef NeXT - -NSString *NSPromptForPassPhrase(NSString *prompt); - // useful for command line (/dev/tty) programs - -#endif NeXT - -/************ Data Hashing Protocol *****************/ - -@protocol NSDataDigester -+ digester; // provides a concrete digester - -// primitives -- (void)digestData:(NSData *)data; // use for multi-bite messages -- (NSData *)messageDigest; // provide digest; re-init - -// conveniences that only use the above primitives -// all in one gulp (eats salt first, if present) -- (NSData *)digestData:(NSData *)data withSalt:(NSData *)salt; - -@end - - -/****** Encryption/Decryption Protocol ***********/ - -@protocol NSCryptor -- (NSData *)encryptData:(NSData *)input; -- (NSData *)decryptData:(NSData *)input; -- (unsigned)keyBitsize; -@end - - -/*************** Public Key Services *************/ - -@protocol NSPublicKey -- (NSString *)publicKeyString; -- (NSString *)algorithmName; // "Diffie-Hellman" "FEE" ... -- (NSString *)usageName; // "Blaine Garst - home" -- (NSData *)padWithPublicKey:(id )otherKey; -- (unsigned)keyBitsize; -@end - -/********* Key Ring ************************/ - -@protocol NSKeyRing -- keyForUsageName:(NSString *)user; -@end - -/********** Digital Signatures **************/ - -// protocol adapted by various signature schemes (FEE, DSA, RSA...) -@protocol NSDigitalSignature -- (NSData *)digitalSignatureForData:(NSData *)message; - // generate a signature for the data - -- (BOOL)isValidDigitalSignature:(NSData *)sig forData:(NSData *)data; -@end diff --git a/OSX/libsecurity_cryptkit/lib/NSDESCryptor.h b/OSX/libsecurity_cryptkit/lib/NSDESCryptor.h deleted file mode 100644 index 6f3ed08ba..000000000 --- a/OSX/libsecurity_cryptkit/lib/NSDESCryptor.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * NSDESCryptor.h created by blaine on Thu 22-Feb-1996 - */ - -#import "NSCryptors.h" - -/****** Digital Encryption Standard/Algorithm ********/ - -@interface NSDESCryptor : NSObject -{ - void *_priv; -} - -+ cryptorWithState:(NSData *)s; - -- initWithState:(NSData *)state; - // designated initializer - // 8 bytes with most sig bit ignored: 56 bits - -- (void)setCryptorState:(NSData *)state; // reset -- (void)setBlockMode:(BOOL)yorn; // default is chaining mode - -/* - * NSCryptor methods - */ -- (NSData *)encryptData:(NSData *)input; -- (NSData *)decryptData:(NSData *)input; -- (unsigned)keyBitsize; - -@end diff --git a/OSX/libsecurity_cryptkit/lib/NSDESCryptor.m b/OSX/libsecurity_cryptkit/lib/NSDESCryptor.m deleted file mode 100644 index 2e071b2e9..000000000 --- a/OSX/libsecurity_cryptkit/lib/NSDESCryptor.m +++ /dev/null @@ -1,130 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * NSDESCryptor.m - DES encrypt/decrypt class - * - * Revision History - * ---------------- - * 28 Mar 97 at Apple - * Rewrote using feeDES module. - * 22 Feb 96 at NeXT - * Created. - */ - -#import -#import "NSDESCryptor.h" -#import "feeDES.h" -#import "falloc.h" -#import "ckutilities.h" -#import "feeFunctions.h" - -/* - * Note: Our _priv ivar is actuall a feeDES pointer. - */ -@implementation NSDESCryptor - -+ cryptorWithState:(NSData *)s { - return [[[self alloc] initWithState:s] autorelease]; -} - -- (void)setCryptorState:(NSData *)state { - if(_priv == NULL) { - return; - } - feeDESSetState(_priv, [state bytes], [state length]); -} - -- initWithState:(NSData *)state { - feeReturn frtn; - - if(_priv == NULL) { - _priv = feeDESNewWithState([state bytes], [state length]); - } - else { - frtn = feeDESSetState(_priv, [state bytes], [state length]); - if(frtn) { - NSLog(@"NSDESCryptor: bad initial state\n"); - return nil; - } - } - return self; -} - -- (void)dealloc -{ - if(_priv) { - feeDESFree(_priv); - } - [super dealloc]; -} - -- (void)setBlockMode:(BOOL)yorn { - if(_priv == NULL) { - return; - } - if(yorn) { - feeDESSetBlockMode(_priv); - } - else { - feeDESSetChainMode(_priv); - } -} - -- (NSData *)encryptData:(NSData *)input { - NSData *result; - feeReturn frtn; - unsigned char *cipherText; - unsigned cipherTextLen; - - if(_priv == NULL) { - return nil; - } - frtn = feeDESEncrypt(_priv, - [input bytes], - [input length], - &cipherText, - &cipherTextLen); - if(frtn) { - NSLog(@"NSDESCryptor encrypt: %s", feeReturnString(frtn)); - return nil; - } - result = [NSData dataWithBytes:cipherText length:cipherTextLen]; - ffree(cipherText); - return result; -} - -- (NSData *)decryptData:(NSData *)input { - NSData *result; - feeReturn frtn; - unsigned char *plainText; - unsigned plainTextLen; - - if(_priv == NULL) { - return nil; - } - frtn = feeDESDecrypt(_priv, - [input bytes], - [input length], - &plainText, - &plainTextLen); - if(frtn) { - NSLog(@"NSDESCryptor decrypt: %s", feeReturnString(frtn)); - return nil; - } - result = [NSData dataWithBytes:plainText length:plainTextLen]; - ffree(plainText); - return result; -} - -- (unsigned)keyBitsize { - return feeDESKeySize(_priv); -} - -@end diff --git a/OSX/libsecurity_cryptkit/lib/NSFEEPublicKey.h b/OSX/libsecurity_cryptkit/lib/NSFEEPublicKey.h deleted file mode 100644 index 42377a280..000000000 --- a/OSX/libsecurity_cryptkit/lib/NSFEEPublicKey.h +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * NSFEEPublicKey.h - * - * Revision History - * ---------------- - * 27 Feb 1997 at Apple - * Broke out from NSCryptors.h. - */ - -#import - -@interface NSFEEPublicKey : NSObject - { -@private - void *_pubKey; -} - -+ keyWithPrivateData:(NSData *)private - depth:(unsigned)depth // depth is in range 0-23 - usageName:(NSString *)uname; - // able to encrypt/decrypt data - // able to create/verify digital signatures - -+ keyWithPublicKeyString:(NSString *)hexstr; - // able to encrypt data - // able to verify digital signatures - -/* - * Create new key with curve parameters matching existing oldKey. - */ -+ keyWithPrivateData:(NSData *)passwd - andKey:(NSFEEPublicKey *)oldKey - usageName:(NSString *)uname; - -/* - * Convenience methods. The first three use the default depth - * (FEE_DEPTH_DEFAULT). - */ -+ keyWithPrivateData:(NSData *)passwd - usageName:(NSString *)uname; -+ keyWithPrivateString:(NSString *)private - usageName:(NSString *)uname; -+ keyWithPrivateString:(NSString *)private - andKey:(NSFEEPublicKey *)oldKey - usageName:(NSString *)uname; - -+ keyWithPrivateString:(NSString *)private - depth:(unsigned)depth - usageName:(NSString *)uname; - -/* - * NSCryptor protocol - */ -- (NSData *)encryptData:(NSData *)data; // done with public knowledge -- (NSData *)decryptData:(NSData *)data; // done with private knowledge - -/* - * NSDigitalSignature protocol - */ -- (NSData *)digitalSignatureForData:(NSData *)data; - // data is hashed with MD5 and then signed with private knowledge -- (BOOL)isValidDigitalSignature:(NSData *)sig forData:(NSData *)data; - // data is hashed with MD5 and then verified with public knowledge - -@end diff --git a/OSX/libsecurity_cryptkit/lib/NSFEEPublicKey.m b/OSX/libsecurity_cryptkit/lib/NSFEEPublicKey.m deleted file mode 100644 index 034af79db..000000000 --- a/OSX/libsecurity_cryptkit/lib/NSFEEPublicKey.m +++ /dev/null @@ -1,496 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * NSFEEPublicKey.m - NSFEEPublicKey class implementation - * - * Revision History - * ---------------- - * 17 Jul 97 at Apple - * Added ECDSA signature routines. - * 21 Aug 96 at NeXT - * Modified to use C-only FeePublicKey module. - * ???? 1994 Blaine Garst at NeXT - * Created. - */ - -#import -#import - -#import "NSCryptors.h" -#import "NSFEEPublicKeyPrivate.h" -#import "feePublicKey.h" -#import "feePublicKeyPrivate.h" -#import "ckutilities.h" -#import "mutils.h" -#import "feeTypes.h" -#import "curveParams.h" -#import "falloc.h" -#import "feeDigitalSignature.h" -#import "feeHash.h" -#import "feeFunctions.h" -#import "feeFEEDExp.h" - -/* - Elliptic curve algebra over finite fields F(p**k), where p = 2**q -1 is a - Mersenne prime. - q is bit-depth. - A private key (a) is a large integer that when multiplied by an initial - curve point P yields the public key aP. - Public keys can be used to generate one-time pads because multiplication - is commutative: - - a(bP) == b(aP) - */ - -@implementation NSFEEPublicKey - -/* - * Root method to create new public key from private "password" data. - */ -+ keyWithPrivateData:(NSData *)passwd - depth:(unsigned)depth - usageName:(NSString *)uname -{ - NSFEEPublicKey *result; - feeReturn frtn; - unichar *uc; - - result = [[self alloc] autorelease]; - result->_pubKey = feePubKeyAlloc(); - uc = fmalloc([uname length] * sizeof(unichar)); - [uname getCharacters:uc]; - frtn = feePubKeyInitFromPrivData(result->_pubKey, - [passwd bytes], [passwd length], - uc, [uname length], - depth); - ffree(uc); - if(frtn) { - NSLog(@"keyWithPrivateData: %s\n", feeReturnString(frtn)); - return nil; - } - return result; -} - -/* - * Create new key with curve parameters matching existing oldKey. - */ -+ keyWithPrivateData:(NSData *)passwd - andKey:(NSFEEPublicKey *)oldKey - usageName:(NSString *)uname -{ - NSFEEPublicKey *result; - feeReturn frtn; - unichar *uc; - - result = [[self alloc] autorelease]; - result->_pubKey = feePubKeyAlloc(); - uc = fmalloc([uname length] * sizeof(unichar)); - [uname getCharacters:uc]; - frtn = feePubKeyInitFromKey(result->_pubKey, - [passwd bytes], [passwd length], - uc, [uname length], - oldKey->_pubKey); - ffree(uc); - if(frtn) { - NSLog(@"keyWithPrivateData:andKey: %s\n", - feeReturnString(frtn)); - return nil; - } - return result; -} - -+ keyWithPrivateData:(NSData *)passwd - usageName:(NSString *)uname -{ - // 4 gives 127 bits of protection - // although the RSA challenge number of 127 bits has been - // broken, FEE is much stronger at the same length - return [self keyWithPrivateData:passwd - depth:FEE_DEPTH_DEFAULT - usageName:uname]; -} - -/* - * The standard way of creating a new key given a private "password" string. - */ -+ keyWithPrivateString:(NSString *)private - usageName:(NSString *)uname -{ - NSData *pdata; - id result; - - /* - * FIXME - handle other encodings? - */ - pdata = [private dataUsingEncoding:NSUTF8StringEncoding]; - result = [self keyWithPrivateData:pdata usageName:uname]; - return result; -} - -+ keyWithPrivateString:(NSString *)private - andKey:(NSFEEPublicKey *)oldKey - usageName:(NSString *)uname -{ - NSData *pdata; - id result; - - if (!uname) return nil; - - pdata = [private dataUsingEncoding:NSUTF8StringEncoding]; - result = [self keyWithPrivateData:pdata andKey:oldKey usageName:uname]; - return result; -} - -+ keyWithPrivateString:(NSString *)private - depth:(unsigned)depth - usageName:(NSString *)uname -{ - NSData *pdata; - id result; - - if (!uname) return nil; - - pdata = [private dataUsingEncoding:NSUTF8StringEncoding]; - result = [self keyWithPrivateData:pdata depth:depth usageName:uname]; - return result; -} - -/* - * The standard way of creating a new key given a public key string. - */ -+ keyWithPublicKeyString:(NSString *)hexstr -{ - NSFEEPublicKey *result; - feeReturn frtn; - NSStringEncoding defEndoding; - const char *s; - - /* - * Protect against gross errors in the key string formatting... - */ - defEndoding = [NSString defaultCStringEncoding]; - if([hexstr canBeConvertedToEncoding:defEndoding] == NO) { - NSLog(@"NSFEEPublicKey: Bad Public Key String Format (1)\n"); - return nil; - } - - /* - * FIXME - docs say this string is "autoreleased". How is a cString - * autoreleased? - */ - s = [hexstr cString]; - result = [[self alloc] autorelease]; - result->_pubKey = feePubKeyAlloc(); - - frtn = feePubKeyInitFromKeyString(result->_pubKey, - s, strlen(s)); - if(frtn) { - NSLog(@"keyWithPublicKeyString:andKey: %s\n", - feeReturnString(frtn)); - return nil; - } - return result; -} - -- (void)dealloc -{ - if(_pubKey) { - feePubKeyFree(_pubKey); - } - [super dealloc]; -} - -/* - * Create a public key in the form of a string. This string contains an - * encoded version of all of our ivars except for _private. - * - * See KeyStringFormat.doc for info on the format of the public key string; - * PLEASE UPDATE THIS DOCUMENT WHEN YOU MAKE CHANGES TO THE STRING FORMAT. - */ -- (NSString *)publicKeyString -{ - char *keyStr; - unsigned keyStrLen; - feeReturn frtn; - NSString *result; - - if(_pubKey == NULL) { - return nil; - } - frtn = feePubKeyCreateKeyString(_pubKey, &keyStr, &keyStrLen); - if(frtn) { - NSLog(@"publicKeyString: %s\n", - feeReturnString(frtn)); - return nil; - } - result = [NSString stringWithCString:keyStr]; - ffree((void *)keyStr); - return result; -} - -- (BOOL)isEqual:(NSFEEPublicKey *)other -{ - if((other == nil) || (other->_pubKey == NULL) || (_pubKey == NULL)) { - return NO; - } - if(feePubKeyIsEqual(_pubKey, other->_pubKey)) { - return YES; - } - else { - return NO; - } -} - -- (unsigned)keyBitsize -{ - if(_pubKey == NULL) { - return 0; - } - return feePubKeyBitsize(_pubKey); -} - -- (NSString *)algorithmName -{ - return [NSString stringWithCString:feePubKeyAlgorithmName()]; -} - -- (NSString *)usageName -{ - unsigned unameLen; - const feeUnichar *uname; - NSString *result; - - if(_pubKey == NULL) { - return nil; - } - uname = feePubKeyUsageName(_pubKey, &unameLen); - result = [NSString stringWithCharacters:uname length:unameLen]; - return result; -} - -- (NSString *)signer -{ - return [self usageName]; -} - -- (NSData *)padWithPublicKey:(id )otherKey -{ - NSFEEPublicKey *other; - NSMutableData *result; - feeReturn frtn; - unsigned char *padData; - unsigned padDataLen; - - if(_pubKey == NULL) { - return nil; - } - if (![otherKey isMemberOfClass:isa]) { - return nil; - } - other = otherKey; - if(other->_pubKey == NULL) { - return nil; - } - frtn = feePubKeyCreatePad(_pubKey, - other->_pubKey, - &padData, - &padDataLen); - if(frtn) { - NSLog(@"padWithPublicKey: %s\n", feeReturnString(frtn)); - return nil; - } - result = [NSData dataWithBytesNoCopy:padData length:padDataLen]; - return result; -} - -- (NSData *)encryptData:(NSData *)data -{ - feeFEEDExp feed; - NSData *result; - feeReturn frtn; - unsigned char *ctext; - unsigned ctextLen; - - if(_pubKey == NULL) { - return nil; - } - feed = feeFEEDExpNewWithPubKey(_pubKey); - frtn = feeFEEDExpEncrypt(feed, - [data bytes], - [data length], - &ctext, - &ctextLen); - if(frtn == FR_Success) { - result = [NSData dataWithBytesNoCopy:ctext length:ctextLen]; - } - else { - NSLog(@"feeFEEDEncrypt: %s\n", feeReturnString(frtn)); - result = nil; - } - feeFEEDExpFree(feed); - return result; -} - -- (NSData *)decryptData:(NSData *)data -{ - feeFEEDExp feed; - NSData *result; - feeReturn frtn; - unsigned char *ptext; - unsigned ptextLen; - - if(_pubKey == NULL) { - return nil; - } - feed = feeFEEDExpNewWithPubKey(_pubKey); - frtn = feeFEEDExpDecrypt(feed, - [data bytes], - [data length], - &ptext, - &ptextLen); - if(frtn == FR_Success) { - result = [NSData dataWithBytesNoCopy:ptext length:ptextLen]; - } - else { - NSLog(@"feeFEEDDecrypt: %s\n", feeReturnString(frtn)); - result = nil; - } - feeFEEDExpFree(feed); - return result; -} - -/* - * When 1, we use ECDSA unless we're using a depth which does not - * have curve orders. - * WARNING - enabling ECDSA by default breaks ICE and compatibility - * with Java signatures, at least until we have a Java ECDSA - * implementation. - */ -#define ECDSA_SIG_DEFAULT 0 - -- (NSData *)digitalSignatureForData:(NSData *)data -{ - NSData *result; - unsigned char *sig; - unsigned sigLen; - feeReturn frtn; - curveParams *cp; - - if(_pubKey == NULL) { - return nil; - } - cp = feePubKeyCurveParams(_pubKey); - if(!ECDSA_SIG_DEFAULT || isZero(cp->x1OrderPlus)) { - frtn = feePubKeyCreateSignature(_pubKey, - [data bytes], - [data length], - &sig, - &sigLen); - } - else { - frtn = feePubKeyCreateECDSASignature(_pubKey, - [data bytes], - [data length], - &sig, - &sigLen); - } - if(frtn) { - NSLog(@"digitalSignatureForData: %s\n", feeReturnString(frtn)); - return nil; - } - result = [NSData dataWithBytesNoCopy:sig length:sigLen]; - return result; -} - -- (BOOL)isValidDigitalSignature:(NSData *)signa - forData:(NSData *)data -{ - feeReturn frtn; - feeUnichar *sigSigner; - unsigned sigSignerLen; - curveParams *cp; - - if(_pubKey == NULL) { - return NO; - } - cp = feePubKeyCurveParams(_pubKey); - if(!ECDSA_SIG_DEFAULT || isZero(cp->x1OrderPlus)) { - frtn = feePubKeyVerifySignature(_pubKey, - [data bytes], - [data length], - [signa bytes], - [signa length], - &sigSigner, - &sigSignerLen); - } - else { - frtn = feePubKeyVerifyECDSASignature(_pubKey, - [data bytes], - [data length], - [signa bytes], - [signa length], - &sigSigner, - &sigSignerLen); - } - - /* - * FIXME - We just throw away the signer for now... - */ - if(sigSignerLen) { - ffree(sigSigner); - } - - switch(frtn) { - case FR_Success: - return YES; - case FR_InvalidSignature: - return NO; - default: - /* - * Something other than simple signature mismatch... - */ - NSLog(@"isValidDigitalSignature: %s\n", feeReturnString(frtn)); - return NO; - } -} - -@end - -@implementation NSFEEPublicKey(Private) - -- (key)minus -{ - if(_pubKey == NULL) { - return NULL; - } - return feePubKeyMinusCurve(_pubKey); -} - -- (key)plus -{ - if(_pubKey == NULL) { - return NULL; - } - return feePubKeyPlusCurve(_pubKey); -} - -- (feePubKey)feePubKey -{ - return _pubKey; -} - -#if FEE_DEBUG -- (void)dump -{ - printPubKey(_pubKey); -} -#endif FEE_DEBUG - -@end diff --git a/OSX/libsecurity_cryptkit/lib/NSFEEPublicKeyPrivate.h b/OSX/libsecurity_cryptkit/lib/NSFEEPublicKeyPrivate.h deleted file mode 100644 index 375769725..000000000 --- a/OSX/libsecurity_cryptkit/lib/NSFEEPublicKeyPrivate.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * NSFEEPublicKeyPrivate.h - * - * Revision History - * ---------------- - * 21 Aug 96 at NeXT - * Created. - */ - -#import "NSFEEPublicKey.h" -#import "elliptic.h" -#import "feeDebug.h" -#import "feePublicKey.h" - -@interface NSFEEPublicKey(Private) - -- (key)minus; -- (key)plus; -#if 0 -- (NSData *)privData; -#endif 0 -- (feePubKey)feePubKey; - -#if FEE_DEBUG -- (void)dump; -#endif FEE_DEBUG -@end diff --git a/OSX/libsecurity_cryptkit/lib/NSMD5Hash.h b/OSX/libsecurity_cryptkit/lib/NSMD5Hash.h deleted file mode 100644 index 1553a4960..000000000 --- a/OSX/libsecurity_cryptkit/lib/NSMD5Hash.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * NSMD5Hash.h - * - * Revision History - * ---------------- - * 28 Mar 97 at Apple - * Created. - */ - -#import -#import - -@interface NSMD5Hash : NSObject - -{ - void *_priv; -} - -+ digester; // provides a concrete digester -- init; // reusable -- (void)digestData:(NSData *)data; -- (NSData *)messageDigest; // provide digest; re-init -- (NSData *)digestData:(NSData *)data withSalt:(NSData *)salt; - -@end diff --git a/OSX/libsecurity_cryptkit/lib/NSMD5Hash.m b/OSX/libsecurity_cryptkit/lib/NSMD5Hash.m deleted file mode 100644 index 8e372be75..000000000 --- a/OSX/libsecurity_cryptkit/lib/NSMD5Hash.m +++ /dev/null @@ -1,79 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * NSMD5Hash.h - * - * Revision History - * ---------------- - * 28 Mar 97 at Apple - * Created. - */ - -/* - * Note: our _priv ivar is actually a feeHash pointer. - */ -#import "NSCryptors.h" -#import "NSMD5Hash.h" -#import "feeHash.h" -#import "falloc.h" - -@implementation NSMD5Hash - -+ digester -{ - return [[self alloc] init]; -} - -- init -{ - if(_priv == NULL) { - _priv = feeHashAlloc(); - } - else { - feeHashReinit(_priv); - } - return self; -} - -- (void)digestData:(NSData *)data -{ - if(_priv == NULL) { - return; - } - feeHashAddData(_priv, [data bytes], [data length]); -} - -- (NSData *)messageDigest -{ - unsigned char *cp; - NSData *md; - - if(_priv == NULL) { - return nil; - } - cp = feeHashDigest(_priv); - md = [NSData dataWithBytes:cp length:feeHashDigestLen()]; - feeHashReinit(_priv); - return md; -} - -- (NSData *)digestData:(NSData *)data withSalt:(NSData *)salt -{ - if(_priv == NULL) { - return nil; - } - if(salt != nil) { - [self digestData:salt]; - } - [self digestData:data]; - return [self messageDigest]; -} - -@end diff --git a/OSX/libsecurity_cryptkit/lib/NSRandomNumberGenerator.h b/OSX/libsecurity_cryptkit/lib/NSRandomNumberGenerator.h deleted file mode 100644 index 1de469cd6..000000000 --- a/OSX/libsecurity_cryptkit/lib/NSRandomNumberGenerator.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * NSRandomNumberGenerator.h - * - * Revision History - * ---------------- - * 28 Mar 97 at Apple - * Simplified. - * ?? 96 Blaine Garst at NeXT - * Created. - */ - -#import - -@interface NSRandomNumberGenerator : NSObject -{ - void *_priv; -} - -- initWithSeed:(unsigned)seed; // designated initializer -- init; // we'll come up with the best seed - // we can - -- (unsigned)nextNumber; -- (unsigned)nextNumberInRange:(NSRange)range; -- (NSData *)randomDataWithLength:(unsigned)l; - -@end diff --git a/OSX/libsecurity_cryptkit/lib/NSRandomNumberGenerator.m b/OSX/libsecurity_cryptkit/lib/NSRandomNumberGenerator.m deleted file mode 100644 index 4d92fc554..000000000 --- a/OSX/libsecurity_cryptkit/lib/NSRandomNumberGenerator.m +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * NSRandomNumberGenerator.m - * - * Revision History - * ---------------- - * 28 Mar 97 at Apple - * Rewrote using feeRandom module. - * ?? 96 Blaine Garst at NeXT - * Created. - */ - -/* - * Note: out _priv ivar is actually a feeRand pointer. - */ - -#import -#import "NSRandomNumberGenerator.h" -#import "feeRandom.h" -#import "falloc.h" - -@implementation NSRandomNumberGenerator - -- init -{ - if(_priv == NULL) { - _priv = feeRandAlloc(); - } - /* - * else no need to re-init - */ - return self; -} - -- initWithSeed:(unsigned)seed -{ - if(_priv != NULL) { - /* - * Free & re-init to use new seed - */ - feeRandFree(_priv); - } - _priv = feeRandAllocWithSeed(seed); - return self; -} - -- (unsigned)nextNumber -{ - if(_priv == NULL) { - return 0; - } - return feeRandNextNum(_priv); -} - -- (unsigned)nextNumberInRange:(NSRange)range -{ - if(_priv == NULL) { - return 0; - } - return range.location + ([self nextNumber] % range.length); -} - -- (NSData *)randomDataWithLength:(unsigned)l -{ - unsigned char *cp; - - if(_priv == NULL) { - return nil; - } - cp = fmalloc(l); - feeRandBytes(_priv, cp, l); - return [NSData dataWithBytesNoCopy:cp length:l]; -} - -@end diff --git a/OSX/libsecurity_cryptkit/lib/README b/OSX/libsecurity_cryptkit/lib/README index e4b8f04a9..51e0ae7ff 100644 --- a/OSX/libsecurity_cryptkit/lib/README +++ b/OSX/libsecurity_cryptkit/lib/README @@ -156,21 +156,6 @@ platform-specific functions: event of a fatal runtime error. The current versions of this function use printf() to log the reason and call exit(1). - unsigned createRandomSeed(); - - This function obtains a 32-bit number with which FEE's - pseudo-random number generator is seeded. The implementation - of this function is highly platform-specific and also depends - on the amount of security required from the RNG in a - particular application. Common (and simple) implementations - involve obtaining a high-precision system clock, process - ID values. etc. - - Note that this function is called during a call to feeRandAlloc() - in feeRandom.c. Clients of the FEE library can also avoid this - mechanism by instantiating the RNG via feeRandAllocWithSeed(), - passing in an application-specific seed. - The file platform.h contains a definition for the endianness of the current platform. Either __BIG_ENDIAN__ or __LITTLE_ENDIAN__ must be #defined at compile time. If your compiler does not implicitly diff --git a/OSX/libsecurity_cryptkit/lib/ckDES.c b/OSX/libsecurity_cryptkit/lib/ckDES.c deleted file mode 100644 index 983f59e12..000000000 --- a/OSX/libsecurity_cryptkit/lib/ckDES.c +++ /dev/null @@ -1,545 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * DES.c - raw DES encryption engine - * - * Revision History - * ---------------- - * Added braces to static array definition of si[][]. - * 10/06/98 ap - * Changed to compile with C++. - * 28 May 98 at Apple - * Changed to use platform-dependent fmalloc(), ffree() - * 31 Mar 97 at Apple - * Put per-instance data in struct _desInst - * Changed setkey() to dessetkey() to avoid collision with libc version - * 21 Aug 96 at NeXT - * Broke out from NSDESCryptor.m - * 22 Feb 96 at NeXT - * Created. - */ - -#include "ckconfig.h" - -#if CRYPTKIT_SYMMETRIC_ENABLE - -#include "ckDES.h" -#include "falloc.h" -#include - -#ifndef NULL -#define NULL ((void *)0) -#endif /* NULL */ - -#define DES_DEBUG 0 /* enables some printfs */ - -/* Sofware DES functions - * written 12 Dec 1986 by Phil Karn, KA9Q; large sections adapted from - * the 1977 public-domain program by Jim Gillogly - */ - -#ifdef __LITTLE_ENDIAN__ -/* Byte swap a long */ -static unsigned int byteswap(unsigned int x) { - register char *cp,tmp; - - cp = (char *)&x; - tmp = cp[3]; - cp[3] = cp[0]; - cp[0] = tmp; - - tmp = cp[2]; - cp[2] = cp[1]; - cp[1] = tmp; - - return x; -} -#endif - -/* Tables defined in the Data Encryption Standard documents */ - -/* initial permutation IP */ -static const char ip[] = { - 58, 50, 42, 34, 26, 18, 10, 2, - 60, 52, 44, 36, 28, 20, 12, 4, - 62, 54, 46, 38, 30, 22, 14, 6, - 64, 56, 48, 40, 32, 24, 16, 8, - 57, 49, 41, 33, 25, 17, 9, 1, - 59, 51, 43, 35, 27, 19, 11, 3, - 61, 53, 45, 37, 29, 21, 13, 5, - 63, 55, 47, 39, 31, 23, 15, 7 -}; - -/* final permutation IP^-1 */ -static const char fp[] = { - 40, 8, 48, 16, 56, 24, 64, 32, - 39, 7, 47, 15, 55, 23, 63, 31, - 38, 6, 46, 14, 54, 22, 62, 30, - 37, 5, 45, 13, 53, 21, 61, 29, - 36, 4, 44, 12, 52, 20, 60, 28, - 35, 3, 43, 11, 51, 19, 59, 27, - 34, 2, 42, 10, 50, 18, 58, 26, - 33, 1, 41, 9, 49, 17, 57, 25 -}; - -/* expansion operation matrix - * This is for reference only; it is unused in the code - * as the f() function performs it implicitly for speed - */ -#ifdef notdef -static char ei[] = { - 32, 1, 2, 3, 4, 5, - 4, 5, 6, 7, 8, 9, - 8, 9, 10, 11, 12, 13, - 12, 13, 14, 15, 16, 17, - 16, 17, 18, 19, 20, 21, - 20, 21, 22, 23, 24, 25, - 24, 25, 26, 27, 28, 29, - 28, 29, 30, 31, 32, 1 -}; -#endif - -/* permuted choice table (key) */ -static const char pc1[] = { - 57, 49, 41, 33, 25, 17, 9, - 1, 58, 50, 42, 34, 26, 18, - 10, 2, 59, 51, 43, 35, 27, - 19, 11, 3, 60, 52, 44, 36, - - 63, 55, 47, 39, 31, 23, 15, - 7, 62, 54, 46, 38, 30, 22, - 14, 6, 61, 53, 45, 37, 29, - 21, 13, 5, 28, 20, 12, 4 -}; - -/* number left rotations of pc1 */ -static const char totrot[] = { - 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 -}; - -/* permuted choice key (table) */ -static const char pc2[] = { - 14, 17, 11, 24, 1, 5, - 3, 28, 15, 6, 21, 10, - 23, 19, 12, 4, 26, 8, - 16, 7, 27, 20, 13, 2, - 41, 52, 31, 37, 47, 55, - 30, 40, 51, 45, 33, 48, - 44, 49, 39, 56, 34, 53, - 46, 42, 50, 36, 29, 32 -}; - -/* The (in)famous S-boxes */ -static const char si[8][64] = { - { - /* S1 */ - 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, - 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, - 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, - 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 - }, - { - /* S2 */ - 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, - 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, - 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, - 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 - }, - { - /* S3 */ - 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, - 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, - 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, - 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 - }, - { - /* S4 */ - 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, - 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, - 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, - 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 - }, - { - /* S5 */ - 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, - 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, - 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, - 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 - }, - { - /* S6 */ - 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, - 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, - 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, - 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 - }, - { - /* S7 */ - 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, - 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, - 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, - 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 - }, - { - /* S8 */ - 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, - 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, - 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, - 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 - } -}; - -/* 32-bit permutation function P used on the output of the S-boxes */ -static const char p32i[] = { - 16, 7, 20, 21, - 29, 12, 28, 17, - 1, 15, 23, 26, - 5, 18, 31, 10, - 2, 8, 24, 14, - 32, 27, 3, 9, - 19, 13, 30, 6, - 22, 11, 4, 25 -}; -/* End of DES-defined tables */ - -/* Lookup tables initialized once only at startup by desinit() */ -static long (*sp)[64]; /* Combined S and P boxes */ - -static char (*iperm)[16][8]; /* Initial and final permutations */ -static char (*fperm)[16][8]; - - -/* bit 0 is left-most in byte */ -static const int bytebit[] = { - 0200,0100,040,020,010,04,02,01 -}; - -static const int nibblebit[] = { - 010,04,02,01 -}; - -/* Allocate space and initialize DES lookup arrays - * mode == 0: standard Data Encryption Algorithm - * mode == 1: DEA without initial and final permutations for speed - * mode == 2: DEA without permutations and with 128-byte key (completely - * independent subkeys for each round) - */ -/* Initialize the lookup table for the combined S and P boxes */ -static void spinit() { - char pbox[32]; - int p,i,s,j,rowcol; - long val; - - /* Compute pbox, the inverse of p32i. - * This is easier to work with - */ - for(p=0;p<32;p++){ - for(i=0;i<32;i++){ - if(p32i[i]-1 == p){ - pbox[p] = i; - break; - } - } - } - for(s = 0; s < 8; s++){ /* For each S-box */ - for(i=0; i<64; i++){ /* For each possible input */ - val = 0; - /* The row number is formed from the first and last - * bits; the column number is from the middle 4 - */ - rowcol = (i & 32) | ((i & 1) ? 16 : 0) | ((i >> 1) & 0xf); - for(j=0;j<4;j++){ /* For each output bit */ - if(si[s][rowcol] & (8 >> j)){ - val |= 1L << (31 - pbox[4*s + j]); - } - } - sp[s][i] = val; - -#if DES_DEBUG - printf("sp[%d][%2d] = %08lx\n",s,i,sp[s][i]); -#endif - } - } -} - -/* initialize a perm array */ -static void perminit(char perm[16][16][8], const char p[64]) { - register int l, j, k; - int i,m; - - /* Clear the permutation array */ - for (i=0; i<16; i++) - for (j=0; j<16; j++) - for (k=0; k<8; k++) - perm[i][j][k]=0; - - for (i=0; i<16; i++) /* each input nibble position */ - for (j = 0; j < 16; j++)/* each possible input nibble */ - for (k = 0; k < 64; k++)/* each output bit position */ - { l = p[k] - 1; /* where does this bit come from*/ - if ((l >> 2) != i) /* does it come from input posn?*/ - continue; /* if not, bit k is 0 */ - if (!(j & nibblebit[l & 3])) - continue; /* any such bit in input? */ - m = k & 07; /* which bit is this in the byte*/ - perm[i][j][k>>3] |= bytebit[m]; - } -} - -int desinit(desInst dinst, int mode) { - dinst->desmode = mode; - - /* - * Remainder only has to be done once. - */ - if(sp != NULL){ - /* Already initialized */ - return 0; - } - if((sp = (long (*)[64])fmalloc(sizeof(long) * 8 * 64)) == NULL){ - return -1; - } - spinit(); - if(mode == 1 || mode == 2) /* No permutations */ - return 0; - - iperm = (char (*)[16][8])fmalloc(sizeof(char) * 16 * 16 * 8); - if(iperm == NULL){ - ffree((char *)sp); - return -1; - } - perminit(iperm,ip); - - fperm = (char (*)[16][8])fmalloc(sizeof(char) * 16 * 16 * 8); - if(fperm == NULL){ - ffree((char *)sp); - ffree((char *)iperm); - return -1; - } - perminit(fperm,fp); - - return 0; -} -/* Free up storage used by DES */ -void desdone(desInst dinst) { -#if 0 - /* - * no per-instance mallocd data - */ - if(sp == NULL) - return; /* Already done */ - - // free((char *)sp); // NO! just free instance data; leave statics - // since these are consts - ffree((char *)dinst->kn); - //if(iperm != NULL) - // free((char *)iperm); - //if(fperm != NULL) - // free((char *)fperm); - - //sp = NULL; - //iperm = NULL; - //fperm = NULL; - dinst->kn = NULL; -#endif /* 0 */ -} -/* Set key (initialize key schedule array) */ -void dessetkey(desInst dinst, char *key) { - char pc1m[56]; /* place to modify pc1 into */ - char pcr[56]; /* place to rotate pc1 into */ - register int i,j,l; - int m; - - /* In mode 2, the 128 bytes of subkey are set directly from the - * user's key, allowing him to use completely independent - * subkeys for each round. Note that the user MUST specify a - * full 128 bytes. - * - * I would like to think that this technique gives the NSA a real - * headache, but I'm not THAT naive. - */ - if(dinst->desmode == 2){ - for(i=0;i<16;i++) - for(j=0;j<8;j++) - dinst->kn[i][j] = *key++; - return; - } - /* Clear key schedule */ - for (i=0; i<16; i++) - for (j=0; j<8; j++) - dinst->kn[i][j]=0; - - for (j=0; j<56; j++) { /* convert pc1 to bits of key */ - l=pc1[j]-1; /* integer bit location */ - m = l & 07; /* find bit */ - pc1m[j]=(key[l>>3] & /* find which key byte l is in */ - bytebit[m]) /* and which bit of that byte */ - ? 1 : 0; /* and store 1-bit result */ - } - for (i=0; i<16; i++) { /* key chunk for each iteration */ - for (j=0; j<56; j++) /* rotate pc1 the right amount */ - pcr[j] = pc1m[(l=j+totrot[i])<(j<28? 28 : 56) ? l: l-28]; - /* rotate left and right halves independently */ - for (j=0; j<48; j++){ /* select bits individually */ - /* check bit that goes to dinst->kn[j] */ - if (pcr[pc2[j]-1]){ - /* mask it in if it's there */ - l= j % 6; - dinst->kn[i][j/6] |= bytebit[l] >> 2; - } - } - } -#if DES_DEBUG - for(i=0;i<16;i++) { - printf("dinst->kn[%d] = ", i); - for(j=0;j<8;j++) { - printf("%x ", dinst->kn[i][j]); - } - printf("\n"); - } - -#endif /* 1 */ -} - -/* The nonlinear function f(r,k), the heart of DES */ -static long int f(unsigned long r, unsigned char subkey[8]) { - /* 32 bits */ - /* 48-bit key for this round */ - register unsigned long rval,rt; -#if DES_DEBUG - printf("f(%08lx, %02x %02x %02x %02x %02x %02x %02x %02x) = ", - r, - subkey[0], subkey[1], subkey[2], - subkey[3], subkey[4], subkey[5], - subkey[6], subkey[7]); -#endif - /* Run E(R) ^ K through the combined S & P boxes - * This code takes advantage of a convenient regularity in - * E, namely that each group of 6 bits in E(R) feeding - * a single S-box is a contiguous segment of R. - */ - rt = (r >> 1) | ((r & 1) ? 0x80000000 : 0); - rval = 0; - rval |= sp[0][((rt >> 26) ^ *subkey++) & 0x3f]; - rval |= sp[1][((rt >> 22) ^ *subkey++) & 0x3f]; - rval |= sp[2][((rt >> 18) ^ *subkey++) & 0x3f]; - rval |= sp[3][((rt >> 14) ^ *subkey++) & 0x3f]; - rval |= sp[4][((rt >> 10) ^ *subkey++) & 0x3f]; - rval |= sp[5][((rt >> 6) ^ *subkey++) & 0x3f]; - rval |= sp[6][((rt >> 2) ^ *subkey++) & 0x3f]; - rt = (r << 1) | ((r & 0x80000000) ? 1 : 0); - rval |= sp[7][(rt ^ *subkey) & 0x3f]; -#if DES_DEBUG - printf(" %08lx\n",rval); -#endif - return rval; -} - -/* Do one DES cipher round */ -static void round(desInst dinst, int num, unsigned long int *block) { - /* i.e. the num-th one */ - - /* The rounds are numbered from 0 to 15. On even rounds - * the right half is fed to f() and the result exclusive-ORs - * the left half; on odd rounds the reverse is done. - */ - if(num & 1){ - block[1] ^= f(block[0],dinst->kn[num]); - } else { - block[0] ^= f(block[1],dinst->kn[num]); - } -} - -/* Permute inblock with perm */ -static void permute(char *inblock, char perm[16][16][8], char *outblock) { - /* result into outblock,64 bits */ - /* 2K bytes defining perm. */ - register int i,j; - register char *ib, *ob; /* ptr to input or output block */ - register char *p, *q; - - if(perm == NULL){ - /* No permutation, just copy */ - for(i=8; i!=0; i--) - *outblock++ = *inblock++; - return; - } - /* Clear output block */ - for (i=8, ob = outblock; i != 0; i--) - *ob++ = 0; - - ib = inblock; - for (j = 0; j < 16; j += 2, ib++) { /* for each input nibble */ - ob = outblock; - p = perm[j][(*ib >> 4) & 017]; - q = perm[j + 1][*ib & 017]; - for (i = 8; i != 0; i--){ /* and each output byte */ - *ob++ |= *p++ | *q++; /* OR the masks together*/ - } - } -} -/* In-place encryption of 64-bit block */ -void endes(desInst dinst, char *block) { - register int i; - unsigned long work[2]; /* Working data storage */ - long tmp; - - permute(block,iperm,(char *)work); /* Initial Permutation */ -#ifdef __LITTLE_ENDIAN__ - work[0] = byteswap(work[0]); - work[1] = byteswap(work[1]); -#endif - - /* Do the 16 rounds */ - for (i=0; i<16; i++) - round(dinst,i,work); - - /* Left/right half swap */ - tmp = work[0]; - work[0] = work[1]; - work[1] = tmp; - -#ifdef __LITTLE_ENDIAN__ - work[0] = byteswap(work[0]); - work[1] = byteswap(work[1]); -#endif - permute((char *)work,fperm,block); /* Inverse initial permutation */ -} -/* In-place decryption of 64-bit block */ -void dedes(desInst dinst, char *block) { - register int i; - unsigned long work[2]; /* Working data storage */ - long tmp; - - permute(block,iperm,(char *)work); /* Initial permutation */ - -#ifdef __LITTLE_ENDIAN__ - work[0] = byteswap(work[0]); - work[1] = byteswap(work[1]); -#endif - - /* Left/right half swap */ - tmp = work[0]; - work[0] = work[1]; - work[1] = tmp; - - /* Do the 16 rounds in reverse order */ - for (i=15; i >= 0; i--) - round(dinst,i,work); - -#ifdef __LITTLE_ENDIAN__ - work[0] = byteswap(work[0]); - work[1] = byteswap(work[1]); -#endif - - permute((char *)work,fperm,block); /* Inverse initial permutation */ -} - -#endif /* CRYPTKIT_SYMMETRIC_ENABLE */ diff --git a/OSX/libsecurity_cryptkit/lib/ckDES.h b/OSX/libsecurity_cryptkit/lib/ckDES.h deleted file mode 100644 index 8f1da0a21..000000000 --- a/OSX/libsecurity_cryptkit/lib/ckDES.h +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * DES.h - raw DES encryption engine interface - * - * Revision History - * ---------------- - * 31 Mar 97 at Apple - * Put per-instance data in struct _desInst - * 21 Aug 96 at NeXT - * Broke out from NSDESCryptor.m - * 22 Feb 96 at NeXT - * Created. - */ - -#ifndef _CK_DES_H_ -#define _CK_DES_H_ - -#include "ckconfig.h" - -#if CRYPTKIT_SYMMETRIC_ENABLE - -#ifdef __cplusplus -extern "C" { -#endif - -#define DES_BLOCK_SIZE_BYTES 8 /* in bytes */ -#define DES_KEY_SIZE_BITS 56 /* effective key size in bits */ -#define DES_KEY_SIZE_BITS_EXTERNAL 64 /* clients actually pass in this much */ -#define DES_KEY_SIZE_BYTES_EXTERNAL (DES_KEY_SIZE_BITS_EXTERNAL / 8) - -#define DES_MODE_STD 0 /* standard Data Encryption Algorithm */ -#define DES_MODE_FAST 1 /* DEA without initial and final */ - /* permutations for speed */ -#define DES_MODE_128 2 /* DEA without permutations and with */ - /* 128-byte key (completely independent */ - /* subkeys for each round) */ - -/* - * Per-instance data. - */ -struct _desInst { - /* 8 16-bit subkeys for each of 16 rounds, initialized by setkey() - */ - unsigned char kn[16][8]; - int desmode; -}; - -typedef struct _desInst *desInst; - -int desinit(desInst dinst, int mode); -void dessetkey(desInst dinst, char *key); -void endes(desInst dinst, char *block); -void dedes(desInst dinst, char *block); -void desdone(desInst dinst); - -#ifdef __cplusplus -} -#endif - -#endif /* CRYPTKIT_SYMMETRIC_ENABLE */ - -#endif /*_CK_DES_H_*/ diff --git a/OSX/libsecurity_cryptkit/lib/ckMD5.c b/OSX/libsecurity_cryptkit/lib/ckMD5.c deleted file mode 100644 index 76f61d19d..000000000 --- a/OSX/libsecurity_cryptkit/lib/ckMD5.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - File: MD5.c - - Written by: Colin Plumb - - Copyright: Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - - Change History (most recent first): - - <7> 10/06/98 ap Changed to compile with C++. - - To Do: -*/ - -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * MD5.c - */ - -/* - * This code implements the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5Context structure, pass it to MD5Init, call MD5Update as - * needed on buffers full of bytes, and then call MD5Final, which - * will fill a supplied 16-byte array with the digest. - */ - -/* - * Revision History - * ---------------- - * 06 Feb 1997 at Apple - * Fixed endian-dependent cast in MD5Final() - * Made byteReverse() tolerant of platform-dependent alignment - * restrictions - */ - -#include "ckconfig.h" - -#if CRYPTKIT_MD5_ENABLE && !CRYPTKIT_LIBMD_DIGEST - -#include "ckMD5.h" -#include "platform.h" -#include "byteRep.h" -#include - - -#define MD5_DEBUG 0 - -#if MD5_DEBUG -static inline void dumpCtx(MD5Context *ctx, char *label) -{ - int i; - - printf("%s\n", label); - printf("buf = "); - for(i=0; i<4; i++) { - printf("%x:", ctx->buf[i]); - } - printf("\nbits: %d:%d\n", ctx->bits[0], ctx->bits[1]); - printf("in[]:\n "); - for(i=0; i<64; i++) { - printf("%02x:", ctx->in[i]); - if((i % 16) == 15) { - printf("\n "); - } - } - printf("\n"); -} -#else // MD5_DEBUG -#define dumpCtx(ctx, label) -#endif // MD5_DEBUG - -static void MD5Transform(UINT32 buf[4], UINT32 const in[16]); - -#if __LITTLE_ENDIAN__ -#define byteReverse(buf, len) /* Nothing */ -#else -static void byteReverse(unsigned char *buf, unsigned longs); - -#ifndef ASM_MD5 -/* - * Note: this code is harmless on little-endian machines. - */ -static void byteReverse(unsigned char *buf, unsigned longs) -{ -#if old_way - /* - * this code is NOT harmless on big-endian machine which require - * natural alignment. - */ - UINT32 t; - do { - t = (UINT32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | - ((unsigned) buf[1] << 8 | buf[0]); - *(UINT32 *) buf = t; - buf += 4; - } while (--longs); -#else // new_way - - unsigned char t; - do { - t = buf[0]; - buf[0] = buf[3]; - buf[3] = t; - t = buf[1]; - buf[1] = buf[2]; - buf[2] = t; - buf += 4; - } while (--longs); -#endif // old_way -} -#endif // ASM_MD5 -#endif // __LITTLE_ENDIAN__ - -/* - * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious - * initialization constants. - */ -void MD5Init(MD5Context *ctx) -{ - ctx->buf[0] = 0x67452301; - ctx->buf[1] = 0xefcdab89; - ctx->buf[2] = 0x98badcfe; - ctx->buf[3] = 0x10325476; - - ctx->bits[0] = 0; - ctx->bits[1] = 0; -} - -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ -void MD5Update(MD5Context *ctx, unsigned char const *buf, unsigned len) -{ - UINT32 t; - - dumpCtx(ctx, "MD5.c update top"); - /* Update bitcount */ - - t = ctx->bits[0]; - if ((ctx->bits[0] = t + ((UINT32) len << 3)) < t) - ctx->bits[1]++; /* Carry from low to high */ - ctx->bits[1] += len >> 29; - - t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ - - /* Handle any leading odd-sized chunks */ - - if (t) { - unsigned char *p = (unsigned char *) ctx->in + t; - - t = 64 - t; - if (len < t) { - memcpy(p, buf, len); - return; - } - memcpy(p, buf, t); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (UINT32 *) ctx->in); - dumpCtx(ctx, "update - return from transform (1)"); - buf += t; - len -= t; - } - /* Process data in 64-byte chunks */ - - while (len >= 64) { - memcpy(ctx->in, buf, 64); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (UINT32 *) ctx->in); - dumpCtx(ctx, "update - return from transform (2)"); - buf += 64; - len -= 64; - } - - /* Handle any remaining bytes of data. */ - - memcpy(ctx->in, buf, len); -} - -/* - * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -void MD5Final(MD5Context *ctx, unsigned char *digest) -{ - unsigned count; - unsigned char *p; - - dumpCtx(ctx, "final top"); - - /* Compute number of bytes mod 64 */ - count = (ctx->bits[0] >> 3) & 0x3F; - - /* Set the first char of padding to 0x80. This is safe since there is - always at least one byte free */ - p = ctx->in + count; - *p++ = 0x80; - #if MD5_DEBUG - printf("in[%d] = %x\n", count, ctx->in[count]); - #endif - /* Bytes of padding needed to make 64 bytes */ - count = 64 - 1 - count; - - /* Pad out to 56 mod 64 */ - dumpCtx(ctx, "final, before pad"); - if (count < 8) { - /* Two lots of padding: Pad the first block to 64 bytes */ - bzero(p, count); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (UINT32 *) ctx->in); - - /* Now fill the next block with 56 bytes */ - bzero(ctx->in, 56); - } else { - /* Pad block to 56 bytes */ - bzero(p, count - 8); - } - byteReverse(ctx->in, 14); - - /* Append length in bits and transform */ - #if old_way - /* - * On a little endian machine, this writes the l.s. byte of - * the bit count to ctx->in[56] and the m.s byte of the bit count to - * ctx->in[63]. - */ - ((UINT32 *) ctx->in)[14] = ctx->bits[0]; - ((UINT32 *) ctx->in)[15] = ctx->bits[1]; - #else // new_way - intToByteRep(ctx->bits[0], &ctx->in[56]); - intToByteRep(ctx->bits[1], &ctx->in[60]); - #endif // new_way - - dumpCtx(ctx, "last transform"); - MD5Transform(ctx->buf, (UINT32 *) ctx->in); - byteReverse((unsigned char *) ctx->buf, 4); - memcpy(digest, ctx->buf, MD5_DIGEST_SIZE); - dumpCtx(ctx, "final end"); - - bzero(ctx, sizeof(*ctx)); /* In case it's sensitive */ -} - -#ifndef ASM_MD5 - -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f, w, x, y, z, data, s) \ - ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) - -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. MD5Update blocks - * the data and converts bytes into longwords for this routine. - */ -static void MD5Transform(UINT32 buf[4], UINT32 const in[16]) -{ - register UINT32 a, b, c, d; - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - -#endif /* ASM_MD5 */ - -#endif /* CRYPTKIT_MD5_ENABLE && CRYPTKIT_LIBMD_DIGEST */ diff --git a/OSX/libsecurity_cryptkit/lib/ckMD5.h b/OSX/libsecurity_cryptkit/lib/ckMD5.h index a4833b374..9bfb2cf81 100644 --- a/OSX/libsecurity_cryptkit/lib/ckMD5.h +++ b/OSX/libsecurity_cryptkit/lib/ckMD5.h @@ -31,9 +31,6 @@ #include "ckconfig.h" -#if CRYPTKIT_MD5_ENABLE -#if CRYPTKIT_LIBMD_DIGEST - /* * In this case we use the MD5 implementation in libSystem. */ @@ -47,44 +44,4 @@ typedef CC_MD5_CTX MD5Context; #define MD5_DIGEST_SIZE CC_MD5_DIGEST_LENGTH -#else /* ! CRYPTKIT_LIBMD_DIGEST */ - -/* Our own private implementation */ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __alpha -typedef unsigned int UINT32; -#elif defined (macintosh) || defined (__ppc__) -typedef unsigned int UINT32; -#else -typedef unsigned long UINT32; -#endif - -typedef struct { - UINT32 buf[4]; - UINT32 bits[2]; // bits[0] is low 32 bits of bit count - unsigned char in[64]; -} MD5Context; - -#define MD5_DIGEST_SIZE 16 /* in bytes */ - -void MD5Init(MD5Context *context); -void MD5Update(MD5Context *context, unsigned char const *buf, - unsigned len); -void MD5Final(MD5Context *context, unsigned char *digest); - -/* - * This is needed to make RSAREF happy on some MS-DOS compilers. - */ -typedef MD5Context MD5_CTX; - -#ifdef __cplusplus -} -#endif - -#endif /* CRYPTKIT_LIBMD_DIGEST */ -#endif /* CRYPTKIT_MD5_ENABLE */ #endif /*_CK_MD5_H_*/ diff --git a/OSX/libsecurity_cryptkit/lib/ckSHA1.c b/OSX/libsecurity_cryptkit/lib/ckSHA1.c index 94a20a6a8..ee7ffff09 100644 --- a/OSX/libsecurity_cryptkit/lib/ckSHA1.c +++ b/OSX/libsecurity_cryptkit/lib/ckSHA1.c @@ -22,18 +22,13 @@ #include "feeTypes.h" #include "ckSHA1.h" -#if CRYPTKIT_LIBMD_DIGEST /* * For linking with AppleCSP: use libSystem SHA1 implementation. */ #include -#else -#include "ckSHA1_priv.h" -#endif #include "falloc.h" #include "platform.h" -#if CRYPTKIT_LIBMD_DIGEST /* * Trivial wrapper for SHA_CTX; a sha1Obj is a pointer to this. */ @@ -82,146 +77,3 @@ unsigned sha1DigestLen(void) return CC_SHA1_DIGEST_LENGTH; } -#else /* standalone cryptkit implementation */ - -/* - * Private data for this object. A sha1Obj handle is cast to a pointer - * to one of these. - */ -typedef struct { - SHS_INFO context; - int isDone; - - /* - * For storing partial blocks - */ - BYTE dataBuf[SHS_BLOCKSIZE]; - unsigned bufBytes; // valid bytes in dataBuf[p] -} sha1Inst; - -/* - * Alloc and init an empty sha1 object. - */ -sha1Obj sha1Alloc(void) -{ - sha1Inst *sinst; - - sinst = (sha1Inst *)fmalloc(sizeof(sha1Inst)); - if(sinst == NULL) { - return NULL; - } - shsInit(&sinst->context); - sha1Reinit((sha1Obj)sinst); - return (sha1Obj)sinst; -} - -/* - * Reusable init function. - */ -void sha1Reinit(sha1Obj sha1) -{ - sha1Inst *sinst = (sha1Inst *) sha1; - - shsInit(&sinst->context); - sinst->isDone = 0; - sinst->bufBytes = 0; -} - -/* - * Free an sha1 object. - */ -void sha1Free(sha1Obj sha1) -{ - sha1Inst *sinst = (sha1Inst *) sha1; - - memset(sha1, 0, sizeof(sha1Inst)); - ffree(sinst); -} - -/* - * Add some data to the sha1 object. - */ -void sha1AddData(sha1Obj sha1, - const unsigned char *data, - unsigned dataLen) -{ - sha1Inst *sinst = (sha1Inst *) sha1; - unsigned toMove; - unsigned blocks; - - if(sinst->isDone) { - /* - * Log some kind of error here... - */ - return; - } - - /* - * First deal with partial buffered block - */ - if(sinst->bufBytes != 0) { - toMove = SHS_BLOCKSIZE - sinst->bufBytes; - if(toMove > dataLen) { - toMove = dataLen; - } - memmove(sinst->dataBuf+sinst->bufBytes, data, toMove); - data += toMove; - dataLen -= toMove; - sinst->bufBytes += toMove; - if(sinst->bufBytes == SHS_BLOCKSIZE) { - shsUpdate(&sinst->context, sinst->dataBuf, SHS_BLOCKSIZE); - sinst->bufBytes = 0; - } - } - - /* - * Now the bulk of the data, in a multiple of full blocks - */ - blocks = dataLen / SHS_BLOCKSIZE; - toMove = blocks * SHS_BLOCKSIZE; - if(toMove != 0) { - shsUpdate(&sinst->context, data, toMove); - data += toMove; - dataLen -= toMove; - } - - /* - * Store any remainder in dataBuf - */ - if(dataLen != 0) { - memmove(sinst->dataBuf, data, dataLen); - sinst->bufBytes = dataLen; - } -} - -/* - * Obtain a pointer to completed message digest, and the length of the digest. - */ -unsigned char *sha1Digest(sha1Obj sha1) -{ - sha1Inst *sinst = (sha1Inst *) sha1; - - if(!sinst->isDone) { - /* - * Deal with partial resid block - */ - if(sinst->bufBytes != 0) { - shsUpdate(&sinst->context, sinst->dataBuf, - sinst->bufBytes); - sinst->bufBytes = 0; - } - shsFinal(&sinst->context); - sinst->isDone = 1; - } - /* - * FIXME - should do explicit conversion to char array....? - */ - return (unsigned char *)sinst->context.digest; -} - -unsigned sha1DigestLen(void) -{ - return SHS_DIGESTSIZE; -} - -#endif /* CRYPTKIT_LIBMD_DIGEST */ diff --git a/OSX/libsecurity_cryptkit/lib/ckSHA1_priv.c b/OSX/libsecurity_cryptkit/lib/ckSHA1_priv.c deleted file mode 100644 index 4ea15ae0b..000000000 --- a/OSX/libsecurity_cryptkit/lib/ckSHA1_priv.c +++ /dev/null @@ -1,321 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * ckSHA1_priv.c - low-level SHA-1 hash algorithm. - * - * Revision History - * ---------------- - * 05 Jan 1998 at Apple - * Created, based on source by Peter C. Gutmann. - * Mods: made reentrant, added NIST fix to expand(), eliminated - * unnecessary copy to local W[] array. - */ - - -/* NIST proposed Secure Hash Standard. - - Written 2 September 1992, Peter C. Gutmann. - This implementation placed in the public domain. - - Comments to pgut1@cs.aukuni.ac.nz */ - -#include "ckconfig.h" - -#if !CRYPTKIT_LIBMD_DIGEST - -#include "ckSHA1_priv.h" -#include "platform.h" -#include - -/* The SHS f()-functions */ - -#define f1(x,y,z) ( ( x & y ) | ( ~x & z ) ) /* Rounds 0-19 */ -#define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */ -#define f3(x,y,z) ( ( x & y ) | ( x & z ) | ( y & z ) ) /* Rounds 40-59 */ -#define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */ - -/* The SHS Mysterious Constants */ - -#define K1 0x5A827999L /* Rounds 0-19 */ -#define K2 0x6ED9EBA1L /* Rounds 20-39 */ -#define K3 0x8F1BBCDCL /* Rounds 40-59 */ -#define K4 0xCA62C1D6L /* Rounds 60-79 */ - -/* SHS initial values */ - -#define h0init 0x67452301L -#define h1init 0xEFCDAB89L -#define h2init 0x98BADCFEL -#define h3init 0x10325476L -#define h4init 0xC3D2E1F0L - -/* 32-bit rotate - kludged with shifts */ - -#define S(n,X) ( ( X << n ) | ( X >> ( 32 - n ) ) ) - -/* The initial expanding function */ - -/* - * 06 Jan 1998. Added left circular shift per NIST FIPS-180-1 (at - * http://www.nist.gov/itl/div897/pubs/fip180-1.htm). Also see - * B. Schneier, Applied Cryptography, Second Edition, section 18.7 - * for info on this addenda to the original NIST spec. - */ -#define expand(count) { \ - W[count] = W[count - 3] ^ W[count - 8] ^ W[count - 14] ^ W[count - 16]; \ - W[count] = S(1, W[count]); \ -} - -/* The four SHS sub-rounds */ - -#define subRound1(count) \ - { \ - temp = S( 5, A ) + f1( B, C, D ) + E + W[ count ] + K1; \ - E = D; \ - D = C; \ - C = S( 30, B ); \ - B = A; \ - A = temp; \ - } - -#define subRound2(count) \ - { \ - temp = S( 5, A ) + f2( B, C, D ) + E + W[ count ] + K2; \ - E = D; \ - D = C; \ - C = S( 30, B ); \ - B = A; \ - A = temp; \ - } - -#define subRound3(count) \ - { \ - temp = S( 5, A ) + f3( B, C, D ) + E + W[ count ] + K3; \ - E = D; \ - D = C; \ - C = S( 30, B ); \ - B = A; \ - A = temp; \ - } - -#define subRound4(count) \ - { \ - temp = S( 5, A ) + f4( B, C, D ) + E + W[ count ] + K4; \ - E = D; \ - D = C; \ - C = S( 30, B ); \ - B = A; \ - A = temp; \ - } - -/* Initialize the SHS values */ - -void shsInit( SHS_INFO *shsInfo ) - { - /* Set the h-vars to their initial values */ - shsInfo->digest[ 0 ] = h0init; - shsInfo->digest[ 1 ] = h1init; - shsInfo->digest[ 2 ] = h2init; - shsInfo->digest[ 3 ] = h3init; - shsInfo->digest[ 4 ] = h4init; - - /* Initialise bit count */ - shsInfo->countLo = shsInfo->countHi = 0L; - } - -/* Perform the SHS transformation. Note that this code, like MD5, seems to - break some optimizing compilers - it may be necessary to split it into - sections, eg based on the four subrounds */ - -static void shsTransform( SHS_INFO *shsInfo ) -{ - LONG *W, temp; - LONG A, B, C, D, E; - - /* Step A. Copy the data buffer into the local work buffer. */ - /* 07 Jan 1998, dmitch: skip this bogus move, and let the caller - * copy data directly into the W[] array. To minimize changes, - * we'll just increase the size of shsInfo->data[] and make W - * a pointer here. - */ - W = shsInfo->data; - - /* Step B. Expand the 16 words into 64 temporary data words */ - - /* - * Note: I tried optimizing this via a for loop, and for some reason, - * the "optimized" version ran slower on PPC than the original - * unrolled version. The optimized version does run faster on i486 than - * the unrolled version. - * - * Similarly, the set of subRounds, below, runs slower on i486 when - * optimized via 4 'for' loops. The "optimized" version of that is - * a wash on PPC. - * - * Conclusion: leave both of 'em unrolled. We could ifdef per machine, - * but this would get messy once we had more than two architectures. - * We may want to revisit this. --dpm - */ - expand( 16 ); expand( 17 ); expand( 18 ); expand( 19 ); expand( 20 ); - expand( 21 ); expand( 22 ); expand( 23 ); expand( 24 ); expand( 25 ); - expand( 26 ); expand( 27 ); expand( 28 ); expand( 29 ); expand( 30 ); - expand( 31 ); expand( 32 ); expand( 33 ); expand( 34 ); expand( 35 ); - expand( 36 ); expand( 37 ); expand( 38 ); expand( 39 ); expand( 40 ); - expand( 41 ); expand( 42 ); expand( 43 ); expand( 44 ); expand( 45 ); - expand( 46 ); expand( 47 ); expand( 48 ); expand( 49 ); expand( 50 ); - expand( 51 ); expand( 52 ); expand( 53 ); expand( 54 ); expand( 55 ); - expand( 56 ); expand( 57 ); expand( 58 ); expand( 59 ); expand( 60 ); - expand( 61 ); expand( 62 ); expand( 63 ); expand( 64 ); expand( 65 ); - expand( 66 ); expand( 67 ); expand( 68 ); expand( 69 ); expand( 70 ); - expand( 71 ); expand( 72 ); expand( 73 ); expand( 74 ); expand( 75 ); - expand( 76 ); expand( 77 ); expand( 78 ); expand( 79 ); - - /* Step C. Set up first buffer */ - A = shsInfo->digest[ 0 ]; - B = shsInfo->digest[ 1 ]; - C = shsInfo->digest[ 2 ]; - D = shsInfo->digest[ 3 ]; - E = shsInfo->digest[ 4 ]; - - /* Step D. Serious mangling, divided into four sub-rounds */ - subRound1( 0 ); subRound1( 1 ); subRound1( 2 ); subRound1( 3 ); - subRound1( 4 ); subRound1( 5 ); subRound1( 6 ); subRound1( 7 ); - subRound1( 8 ); subRound1( 9 ); subRound1( 10 ); subRound1( 11 ); - subRound1( 12 ); subRound1( 13 ); subRound1( 14 ); subRound1( 15 ); - subRound1( 16 ); subRound1( 17 ); subRound1( 18 ); subRound1( 19 ); - subRound2( 20 ); subRound2( 21 ); subRound2( 22 ); subRound2( 23 ); - subRound2( 24 ); subRound2( 25 ); subRound2( 26 ); subRound2( 27 ); - subRound2( 28 ); subRound2( 29 ); subRound2( 30 ); subRound2( 31 ); - subRound2( 32 ); subRound2( 33 ); subRound2( 34 ); subRound2( 35 ); - subRound2( 36 ); subRound2( 37 ); subRound2( 38 ); subRound2( 39 ); - subRound3( 40 ); subRound3( 41 ); subRound3( 42 ); subRound3( 43 ); - subRound3( 44 ); subRound3( 45 ); subRound3( 46 ); subRound3( 47 ); - subRound3( 48 ); subRound3( 49 ); subRound3( 50 ); subRound3( 51 ); - subRound3( 52 ); subRound3( 53 ); subRound3( 54 ); subRound3( 55 ); - subRound3( 56 ); subRound3( 57 ); subRound3( 58 ); subRound3( 59 ); - subRound4( 60 ); subRound4( 61 ); subRound4( 62 ); subRound4( 63 ); - subRound4( 64 ); subRound4( 65 ); subRound4( 66 ); subRound4( 67 ); - subRound4( 68 ); subRound4( 69 ); subRound4( 70 ); subRound4( 71 ); - subRound4( 72 ); subRound4( 73 ); subRound4( 74 ); subRound4( 75 ); - subRound4( 76 ); subRound4( 77 ); subRound4( 78 ); subRound4( 79 ); - - /* Step E. Build message digest */ - shsInfo->digest[ 0 ] += A; - shsInfo->digest[ 1 ] += B; - shsInfo->digest[ 2 ] += C; - shsInfo->digest[ 3 ] += D; - shsInfo->digest[ 4 ] += E; -} - -/* __LITTLE_ENDIAN__ is in fact #defined on OS X on PPC.... */ -//#ifdef __LITTLE_ENDIAN__ -#if 0 - -/* When run on a little-endian CPU we need to perform byte reversal on an - array of longwords. It is possible to make the code endianness- - independant by fiddling around with data at the byte level, but this - makes for very slow code, so we rely on the user to sort out endianness - at compile time */ - -static void byteReverse( buffer, byteCount ) - LONG *buffer; - int byteCount; - - { - LONG value; - int count; - - byteCount /= sizeof( LONG ); - for( count = 0; count < byteCount; count++ ) - { - value = ( buffer[ count ] << 16 ) | ( buffer[ count ] >> 16 ); - buffer[ count ] = ( ( value & 0xFF00FF00L ) >> 8 ) | ( ( value & 0x00FF00FFL ) << 8 ); - } - } - -#else /* __LITTLE_ENDIAN__ */ - -/* - * Nop for big-endian machines - */ -#define byteReverse( buffer, byteCount ) - -#endif /* __LITTLE_ENDIAN__ */ - - -/* Update SHS for a block of data. This code assumes that the buffer size - is a multiple of SHS_BLOCKSIZE bytes long, which makes the code a lot - more efficient since it does away with the need to handle partial blocks - between calls to shsUpdate() */ - -void shsUpdate( - SHS_INFO *shsInfo, - const BYTE *buffer, - int count) - - { - /* Update bitcount */ - if( ( shsInfo->countLo + ( ( LONG ) count << 3 ) ) < shsInfo->countLo ) - shsInfo->countHi++; /* Carry from low to high bitCount */ - shsInfo->countLo += ( ( LONG ) count << 3 ); - shsInfo->countHi += ( ( LONG ) count >> 29 ); - - /* Process data in SHS_BLOCKSIZE chunks */ - while( count >= SHS_BLOCKSIZE ) - { - memcpy( shsInfo->data, buffer, SHS_BLOCKSIZE ); - byteReverse( shsInfo->data, SHS_BLOCKSIZE ); - shsTransform( shsInfo ); - buffer += SHS_BLOCKSIZE; - count -= SHS_BLOCKSIZE; - } - - /* Handle any remaining bytes of data. This should only happen once - on the final lot of data */ - memcpy( shsInfo->data, buffer, count ); - } - -void shsFinal(SHS_INFO *shsInfo) - { - int count; - LONG lowBitcount = shsInfo->countLo, highBitcount = shsInfo->countHi; - - /* Compute number of bytes mod 64 */ - count = ( int ) ( ( shsInfo->countLo >> 3 ) & 0x3F ); - - /* Set the first char of padding to 0x80. This is safe since there is - always at least one byte free */ - ( ( BYTE * ) shsInfo->data )[ count++ ] = 0x80; - - /* Pad out to 56 mod 64 */ - if( count > 56 ) - { - /* Two lots of padding: Pad the first block to 64 bytes */ - memset( ( BYTE * ) &shsInfo->data + count, 0, 64 - count ); - byteReverse( shsInfo->data, SHS_BLOCKSIZE ); - shsTransform( shsInfo ); - - /* Now fill the next block with 56 bytes */ - memset( &shsInfo->data, 0, 56 ); - } - else - /* Pad block to 56 bytes */ - memset( ( BYTE * ) &shsInfo->data + count, 0, 56 - count ); - byteReverse( shsInfo->data, SHS_BLOCKSIZE ); - - /* Append length in bits and transform */ - shsInfo->data[ 14 ] = highBitcount; - shsInfo->data[ 15 ] = lowBitcount; - - shsTransform( shsInfo ); - byteReverse( shsInfo->data, SHS_DIGESTSIZE ); - } - -#endif /* CRYPTKIT_LIBMD_DIGEST */ diff --git a/OSX/libsecurity_cryptkit/lib/ckSHA1_priv.h b/OSX/libsecurity_cryptkit/lib/ckSHA1_priv.h deleted file mode 100644 index 05cb9cb6e..000000000 --- a/OSX/libsecurity_cryptkit/lib/ckSHA1_priv.h +++ /dev/null @@ -1,60 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * ckSHA1_priv.h - private low-level API for SHA-1 hash algorithm - * - * Revision History - * ---------------- - * 22 Aug 96 at NeXT - * Created. - */ - -/* Useful defines/typedefs */ - -#ifndef _CK_SHA1_PRIV_H_ -#define _CK_SHA1_PRIV_H_ - -#include "ckconfig.h" - -#if !CRYPTKIT_LIBMD_DIGEST - -#ifdef __cplusplus -extern "C" { -#endif - -typedef unsigned char BYTE; -typedef unsigned long LONG; - -/* The SHS block size and message digest sizes, in bytes */ - -#define SHS_BLOCKSIZE 64 -#define SHS_DIGESTSIZE 20 - -/* The structure for storing SHS info */ - -typedef struct { - LONG digest[ 5 ]; /* Message digest */ - LONG countLo, countHi; /* 64-bit bit count */ - LONG data[ 80 ]; /* SHS data buffer */ - } SHS_INFO; - -extern void shsInit(SHS_INFO *shsInfo); -extern void shsUpdate(SHS_INFO *shsInfo, - const BYTE *buffer, - int count); -extern void shsFinal(SHS_INFO *shsInfo); - -#ifdef __cplusplus -} -#endif - -#endif /* !CRYPTKIT_LIBMD_DIGEST */ - -#endif /* _CK_SHA1_PRIV_H_ */ diff --git a/OSX/libsecurity_cryptkit/lib/ckconfig.h b/OSX/libsecurity_cryptkit/lib/ckconfig.h index c1737ea64..73662911c 100644 --- a/OSX/libsecurity_cryptkit/lib/ckconfig.h +++ b/OSX/libsecurity_cryptkit/lib/ckconfig.h @@ -33,69 +33,30 @@ */ #define DEBUG_ENGINE 0 -#define ENGINE_127_BITS 0 /* hard-coded 127 elliptic() */ - /* - * These flags are set en masse, one set per target in the XCode project file or - * Makefile. They determine what gets compiled into the library. Every flag - * has to be defined for every configureation - preprocessors directives use - * #if, not #ifdef. + * These CK_*_BUILD options used to control feature flags for different build strategies. As we + * only build in Security.framework (AppleCSP) these days, code not needed for this use case has been removed. + * For posterity, the feature flags of CK_SECURITY_BUILD will be described below. */ #ifdef CK_SECURITY_BUILD /* * Standard Security.framework build + +#define CRYPTKIT_DER_ENABLE 1 // DER encoding support +#define CRYPTKIT_LIBMD_DIGEST 1 // use CommonCrypto digests +#define CRYPTKIT_ELL_PROJ_ENABLE 1 // elliptic projection +#define CRYPTKIT_ECDSA_ENABLE 1 // ECDSA (requires ELL_PROJ_ENABLE) +#define CRYPTKIT_CIPHERFILE_ENABLE 0 // cipherfile w/symmetric encryption +#define CRYPTKIT_SYMMETRIC_ENABLE 0 // symmetric encryption +#define CRYPTKIT_ASYMMETRIC_ENABLE 1 // asymmetric encryption +#define CRYPTKIT_MD5_ENABLE 1 // MD5 hash +#define CRYPTKIT_SHA1_ENABLE 1 // SHA1 hash - needed for GHMAX_LEGACY +#define CRYPTKIT_HMAC_LEGACY 1 +#define CRYPTKIT_KEY_EXCHANGE 0 // FEE key exchange +#define CRYPTKIT_HIGH_LEVEL_SIG 0 // high level one-shot signature +#define CRYPTKIT_GIANT_STACK_ENABLE 0 // cache of giants */ -#define CRYPTKIT_DER_ENABLE 1 /* DER encoding support */ -#define CRYPTKIT_LIBMD_DIGEST 1 /* use CommonCrypto digests */ -#define CRYPTKIT_ELL_PROJ_ENABLE 1 /* elliptic projection */ -#define CRYPTKIT_ECDSA_ENABLE 1 /* ECDSA (requires ELL_PROJ_ENABLE) */ -#define CRYPTKIT_CIPHERFILE_ENABLE 0 /* cipherfile w/symmetric encryption */ -#define CRYPTKIT_SYMMETRIC_ENABLE 0 /* symmetric encryption */ -#define CRYPTKIT_ASYMMETRIC_ENABLE 1 /* asymmetric encryption */ -#define CRYPTKIT_MD5_ENABLE 1 /* MD5 hash */ -#define CRYPTKIT_SHA1_ENABLE 1 /* SHA1 hash - needed for GHMAX_LEGACY */ -#define CRYPTKIT_HMAC_LEGACY 1 -#define CRYPTKIT_KEY_EXCHANGE 0 /* FEE key exchange */ -#define CRYPTKIT_HIGH_LEVEL_SIG 0 /* high level one-shot signature */ -#define CRYPTKIT_GIANT_STACK_ENABLE 0 /* cache of giants */ - -#elif defined(CK_STANDALONE_BUILD) -/* - * Standalone library build - */ -#define CRYPTKIT_DER_ENABLE 0 -#define CRYPTKIT_LIBMD_DIGEST 0 -#define CRYPTKIT_ELL_PROJ_ENABLE 1 -#define CRYPTKIT_ECDSA_ENABLE 1 -#define CRYPTKIT_CIPHERFILE_ENABLE 1 -#define CRYPTKIT_SYMMETRIC_ENABLE 1 -#define CRYPTKIT_ASYMMETRIC_ENABLE 1 -#define CRYPTKIT_MD5_ENABLE 1 -#define CRYPTKIT_SHA1_ENABLE 1 -#define CRYPTKIT_HMAC_LEGACY 0 -#define CRYPTKIT_KEY_EXCHANGE 1 -#define CRYPTKIT_HIGH_LEVEL_SIG 1 -#define CRYPTKIT_GIANT_STACK_ENABLE 1 - -#elif defined(CK_MINIMUM_SIG_BUILD) -/* - * Standalone, just ElGamal signature and key generation - */ -#define CRYPTKIT_DER_ENABLE 0 -#define CRYPTKIT_LIBMD_DIGEST 0 -#define CRYPTKIT_ELL_PROJ_ENABLE 0 -#define CRYPTKIT_ECDSA_ENABLE 0 -#define CRYPTKIT_CIPHERFILE_ENABLE 0 -#define CRYPTKIT_SYMMETRIC_ENABLE 0 -#define CRYPTKIT_ASYMMETRIC_ENABLE 0 -#define CRYPTKIT_MD5_ENABLE 1 -/* FIXME convert native ElGamal to use SHA1! */ -#define CRYPTKIT_SHA1_ENABLE 0 -#define CRYPTKIT_HMAC_LEGACY 0 -#define CRYPTKIT_KEY_EXCHANGE 0 -#define CRYPTKIT_HIGH_LEVEL_SIG 0 -#define CRYPTKIT_GIANT_STACK_ENABLE 1 #else diff --git a/OSX/libsecurity_cryptkit/lib/ckutilities.c b/OSX/libsecurity_cryptkit/lib/ckutilities.c index 7ed0beea5..6a40a06fd 100644 --- a/OSX/libsecurity_cryptkit/lib/ckutilities.c +++ b/OSX/libsecurity_cryptkit/lib/ckutilities.c @@ -86,9 +86,6 @@ static const frtnItem frtnStrings[] = { */ void initCryptKit(void) { - #if GIANTS_VIA_STACK - curveParamsInitGiants(); - #endif } /* @@ -96,9 +93,6 @@ void initCryptKit(void) */ void terminateCryptKit(void) { - #if GIANTS_VIA_STACK - freeGiantStacks(); - #endif } /* @@ -265,41 +259,6 @@ void printCurveParams(const curveParams *p) {} #endif /* FEE_DEBUG */ -#if defined(NeXT) && !defined(WIN32) - -void getpassword(const char *prompt, char *pbuf) -{ - struct sgttyb ttyb; - int flags; - register char *p; - register int c; - FILE *fi; - void (*sig)(int); - - if ((fi = fdopen(open("/dev/tty", 2, 0), "r")) == NULL) - fi = stdin; - else - setbuf(fi, (char *)NULL); - sig = signal(SIGINT, SIG_IGN); - ioctl(fileno(fi), TIOCGETP, &ttyb); - flags = ttyb.sg_flags; - ttyb.sg_flags &= ~ECHO; - ioctl(fileno(fi), TIOCSETP, &ttyb); - fprintf(stderr, "%s", prompt); fflush(stderr); - for (p=pbuf; (c = getc(fi))!='\n' && c!=EOF;) { - if (p < &pbuf[PHRASELEN-1]) - *p++ = c; - } - *p = '\0'; - fprintf(stderr, "\n"); fflush(stderr); - ttyb.sg_flags = flags; - ioctl(fileno(fi), TIOCSETP, &ttyb); - (void)signal(SIGINT, sig); - if (fi != stdin) - fclose(fi); -} -#endif // NeXT - /* * serialize, deserialize giants's n[] to/from byte stream. * First byte of byte stream is the MS byte of the resulting giant, diff --git a/OSX/libsecurity_cryptkit/lib/curveParamDataOld.h b/OSX/libsecurity_cryptkit/lib/curveParamDataOld.h deleted file mode 100644 index 2b0c6fbf2..000000000 --- a/OSX/libsecurity_cryptkit/lib/curveParamDataOld.h +++ /dev/null @@ -1,350 +0,0 @@ -/* - * curveParamDataOld.h - prototype FEE curve parameters (obsolete as of 4/9/2001) - */ -#warning Using obsolete curveParam data! -/* - * q = 31 k = 1, Weierstrass - * a = 7 b = 1 c = 0 - */ -static arrayDigit ga_w31_1_a[] = {1, 7}; -static arrayDigit ga_w31_1_x1Plus[] = - {2,15438,14404}; - /* 943995982 */ -static arrayDigit ga_w31_1_x1Minus[] = - {2, 10400, 19905}; - /* 1304504480 */ -static arrayDigit ga_w31_1_plusOrder[] = - {2, 3848, 32769}; - /* 2147553032 */ -static arrayDigit ga_w31_1_minusOrder[] = - {2, 61688, 32766 }; - /* 2147414264 */ -static arrayDigit ga_w31_1_x1OrderPlus[] = - {2, 8673, 4096}; - /* 268444129 */ -static arrayDigit ga_w31_1_x1OrderMinus[] = - {2, 56863, 4095 }; - /* 268426783 */ -static arrayDigit ga_w31_1_x1OrderPlusRecip[] = - {2, 30845, 16383}; -static arrayDigit ga_w31_1_lesserX1OrderRecip[] = - {2, 8673, 4096}; - -/* - * q = 31 k = 1, Montgomery - * a = 1 b = 0 c = 666 - */ -static arrayDigit ga_m31_1_x1Plus[] = - {2, 61780, 6237}; - /* 408809812 */ -static arrayDigit ga_m31_1_x1Minus[] = - {2,12973,30585}; - /* 2004431533 */ -static arrayDigit ga_m31_1_plusOrder[] = - {2, 25928, 32768 }; - /* 2147509576 */ -static arrayDigit ga_m31_1_minusOrder[] = - {2, 39608, 32767 }; - /* 2147457720 */ -static arrayDigit ga_m31_1_x1OrderPlus[] = - {2, 3241, 4096}; - /* 268438697 */ -static arrayDigit ga_m31_1_x1OrderMinus[] = - {2, 4153, 273}; - /* 17895481 */ -static arrayDigit ga_m31_1_x1OrderPlusRecip[] = - {2, 52572, 16383}; -static arrayDigit ga_m31_1_lesserX1OrderRecip[] = - {2, 759, 960}; - -/* - * q = 31 k = 1, Montgomery, prime curve orders - * a = 5824692 b = 2067311435 c = 0 - */ -static arrayDigit ga_31_1P_x1Plus[] = - {1, 6 }; -static arrayDigit ga_31_1P_x1Minus[] = - {1, 7 }; -static arrayDigit ga_31_1P_plusOrder[] = - {2,59003,32766 }; - /* 2147411579 */ -static arrayDigit ga_31_1P_minusOrder[] = - {2,6533,32769 }; - /* 2147555717 */ -static arrayDigit ga_31_1P_x1OrderPlus[] = - {2,59003,32766}; - /* 2147411579 */ -static arrayDigit ga_31_1P_x1OrderMinus[] = - {2,6533,32769}; - /* 2147555717 */ -static arrayDigit ga_31_1P_x1OrderPlusRecip[] = - {2, 6535, 32769}; - -static arrayDigit ga_31_1P_a[] = - {2,57524,88}; - /* 5824692 */ -static arrayDigit ga_31_1P_b[] = - {2,43851,31544}; - /* 2067311435 */ - -/* - * q = 40 k = 213, Weierstrass - * a = 1627500953 b = 523907505 c = 0 - */ -static arrayDigit ga_40_213_x1Plus[] = - {1, 1 }; -static arrayDigit ga_40_213_x1Minus[] = - {1, 2 }; -static arrayDigit ga_40_213_plusOrder[] = - {3,11655,25,256}; - /* 1099513277831 */ -static arrayDigit ga_40_213_minusOrder[] = - {3,53457,65510,255}; - /* 1099509977297 */ -static arrayDigit ga_40_213_x1OrderPlus[] = - {3,11655,25,256}; - /* 1099513277831 */ -static arrayDigit ga_40_213_x1OrderMinus[] = - {3,53457,65510,255}; - /* 1099509977297 */ -static arrayDigit ga_40_213_x1OrderPlusRecip[] = - {3, 18925, 65435, 1023}; -static arrayDigit ga_40_213_lesserX1OrderRecip[] = - {3, 12081, 25, 256}; - -static arrayDigit ga_40_213_a[] = - {2,45465,24833}; - /* 1627500953 */ -static arrayDigit ga_40_213_b[] = - {2,12721,7994}; - /* 523907505 */ - -/* - * q = 127 k = 1 - * a = 1 b = 0 c = 666 - */ -static arrayDigit ga_127_1_x1Plus[] = - {8, 24044, 39922, 11050, - 24692, 34049, 9793, 1228, 31562}; - /* 163879370753099435779911346846180728300 */ -static arrayDigit ga_127_1_x1Minus[] = - {8,49015,6682,26772,63672,45560,46133,24769,8366}; - /* 43440717976631899041527862406676135799 */ -static arrayDigit ga_127_1_plusOrder[] = - { 8, 14612, 61088, 34331, - 32354, 65535, 65535, 65535, - 32767}; - /* 170141183460469231722347548493196835092 */ -static arrayDigit ga_127_1_minusOrder[] = - { 8, 50924, 4447, 31204, - 33181, 0, 0, 0, - 32768 }; - /* 170141183460469231741027058938571376364 */ -static arrayDigit ga_127_1_x1OrderPlus[] = - {6, 8201, 61942, 37082, - 53787, 49605, 7887 }; - /* 9535713005180210505588285449 */ -static arrayDigit ga_127_1_x1OrderMinus[] = - {6, 14659, 1977,16924, - 7446, 49030, 1}; - /* 2113371777483973234080067 */ -static arrayDigit ga_127_1_x1OrderPlusRecip[] = - {6, 21911, 8615, 0, 40960, 64107, 8507}; -static arrayDigit ga_127_1_lesserX1OrderRecip[] = - {6, 44759, 65533, 17695, 61560, 18883, 2}; - -/* - * This is only used for the FEE_DEPTH_127_GEN (FPT_General) case. - */ -static arrayDigit ga_127_1_bp[] = - {8, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 32767}; - -/* - * q = 127 k = 1, Weierstrass - * a = 666 b = 1 c = 0 - */ -static arrayDigit ga_127_1W_x1Plus[] = - {8, 8152, 12974, 29415, - 29630, 64916, 34821, 65368, - 29317}; - /* 152227746030289977478827896983637598168 */ -static arrayDigit ga_127_1W_x1Minus[] = - {8, 33297, 13207, 15262, - 22815, 21569, 49926, 18455, - 22807}; - /* 118422176668700242826570137796135584273 */ -static arrayDigit ga_127_1W_plusOrder[] = - {8, 7568, 62409, 28235, - 47403, 65534, 65535, 65535, - 32767 }; - /* 170141183460469231708136695161971875216 - = 2 * 2 * 2 * 2 * 11 * 17 * 47 * 103 * 10861 * - 1081540940469355570836125423 */ -static arrayDigit ga_127_1W_minusOrder[] = - {8, 57968, 3126,37300, 18132, 1, 0, 0, 32768 }; - /* 170141183460469231755237912269796336240 - = 2 * 2 * 2 * 2 * 3 * 5 * 19 * 34267 * - 1088851169917897274673487152937 */ -static arrayDigit ga_127_1W_x1OrderPlus[] = - { 6, 46831, 48825, 15584, 56652, 41267, 894 }; - /* 1081540940469355570836125423 */ -static arrayDigit ga_127_1W_x1OrderMinus[] = - {7, 1833, 34556, 10366, 60186, 37860, 48708, 13}; - /* 1088851169917897274673487152937 */ -static arrayDigit ga_127_1W_x1OrderPlusRecip[] = - {6, 48506, 2992, 0, 28160, 5127, 1172}; - -/* - * q = 160 k = 57 - * a = c = 0 b = 3 - */ -static arrayDigit ga_160_57_x1Plus[] = - {10,12520,51433,52060,51310,41288,18467,39861,56172,11574,31757}; - /* 708208703989516599321256243677211664634713026792 */ -static arrayDigit ga_160_57_x1Minus[] = - {10,40240,19544,56125,45242,10556,34052,10700,5155,57632,13213}; - /* 294679357488322649182890242541447794429265485104 */ -static arrayDigit ga_160_57_plusOrder[] = - {11,62853,63609,4196,64365,22452,1,0,0,0,0,1}; - /* 1461501637330902918203686455826517732113793021317 */ -static arrayDigit ga_160_57_minusOrder[] = - {10,2571,1926,61339,1170,43083,65534,65535,65535,65535,65535}; - /* 1461501637330902918203683209606048307198072064523 */ -static arrayDigit ga_160_57_x1OrderPlus[] = - {5,171,21451,35098,934,63868}; - /* 1178156913548056058331307 */ -static arrayDigit ga_160_57_x1OrderMinus[] = - {7,255,39523,10835,12387,25442,37088,9774}; - /* 774420897524543052406523561181439 */ -static arrayDigit ga_160_57_x1OrderPlusRecip[] = - {6, 49805, 35001, 38758, 35853, 1711, 1}; -static arrayDigit ga_160_57_b[] = {1, 3}; /* b = (giant)3 */ - -/* - * This is only used for the FEE_DEPTH_160_GEN (FPT_General) case. - */ -static arrayDigit ga_160_57_bp[] = - {10,65479,65535,65535,65535,65535,65535,65535,65535,65535,65535}; - /* 1461501637330902918203684832716283019655932542919 */ - - -/* - * q = 192 k = 1425 - * a = 0 b = -11 c = 0 - */ -static arrayDigit ga_192_1425_x1Plus[] = - {12, 44344, 60264, 44908, - 24163, 37728, 58781, 45290, - 62313, 45939, 59670, 20046, - 8781}; - /* 841082007613983662909216085212018592355989658924032240952 */ -static arrayDigit ga_192_1425_x1Minus[] = - {12,32855,61817,23700,48262,13770,23791,31597,23825,7973,37638, - 62245,25400}; - /* 2432927643133372385673335524462623851522707126886260637783 */ -static arrayDigit ga_192_1425_plusOrder[] = - {13, 7615, 52517, 60178, - 40906, 43135, 27853, 1, - 0, 0, 0, 0, 0, 1}; - /* 6277101735386680763835789423320567585182165941785488334271 */ -static arrayDigit ga_192_1425_minusOrder[] = - {12, 55073, 13018, 5357, - 24629, 22400, 37682, 65534, - 65535, 65535, 65535, 65535, - 65535}; - /* 6277101735386680763835789423094765247022544947142580688673 */ -static arrayDigit ga_192_1425_x1OrderPlus[] = - {11, 55217, 35908, 19375, - 13869, 14836, 18343, 39323, - 50251, 7215, 49984, 21171}; - /* 30942565846835947234516838572438382480699614724151217 */ -static arrayDigit ga_192_1425_x1OrderMinus[] = - {12, 42525, 5637, 42463, - 55864, 53758, 3234, 41914, - 27439, 9168, 44294, 64393, 2}; - /* 285673405333212613836790125294441598644816135581967901 */ -static arrayDigit ga_192_1425_x1OrderPlusRecip[] = - {11, 31243, 31728, 18067, - 25698, 58801, 65534, 65535, - 65535, 65535, 49151, 50715}; -static arrayDigit ga_192_1425_b[] = {-1, 11}; /* b = (giant)(-11) */ - -/* - * q = 192 k = -529891 - * a = -152 b = 722 c = 0 - */ -static arrayDigit ga_192_M529891_x1Plus[] = - {12, 27752, 118, 22193, - 28093, 63505, 16219, 38086, - 5777, 13552, 56652, 28149, - 56180}; - /* 5381016108938327910020782805833379575685074837329310805096 */ -static arrayDigit ga_192_M529891_x1Minus[] = - {12, 20031, 4376, 4872, - 24519, 24047, 14628, 60533, - 27380, 49464, 20541, 38806, - 59062}; - /* 5657072442654455186533371860713762559076927475376430009919 */ -static arrayDigit ga_192_M529891_plusOrder[] = - {13, 5604, 8, 0, - 0, 0, 0, 2, - 0, 0, 0, 0, - 0, 1}; - /* 6277101735386680763835789423366122741130884119651122943460 */ -static arrayDigit ga_192_M529891_minusOrder[] = - {12, 5604, 8, 0, - 0, 0, 0, 65534, - 65535, 65535, 65535, 65535, - 65535}; - /* 6277101735386680763835789423049210091073826769276947142116 */ -static arrayDigit ga_192_M529891_x1OrderPlus[] = - {12, 28623, 26214, 26214, - 26214, 26214, 58982, 16681, - 4766, 10724, 40513, 58386, - 297}; - /* 28532280615394003471980861015300557914231291452959649743 */ -static arrayDigit ga_192_M529891_x1OrderMinus[] = - {11, 18083, 10335, 12214, - 61896, 30741, 14099, 7255, - 33291, 27015, 23037, 196}; - /* 286968072376896521631921223217092198374509106906787 */ -static arrayDigit ga_192_M529891_x1OrderPlusRecip[] = - {12, 58420, 65535, 65535, - 65535, 65535, 63775, 65535, - 65535, 65535, 65535, 65535, 879}; -static arrayDigit ga_192_M529891_lesserX1OrderRecip[] = - {11, 65535, 65535, 65535, 35223, - 667, 0, 0, 0, 0, 50380, 333}; -static arrayDigit ga_192_M529891_a[] = {-1, 152}; /* a = -152 */ -static arrayDigit ga_192_M529891_b[] = { 1, 722}; /* b = 722 */ - -/* - * FPT_General, 161 bits - */ -static arrayDigit ga_161_gen_bp[] = - {11,41419,58349,36408,14563,25486,9098,29127,50972,7281,8647,1}; - /* baseprime = 1654338658923174831024422729553880293604080853451 */ -static arrayDigit ga_161_gen_x1Plus[] = - {10,59390,38748,49144,50217,32781,46057,53816,62856,18968,55868}; - /* 1245904487553815885170631576005220733978383542270 */ -static arrayDigit ga_161_gen_x1Minus[] = - {10,62588,37264,57758,58571,20023,11302,61317,50155,46534,18610}; - /* 415032703104741702601157337572231150005648422012 */ -static arrayDigit ga_161_gen_plusOrder[] = - {11,41420,58349,36408,14563,25486,9100,29127,50972,7281,8647,1}; - /* 1654338658923174831024425147405519522862430265804 */ -static arrayDigit ga_161_gen_minusOrder[] = - {11,41420,58349,36408,14563,25486,9096,29127,50972,7281,8647,1}; - /* 1654338658923174831024420311702241064345731441100 */ -static arrayDigit ga_161_gen_x1OrderPlus[] = - {8,59671,64703,58305,55887,34170,37971,15627,197}; - /* 1024120625531724089187207582052247831 */ -static arrayDigit ga_161_gen_x1OrderMinus[] = - {10,49675,56911,64364,6281,5543,59511,52057,44604,37151,2}; - /* 57243552211874561627142571339177891499852299 */ -static arrayDigit ga_161_gen_x1OrderPlusRecip[] = - {8, 7566, 37898, 14581, 2404, 52670, 23839, 17554, 332}; - -static arrayDigit ga_161_gen_a[] = {-1, 152}; /* a = -152 */ -static arrayDigit ga_161_gen_b[] = { 1, 722}; /* b = 722 */ - diff --git a/OSX/libsecurity_cryptkit/lib/curveParams.c b/OSX/libsecurity_cryptkit/lib/curveParams.c index 94ec21954..7dd0abe03 100644 --- a/OSX/libsecurity_cryptkit/lib/curveParams.c +++ b/OSX/libsecurity_cryptkit/lib/curveParams.c @@ -100,11 +100,8 @@ static const arrayDigit ga_one[] = {1, 1 }; // (giant)1 * individually.... */ -#if FEE_PROTOTYPE_CURVES -#include "curveParamDataOld.h" -#else #include "curveParamData.h" -#endif + /* * Now the curveParamsStatic structs, which provide templates for creating the @@ -116,257 +113,7 @@ static const arrayDigit ga_one[] = {1, 1 }; // (giant)1 * Note these are stored as an array, an index into which is a feeDepth * parameter. */ -#if FEE_PROTOTYPE_CURVES -static curveParamsStatic curveParamsArray[] = { - { // depth=0 - FPT_Mersenne, - FCT_Weierstrass, - 31, 1, // q=31, k=1 - NULL, // basePrime only used for FPT_General - 1, // m = 1 - ga_w31_1_a, // a = 7 - ga_one, // b = 1 - ga_zero, // c = 0 - ga_w31_1_x1Plus, - NULL, // y1Plus - ga_w31_1_x1Minus, - ga_w31_1_plusOrder, - ga_w31_1_minusOrder, - ga_w31_1_x1OrderPlus, - ga_w31_1_x1OrderMinus, - ga_w31_1_x1OrderPlusRecip, - ga_w31_1_lesserX1OrderRecip - }, - { // depth=1 - FPT_Mersenne, - FCT_Montgomery, - 31, 1, // q=31, k=1 - NULL, - 1, // m = 1 - ga_one, // a = 1 - ga_zero, // b = 0 - ga_666, // c = 666 - ga_m31_1_x1Plus, - NULL, // y1Plus - ga_m31_1_x1Minus, - ga_m31_1_plusOrder, - ga_m31_1_minusOrder, - ga_m31_1_x1OrderPlus, - ga_m31_1_x1OrderMinus, - ga_m31_1_x1OrderPlusRecip, - ga_m31_1_lesserX1OrderRecip - - }, - { // depth=2 - FPT_Mersenne, - FCT_Weierstrass, - 31, 1, // q=31, k=1, prime curve orders - NULL, - 1, // m = 1 - ga_31_1P_a, // a = 5824692 - ga_31_1P_b, // b = 2067311435 - ga_zero, // c = 0 - ga_31_1P_x1Plus, - NULL, // y1Plus - ga_31_1P_x1Minus, - ga_31_1P_plusOrder, - ga_31_1P_minusOrder, - ga_31_1P_x1OrderPlus, - ga_31_1P_x1OrderMinus, - ga_31_1P_x1OrderPlusRecip, - NULL // x1PlusOrder is lesser - - }, - { // depth=3 - FPT_FEE, - FCT_Weierstrass, - 40, 213, // q=40, k=213, prime curve orders - NULL, - 1, // m = 1 - ga_40_213_a, // a = 1627500953 - ga_40_213_b, // b = 523907505 - ga_zero, // c = 0 - ga_40_213_x1Plus, - NULL, // y1Plus - ga_40_213_x1Minus, - ga_40_213_plusOrder, - ga_40_213_minusOrder, - ga_40_213_x1OrderPlus, - ga_40_213_x1OrderMinus, - ga_40_213_x1OrderPlusRecip, - ga_40_213_lesserX1OrderRecip - - }, - { // depth=4 - FPT_Mersenne, - FCT_Montgomery, - 127, 1, - NULL, - 1, // m = 1 - ga_one, // a = 1 - ga_zero, // b = 0 - ga_666, // c = 666 - ga_127_1_x1Plus, - NULL, // y1Plus - ga_127_1_x1Minus, - ga_127_1_plusOrder, - ga_127_1_minusOrder, - ga_127_1_x1OrderPlus, - ga_127_1_x1OrderMinus, - ga_127_1_x1OrderPlusRecip, - ga_127_1_lesserX1OrderRecip - - }, - { // depth=5 - FPT_Mersenne, - FCT_Weierstrass, - 127, 1, // q=127, k=1 Weierstrass - NULL, - 1, // m = 1 - ga_666, // a = 666 - ga_one, // b = 1 - ga_zero, // c = 0 - ga_127_1W_x1Plus, - NULL, // y1Plus - ga_127_1W_x1Minus, - ga_127_1W_plusOrder, - ga_127_1W_minusOrder, - ga_127_1W_x1OrderPlus, - ga_127_1W_x1OrderMinus, - ga_127_1W_x1OrderPlusRecip, - NULL // x1PlusOrder is lesser - - }, - { // depth=6 - FPT_FEE, - FCT_Weierstrass, // also Atkin3 - 160, 57, - NULL, - 1, // m = 1 - ga_zero, // a = 0 - ga_160_57_b, // b = 3 - ga_zero, // c = 0 - ga_160_57_x1Plus, - NULL, // y1Plus - ga_160_57_x1Minus, - ga_160_57_plusOrder, - ga_160_57_minusOrder, - ga_160_57_x1OrderPlus, - ga_160_57_x1OrderMinus, - ga_160_57_x1OrderPlusRecip, - NULL // x1PlusOrder is lesser - }, - { // depth=7 - FPT_FEE, - FCT_Weierstrass, // also Atkin3 - 192, 1425, - NULL, - 1, // m = 1 - ga_zero, // a = 0 - ga_192_1425_b, // b = -11 - ga_zero, // c = 0 - ga_192_1425_x1Plus, - NULL, // y1Plus - ga_192_1425_x1Minus, - ga_192_1425_plusOrder, - ga_192_1425_minusOrder, - ga_192_1425_x1OrderPlus, - ga_192_1425_x1OrderMinus, - ga_192_1425_x1OrderPlusRecip, - NULL // x1PlusOrder is lesser - - }, - { // depth=8 - FPT_FEE, - FCT_Weierstrass, - 192, -529891, - NULL, - 1, // m = 1 - ga_192_M529891_a, // a = -152 - ga_192_M529891_b, // b = 722 - ga_zero, // c = 0 - ga_192_M529891_x1Plus, - NULL, // y1Plus - ga_192_M529891_x1Minus, - ga_192_M529891_plusOrder, - ga_192_M529891_minusOrder, - ga_192_M529891_x1OrderPlus, - ga_192_M529891_x1OrderMinus, - ga_192_M529891_x1OrderPlusRecip, - ga_192_M529891_lesserX1OrderRecip - - }, - /* - * FPT_General curves, currently just copies of known FPT_FEE or FPT_Mersenne - * curves with primeType set to FPT_General. These are just for - * verification the general curve are handled properly. - * We include the q parameter here for use by feeKeyBitsToDepth(). - */ - { // depth=9 - FPT_General, - FCT_General, - 127, 0, - ga_127_1_bp, // explicit basePrime - 1, // m = 1 - ga_one, // a = 1 - ga_zero, // b = 0 - ga_666, // c = 666 - ga_127_1_x1Plus, - NULL, // y1Plus - ga_127_1_x1Minus, - ga_127_1_plusOrder, - ga_127_1_minusOrder, - ga_127_1_x1OrderPlus, - ga_127_1_x1OrderMinus, - ga_127_1_x1OrderPlusRecip, - ga_127_1_lesserX1OrderRecip - - }, - { // depth=10, FPT_General version of q=160 - FPT_General, - FCT_Weierstrass, - 160, 0, // we don't use these... - ga_160_57_bp, // explicit basePrime - 1, // m = 1 - ga_zero, // a = 0 - ga_160_57_b, // b = 3 - ga_zero, - ga_160_57_x1Plus, - NULL, // y1Plus - ga_160_57_x1Minus, - ga_160_57_plusOrder, - ga_160_57_minusOrder, - ga_160_57_x1OrderPlus, - ga_160_57_x1OrderMinus, - ga_160_57_x1OrderPlusRecip, - NULL // x1PlusOrder is lesser - }, - - { // depth=11, FPT_General, 161 bits - FPT_General, - FCT_Weierstrass, - //161, 0, - 161, 0, // for verifying we don't use these... - ga_161_gen_bp, // explicit basePrime - 1, // m = 1 - ga_161_gen_a, // a = -152 - ga_161_gen_b, // b = 722 - ga_zero, // c = 0 - ga_161_gen_x1Plus, - NULL, // y1Plus - ga_161_gen_x1Minus, - ga_161_gen_plusOrder, - ga_161_gen_minusOrder, - ga_161_gen_x1OrderPlus, - ga_161_gen_x1OrderMinus, - ga_161_gen_x1OrderPlusRecip, - NULL // x1PlusOrder is lesser - }, - -}; - -#else /* FEE_PROTOTYPE_CURVES */ static const curveParamsStatic curveParamsArray[] = { { @@ -666,7 +413,6 @@ static const curveParamsStatic curveParamsArray[] = { NULL } }; -#endif /* FEE_PROTOTYPE_CURVES */ /* * Convert the static form of a giant - i.e., an array of arrayDigits, @@ -778,9 +524,7 @@ curveParams *curveParamsForDepth(feeDepth depth) if(depth > FEE_DEPTH_MAX) { return NULL; } - #if GIANTS_VIA_STACK - curveParamsInitGiants(); - #endif + cp = newCurveParams(); cp->primeType = cps->primeType; cp->curveType = cps->curveType; @@ -1017,29 +761,6 @@ giant lesserX1Order(curveParams *cp) } } -#if GIANTS_VIA_STACK - -/* - * Prime the curveParams and giants modules for quick allocs of giants. - */ -static int giantsInitd = 0; - -void curveParamsInitGiants(void) -{ - const curveParamsStatic *cps = &curveParamsArray[FEE_DEPTH_MAX]; - - if(giantsInitd) { - return; - } - - /* - * Figure the max giant size of the largest depth we know about... - */ - initGiantStacks(giantMaxDigits(giantMinBytes(cps->q, cps->k))); - giantsInitd = 1; -} - -#endif // GIANTS_VIA_STACK /* * Infer the following fields from a partially constructed curveParams: @@ -1076,7 +797,6 @@ void curveParamsInferFields(curveParams *cp) } /* y1Plus */ - #if CRYPTKIT_ELL_PROJ_ENABLE if(cp->curveType == FCT_Weierstrass) { if(cp->y1Plus == NULL) { /* ECDSA Curves already have this */ @@ -1094,9 +814,7 @@ void curveParamsInferFields(curveParams *cp) else { cp->y1Plus = newGiant(1); } - #else /* CRYPTKIT_ELL_PROJ_ENABLE */ - cp->y1Plus = newGiant(1); - #endif + if((cp->x1OrderPlusRecip == NULL) || isZero(cp->x1OrderPlusRecip)) { /* @@ -1119,88 +837,6 @@ void curveParamsInferFields(curveParams *cp) */ #define LOG_DEPTH 0 -#if FEE_PROTOTYPE_CURVES -feeReturn feeKeyBitsToDepth(unsigned keySize, - feePrimeType primeType, /* FPT_Fefault means "best one" */ - feeCurveType curveType, /* FCT_Default means "best one" */ - feeDepth *depth) -{ - feeReturn frtn = FR_Success; - switch(keySize) { - case 31: - switch(curveType) { - case FCT_Montgomery: - default: - *depth = FEE_DEPTH_31_1_M; - break; - case FCT_Weierstrass: - *depth = FEE_DEPTH_31_1_P; - break; - } - break; - case 40: - switch(curveType) { - case FCT_Weierstrass: - default: - *depth = FEE_DEPTH_40_213; - break; - case FCT_Montgomery: - return FR_IllegalDepth; - } - break; - case 127: - switch(curveType) { - case FCT_Montgomery: - if(primeType == FPT_General) { - *depth = FEE_DEPTH_127_GEN; - } - else{ - *depth = FEE_DEPTH_127_1; - } - break; - case FCT_Weierstrass: - default: - *depth = FEE_DEPTH_127_1W; - break; - } - break; - case 160: - switch(curveType) { - case FCT_Montgomery: - return FR_IllegalDepth; - case FCT_Weierstrass: - default: - if(primeType == FPT_General) { - *depth = FEE_DEPTH_160_GEN; - } - else { - *depth = FEE_DEPTH_160_57; - } - break; - } - break; - case 192: - switch(curveType) { - case FCT_Montgomery: - *depth = FEE_DEPTH_192_M529891; - case FCT_Weierstrass: - default: - *depth = FEE_DEPTH_192_1425; - break; - } - break; - default: - frtn = FR_IllegalDepth; - break; - } - #if LOG_DEPTH - printf("feeKeyBitsToDepth: depth %d\n", *depth); - #endif - return frtn; -} - -#else /* FEE_PROTOTYPE_CURVES */ - feeReturn feeKeyBitsToDepth(unsigned keySize, feePrimeType primeType, /* FPT_Fefault means "best one" */ feeCurveType curveType, /* FCT_Default means "best one" */ @@ -1374,8 +1010,6 @@ feeReturn feeKeyBitsToDepth(unsigned keySize, return frtn; } -#endif /* FEE_PROTOTYPE_CURVES */ - /* * Obtain depth for specified curveParams */ diff --git a/OSX/libsecurity_cryptkit/lib/elliptic.c b/OSX/libsecurity_cryptkit/lib/elliptic.c index 3f45d199c..212df9271 100644 --- a/OSX/libsecurity_cryptkit/lib/elliptic.c +++ b/OSX/libsecurity_cryptkit/lib/elliptic.c @@ -351,7 +351,6 @@ void set_priv_key_giant(key k, giant privGiant) curveParams *cp = k->cp; /* elliptiy multiply of initial public point times private key */ - #if CRYPTKIT_ELL_PROJ_ENABLE if((k->twist == CURVE_PLUS) && (cp->curveType == FCT_Weierstrass)) { /* projective */ @@ -374,9 +373,7 @@ void set_priv_key_giant(key k, giant privGiant) freePointProj(pt1); // FIXME - clear the giants } else { - #else - { - #endif /* CRYPTKIT_ELL_PROJ_ENABLE */ + /* FEE */ if(k->twist == CURVE_PLUS) { gtog(cp->x1Plus, k->x); diff --git a/OSX/libsecurity_cryptkit/lib/ellipticProj.c b/OSX/libsecurity_cryptkit/lib/ellipticProj.c index bdb243164..81d4b691d 100644 --- a/OSX/libsecurity_cryptkit/lib/ellipticProj.c +++ b/OSX/libsecurity_cryptkit/lib/ellipticProj.c @@ -63,7 +63,6 @@ ***********************************************************/ #include "ckconfig.h" -#if CRYPTKIT_ELL_PROJ_ENABLE #include "ellipticProj.h" #include "falloc.h" @@ -561,5 +560,3 @@ void findPointProj(pointProj pt, giant seed, curveParams *cp) gtog(seed,x); int_to_giant(1, z); } - -#endif /* CRYPTKIT_ELL_PROJ_ENABLE */ diff --git a/OSX/libsecurity_cryptkit/lib/ellipticProj.h b/OSX/libsecurity_cryptkit/lib/ellipticProj.h index c71add728..ce611f735 100644 --- a/OSX/libsecurity_cryptkit/lib/ellipticProj.h +++ b/OSX/libsecurity_cryptkit/lib/ellipticProj.h @@ -23,8 +23,6 @@ #include "ckconfig.h" -#if CRYPTKIT_ELL_PROJ_ENABLE - #include "giantIntegers.h" #include "curveParams.h" @@ -72,5 +70,4 @@ normalizeProj(pointProj pt, curveParams *cp); void /* Find a point (x, y, 1) on the curve. */ findPointProj(pointProj pt, giant seed, curveParams *cp); -#endif /* CRYPTKIT_ELL_PROJ_ENABLE*/ #endif /* _CRYPTKIT_ELLIPTIC_PROJ_H_ */ diff --git a/OSX/libsecurity_cryptkit/lib/engineNSA127.c b/OSX/libsecurity_cryptkit/lib/engineNSA127.c deleted file mode 100644 index 0e8ea4af4..000000000 --- a/OSX/libsecurity_cryptkit/lib/engineNSA127.c +++ /dev/null @@ -1,542 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - - CONFIDENTIAL CONFIDENTIAL CONFIDENTIAL - engineNSA.c - - Security Engine code, to be compiled prior to software - distribution. The code performs the - elliptic curve algebra fundamental to the patented FEE - system. - - This Engine is designed to be virtually nonmalleable - with respect to key size. This is achieved herein - via hard-coding of numerical algorithms with respect to - the DEPTH = 4 security level (127 bit Mersenne prime). - - In meetings between the NSA and NeXT Software, Inc. in - 1995-1996, the notion of Security Engine emerged as a - means by which one could discourage disassembly of - FEE compilations, especially when such disassembly - has the sinister goal of modifying encryption depth. - - DO NOT EVEN THINK ABOUT READING THE SOURCE CODE - BELOW UNLESS YOU ARE EXPLICITLY AUTHORIZED TO DO SO - BY NeXT OR ITS DESIGNEE. - - c. 1996, NeXT Software, Inc. - All Rights Reserved. -*/ - -/* This engine requires no initialization. There is one - function to becalled externally, namely elliptic(). - */ - - - - - - - - - - - - - - - - - - - -/* - * Revision History - * ---------------- - * 10/06/98 ap - * Changed to compile with C++. - * 6 Aug 06 at NeXT - * 'a' argument to elliptic() and ell_even() is now a giant. - * 25 Jul 96 at NeXT - * Wrapped ENGINEmul() with gmersennemod(127,.) to guarantee no - * overflow in the hard-coded mul. - * Fixed sign calculation bug in ENGINEmul(). - * 24 Jul 96 at NeXT - * Made conditional on ENGINE_127_BITS. - * Made all functions except for elliptic() static. - * Renamed some giants function calls via #define. - * Deleted use of array of static pseudo-giants. - * Cosmetic changes for debuggability. - * 19 Jun 96 at NeXT - * Created. - */ - -#include "ckconfig.h" - -#if ENGINE_127_BITS -/* - * This file is obsolete as of 8 January 1997. - */ -#error Hey! New curveParam-dependent 127-bit elliptic() needed! -#warning Using NSA-approved 127-bit security engine... - -#include "NSGiantIntegers.h" - -#define D 65536 -#define DM 65535 - -/* - * Size of 127-bit giantstruct n[] array, in shorts. - */ -#define SHORTCOUNT (8 * 2) -#define BORROW_SIZE 0 - - -static void -ENGINEmul(giant a, giant b) { - int a0,a1,a2,a3,a4,a5,a6,a7, - b0,b1,b2,b3,b4,b5,b6,b7; - int asign, bsign; - int i, j, car; - unsigned int prod; - unsigned short mult; - - gmersennemod(127, a); - gmersennemod(127, b); - asign = a->sign; - bsign = b->sign; - - for(j = abs(asign); j < SHORTCOUNT; j++) a->n[j] = 0; - for(j = abs(bsign); j < SHORTCOUNT; j++) b->n[j] = 0; - a0 = a->n[0]; - a1 = a->n[1]; - a2 = a->n[2]; - a3 = a->n[3]; - a4 = a->n[4]; - a5 = a->n[5]; - a6 = a->n[6]; - a7 = a->n[7]; - b0 = b->n[0]; - b1 = b->n[1]; - b2 = b->n[2]; - b3 = b->n[3]; - b4 = b->n[4]; - b5 = b->n[5]; - b6 = b->n[6]; - b7 = b->n[7]; - for(j = 0; j < SHORTCOUNT; j++) b->n[j] = 0; - - i = 0; - mult = b0; - car = 0; - - prod = a0 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a1 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a2 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a3 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a4 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a5 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a6 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a7 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - b->n[i] = car; - - i = 1; - mult = b1; - car = 0; - - prod = a0 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a1 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a2 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a3 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a4 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a5 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a6 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a7 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - b->n[i] = car; - - i = 2; - mult = b2; - car = 0; - - prod = a0 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a1 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a2 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a3 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a4 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a5 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a6 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a7 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - b->n[i] = car; - - i = 3; - mult = b3; - car = 0; - - prod = a0 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a1 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a2 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a3 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a4 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a5 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a6 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a7 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - b->n[i] = car; - - i = 4; - mult = b4; - car = 0; - - prod = a0 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a1 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a2 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a3 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a4 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a5 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a6 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a7 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - b->n[i] = car; - - i = 5; - mult = b5; - car = 0; - - prod = a0 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a1 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a2 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a3 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a4 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a5 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a6 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a7 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - b->n[i] = car; - - i = 6; - mult = b6; - car = 0; - - prod = a0 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a1 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a2 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a3 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a4 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a5 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a6 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a7 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - b->n[i] = car; - - i = 7; - mult = b7; - car = 0; - - prod = a0 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a1 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a2 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a3 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a4 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a5 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a6 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - prod = a7 * mult + b->n[i] + car; - b->n[i++] = prod & DM; - car = prod/D; - - b->n[i] = car; - b->sign = abs(b->sign) + abs(a->sign); - for(j = (b->sign)-1; j >= 0; j--) { - if(b->n[j] != 0) { - break; - } - } - b->sign = j+1; - gmersennemod(127,b); -} - -static void -ell_even(giant x1, giant z1, giant x2, giant z2, giant a, int q) -{ - giant t1, t2, t3; - - t1 = borrowGiant(BORROW_SIZE); - t2 = borrowGiant(BORROW_SIZE); - t3 = borrowGiant(BORROW_SIZE); - - gtog(x1, t1); gsquare(t1); gmersennemod(q, t1); - gtog(z1, t2); gsquare(t2); gmersennemod(q, t2); - gtog(x1, t3); ENGINEmul(z1, t3); - gtog(t1, x2); subg(t2, x2); gsquare(x2); gmersennemod(q, x2); - gtog(a, z2); - ENGINEmul(t3, z2); - addg(t1, z2); addg(t2, z2); ENGINEmul(t3, z2); - gshiftleft(2, z2); - gmersennemod(q, z2); - - returnGiant(t1); - returnGiant(t2); - returnGiant(t3); -} - -static void -ell_odd(giant x1, giant z1, giant x2, giant z2, giant xor, giant zor, int q) -{ - giant t1, t2, t3; - - t1 = borrowGiant(BORROW_SIZE); - t2 = borrowGiant(BORROW_SIZE); - t3 = borrowGiant(BORROW_SIZE); - - gtog(x1, t1); subg(z1, t1); - gtog(x2, t2); addg(z2, t2); - ENGINEmul(t1, t2); - gtog(x1, t1); addg(z1, t1); - gtog(x2, t3); subg(z2, t3); - ENGINEmul(t3, t1); - gtog(t2, x2); addg(t1, x2); - gsquare(x2); gmersennemod(q, x2); //? - gtog(t2, z2); subg(t1, z2); - gsquare(z2); gmersennemod(q, z2); //? - ENGINEmul(zor, x2); - ENGINEmul(xor, z2); - - returnGiant(t1); - returnGiant(t2); - returnGiant(t3); -} - -/* Elliptic multiply. - For given curve parameter a and given prime p = 2^q-1, - the point (xx,zz) becomes k * (xx,zz), in place. - */ -void -elliptic(giant xx, giant zz, giant k, giant a, int q) -{ - int len = bitlen(k), pos = len-2; - giant xs; - giant zs; - giant xorg; - giant zorg; - - if(scompg(1,k)) return; - if(scompg(2,k)) { - ell_even(xx, zz, xx, zz, a, q); - return; - } - - zs = borrowGiant(BORROW_SIZE); - xs = borrowGiant(BORROW_SIZE); - zorg = borrowGiant(BORROW_SIZE); - xorg = borrowGiant(BORROW_SIZE); - - gtog(xx, xorg); gtog(zz, zorg); - ell_even(xx, zz, xs, zs, a, q); - do{ - if(bitval(k, pos--)) { - ell_odd(xs, zs, xx, zz, xorg, zorg, q); - ell_even(xs, zs, xs, zs, a, q); - } else { - ell_odd(xx, zz, xs, zs, xorg, zorg, q); - ell_even(xx, zz, xx, zz, a, q); - } - } while(pos >=0); - - returnGiant(xs); - returnGiant(zs); - returnGiant(xorg); - returnGiant(zorg); -} - -#endif /* ENGINE_127_BITS */ diff --git a/OSX/libsecurity_cryptkit/lib/feeCipherFile.c b/OSX/libsecurity_cryptkit/lib/feeCipherFile.c deleted file mode 100644 index 9c79156d7..000000000 --- a/OSX/libsecurity_cryptkit/lib/feeCipherFile.c +++ /dev/null @@ -1,280 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * feeCipherFile.c - general cipherfile support - * - * Revision History - * ---------------- - * 05 Feb 97 at Apple - * Added CFE_FEED and CFE_FEEDExp types. - * 24 Oct 96 at NeXT - * Created. - */ - -#include "feeCipherFile.h" -#include "falloc.h" -#include "feeFEEDExp.h" -#include "feeFEED.h" -#include "feeDebug.h" -#include "CipherFileFEED.h" -#include "CipherFileDES.h" - - -/* - * Create a cipherfile of specified cipherFileEncrType. - */ -feeReturn createCipherFile(feePubKey sendPrivKey, - feePubKey recvPubKey, - cipherFileEncrType encrType, - const unsigned char *plainText, - unsigned plainTextLen, - int genSig, // 1 ==> generate signature - int doEnc64, // 1 ==> perform enc64 - unsigned userData, // for caller's convenience - unsigned char **cipherFileData, // RETURNED - unsigned *cipherFileDataLen) // RETURNED -{ - feeReturn frtn = FR_Success; - feeCipherFile cipherFile = NULL; - unsigned char *cipherData = NULL; - unsigned cipherDataLen; - - /* - * Dispatch to encrType-specific code. - */ - switch(encrType) { - case CFE_RandDES: - frtn = createRandDES(sendPrivKey, - recvPubKey, - plainText, - plainTextLen, - genSig, - userData, - &cipherFile); - break; - case CFE_PublicDES: - frtn = createPubDES(sendPrivKey, - recvPubKey, - plainText, - plainTextLen, - genSig, - userData, - &cipherFile); - break; - case CFE_FEED: - frtn = createFEED(sendPrivKey, - recvPubKey, - plainText, - plainTextLen, - genSig, - userData, - &cipherFile); - break; - case CFE_FEEDExp: - frtn = createFEEDExp(sendPrivKey, - recvPubKey, - plainText, - plainTextLen, - genSig, - userData, - &cipherFile); - break; - default: - frtn = FR_Unimplemented; - break; - } - - if(frtn) { - goto out; - } - - /* - * Common logic for all encrTypes - */ - - /* - * Get the cipherfile's raw data - */ - frtn = feeCFileDataRepresentation(cipherFile, - (const unsigned char **)&cipherData, - &cipherDataLen); - if(frtn) { - goto out; - } - - /* - * Optionally encode in 64-char ASCII - */ - if(doEnc64) { - *cipherFileData = enc64(cipherData, - cipherDataLen, - cipherFileDataLen); - ffree(cipherData); - if(*cipherFileData == NULL) { - frtn = FR_Internal; - ffree(cipherData); - goto out; - } - } - else { - *cipherFileData = cipherData; - *cipherFileDataLen = cipherDataLen; - } -out: - /* free stuff */ - if(cipherFile) { - feeCFileFree(cipherFile); - } - return frtn; -} - -/* - * Parse a cipherfile. - * - * sendPubKey only needed for cipherFileEncrType CFE_RandDES if signature - * is present. If sendPubKey is present, it will be used for signature - * validation rather than the embedded sender's public key. - */ -feeReturn parseCipherFile(feePubKey recvPrivKey, - feePubKey sendPubKey, - const unsigned char *cipherFileData, - unsigned cipherFileDataLen, - int doDec64, // 1 ==> perform dec64 - cipherFileEncrType *encrType, // RETURNED - unsigned char **plainText, // RETURNED - unsigned *plainTextLen, // RETURNED - feeSigStatus *sigStatus, // RETURNED - unsigned *userData) // RETURNED -{ - feeReturn frtn; - unsigned char *cipherData = NULL; - unsigned cipherDataLen; - int freeCipherData = 0; - feeCipherFile cipherFile = NULL; - - *plainText = NULL; - *plainTextLen = 0; - - if(recvPrivKey == NULL) { // always required - frtn = FR_BadPubKey; - goto out; - } - - /* - * First, optional dec64() - */ - if(doDec64) { - cipherData = dec64(cipherFileData, - cipherFileDataLen, - &cipherDataLen); - if(cipherData == NULL) { - frtn = FR_BadEnc64; - goto out; - } - else { - freeCipherData = 1; - } - } - else { - cipherData = (unsigned char *)cipherFileData; - cipherDataLen = cipherFileDataLen; - } - - /* - * Cons up a feeCipherFile object. - */ - frtn = feeCFileNewFromDataRep(cipherData, - cipherDataLen, - &cipherFile); - if(frtn) { - goto out; - } - *encrType = feeCFileEncrType(cipherFile); - *userData = feeCFileUserData(cipherFile); - frtn = decryptCipherFile(cipherFile, - recvPrivKey, - sendPubKey, - plainText, - plainTextLen, - sigStatus); - -out: - /* free stuff */ - - if(cipherData && freeCipherData) { - ffree(cipherData); - } - if(cipherFile) { - feeCFileFree(cipherFile); - } - return frtn; -} - -/* - * Decrypt a feeCipherFile obtained via feeCFileNewFromDataRep(). - * recvPrivKey is required in all cases. If sendPubKey is present, - * sendPubKey - rather than the embedded sender's public key - will be - * used for signature validation. - */ -feeReturn decryptCipherFile(feeCipherFile cipherFile, - feePubKey recvPrivKey, // required - feePubKey sendPubKey, // optional, for signature - unsigned char **plainText, // malloc'd & RETURNED - unsigned *plainTextLen, // RETURNED - feeSigStatus *sigStatus) // RETURNED -{ - cipherFileEncrType encrType = feeCFileEncrType(cipherFile); - feeReturn frtn; - - *plainText = NULL; - *plainTextLen = 0; - - /* - * Dispatch to encrType-specific code. - */ - switch(encrType) { - case CFE_RandDES: - frtn = decryptRandDES(cipherFile, - recvPrivKey, - sendPubKey, - plainText, - plainTextLen, - sigStatus); - break; - case CFE_PublicDES: - frtn = decryptPubDES(cipherFile, - recvPrivKey, - sendPubKey, - plainText, - plainTextLen, - sigStatus); - break; - case CFE_FEED: - frtn = decryptFEED(cipherFile, - recvPrivKey, - sendPubKey, - plainText, - plainTextLen, - sigStatus); - break; - case CFE_FEEDExp: - frtn = decryptFEEDExp(cipherFile, - recvPrivKey, - sendPubKey, - plainText, - plainTextLen, - sigStatus); - break; - default: - frtn = FR_Unimplemented; - break; - } - return frtn; -} diff --git a/OSX/libsecurity_cryptkit/lib/feeCipherFile.h b/OSX/libsecurity_cryptkit/lib/feeCipherFile.h deleted file mode 100644 index a46f3baf3..000000000 --- a/OSX/libsecurity_cryptkit/lib/feeCipherFile.h +++ /dev/null @@ -1,164 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * feeCipherFile.h - * - * Revision History - * ---------------- - * 24 Oct 96 at NeXT - * Created. - */ - -#ifndef _CK_FEECIPHERFILE_H_ -#define _CK_FEECIPHERFILE_H_ - -#if !defined(__MACH__) -#include -#include -#include -#include -#else -#include "ckconfig.h" -#include "feeTypes.h" -#include "feePublicKey.h" -#include "CipherFileTypes.h" -#endif - -#if CRYPTKIT_CIPHERFILE_ENABLE - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Opaque cipherfile object. - */ -typedef void *feeCipherFile; - -/* - * Alloc and return a new feeCipherFile object associated with the specified - * data. - */ -feeCipherFile feeCFileNewFromCipherText(cipherFileEncrType encrType, - const unsigned char *cipherText, - unsigned cipherTextLen, - const unsigned char *sendPubKeyData, - unsigned sendPubKeyDataLen, - const unsigned char *otherKeyData, - unsigned otherKeyDataDataLen, - const unsigned char *sigData, // optional; NULL means no signature - unsigned sigDataLen, // 0 if sigData is NULL - unsigned userData); // for caller's convenience - -/* - * Obtain the contents of a feeCipherFile as a byte stream. Caller must free - * the returned data. - */ -feeReturn feeCFileDataRepresentation(feeCipherFile cipherFile, - const unsigned char **dataRep, // RETURNED - unsigned *dataRepLen); // RETURNED - -/* - * Alloc and return a new feeCipherFile object, given a byte stream (originally - * obtained from feeCFDataRepresentation()). - */ -feeReturn feeCFileNewFromDataRep(const unsigned char *dataRep, - unsigned dataRepLen, - feeCipherFile *cipherFile); // RETURNED if sucessful - -/* - * Free a feeCipherFile object. - */ -void feeCFileFree(feeCipherFile cipherFile); - -/* - * Given a feeCipherFile object (typically obtained from - * feeCFileNewFromDataRep()), obtain its constituent parts. - * - * Data returned must be freed by caller. - * feeCFileSigData(), feeCFileSendPubKeyData, and feeCFileOtherKeyData() - * may return NULL, indicating component not present. - */ -cipherFileEncrType feeCFileEncrType(feeCipherFile cipherFile); -unsigned char *feeCFileCipherText(feeCipherFile cipherFile, - unsigned *cipherTextLen); // RETURNED -unsigned char *feeCFileSendPubKeyData(feeCipherFile cipherFile, - unsigned *sendPubKeyDataLen); // RETURNED -unsigned char *feeCFileOtherKeyData(feeCipherFile cipherFile, - unsigned *otherKeyDataLen); // RETURNED -unsigned char *feeCFileSigData(feeCipherFile cipherFile, - unsigned *sigDataLen); // RETURNED -unsigned feeCFileUserData(feeCipherFile cipherFile); - -/* - * High-level feeCipherFile support. - */ - -/* - * Obtain the data representation of a feeCipherFile given the specified - * plainText and cipherFileEncrType. - * Receiver's public key is required for all encrTypes; sender's private - * key is required for signature generation and also for encrType - * CFE_PublicDES and CFE_FEED. - */ -feeReturn createCipherFile(feePubKey sendPrivKey, - feePubKey recvPubKey, - cipherFileEncrType encrType, - const unsigned char *plainText, - unsigned plainTextLen, - int genSig, // 1 ==> generate signature - int doEnc64, // 1 ==> perform enc64 - unsigned userData, // for caller's convenience - unsigned char **cipherFileData, // RETURNED - unsigned *cipherFileDataLen); // RETURNED - -/* - * Parse and decrypt a cipherfile given its data representation. - * - * recvPrivKey is required in all cases. If sendPubKey is present, - * sendPubKey - rather than the embedded sender's public key - will be - * used for signature validation. - */ -feeReturn parseCipherFile(feePubKey recvPrivKey, // required - feePubKey sendPubKey, // optional, for signature - const unsigned char *cipherFileData, - unsigned cipherFileDataLen, - int doDec64, // 1 ==> perform dec64 - cipherFileEncrType *encrType, // RETURNED - unsigned char **plainText, // malloc'd & RETURNED - unsigned *plainTextLen, // RETURNED - feeSigStatus *sigStatus, // RETURNED - unsigned *userData); // RETURNED - -/* - * Decrypt a feeCipherFile object obtained via feeCFileNewFromDataRep(). - * recvPrivKey is required in all cases. If sendPubKey is present, - * sendPubKey - rather than the embedded sender's public key - will be - * used for signature validation. - * - * Note: this function is used (in conjunction with feeCFileNewFromDataRep()) - * rather than the simpler parseCipherFile(), in case the caller needs - * access to CipherFile fields not returned in parseCipherFile(). For - * example, the caller might want to get the sender's public key data - * via feeCFileSendPubKeyData(). - */ -feeReturn decryptCipherFile(feeCipherFile cipherFile, - feePubKey recvPrivKey, // required - feePubKey sendPubKey, // optional, for signature - unsigned char **plainText, // malloc'd & RETURNED - unsigned *plainTextLen, // RETURNED - feeSigStatus *sigStatus); // RETURNED - -#ifdef __cplusplus -} -#endif - -#endif /* CRYPTKIT_CIPHERFILE_ENABLE */ -#endif /*_CK_FEECIPHERFILE_H_*/ diff --git a/OSX/libsecurity_cryptkit/lib/feeCipherFileAtom.c b/OSX/libsecurity_cryptkit/lib/feeCipherFileAtom.c deleted file mode 100644 index 3576551d4..000000000 --- a/OSX/libsecurity_cryptkit/lib/feeCipherFileAtom.c +++ /dev/null @@ -1,400 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * feeCipherFile.c - * - * Revision History - * ---------------- - * 10/06/98 ap - * Changed to compile with C++. - * 05 Feb 97 at Apple - * Modified to use portable byte representation. - * 23 Oct 96 at NeXT - * Created. - */ - -#include "feeCipherFile.h" -#include "falloc.h" -#include "platform.h" -#include "feeDebug.h" -#include "byteRep.h" - -#ifndef NULL -#define NULL ((void *)0) -#endif /* NULL */ - -/* - * These must match constants of same name in CipherFileAtom.java. - */ -#define CFILE_MAGIC 0xfeecf111 -#define CFILE_VERSION 1 -#define CFILE_MIN_VERSION 1 - -/* - * Format of a feeCipherFile header. - * Offsets and lengths refer to locations of components in cFileInst.dataRep. - * This struct appears at the start of a feeCipherFile data representation. - */ -typedef struct { - unsigned magic; - unsigned version; - unsigned minVersion; - unsigned totalLength; // equals dataRepLen - cipherFileEncrType encrType; - unsigned cipherTextOffset; // offset of ciphertext - unsigned cipherTextLen; // in bytes - unsigned sendPubKeyDataOffset; // optional - unsigned sendPubKeyDataLen; - unsigned otherKeyDataOffset; // optional - unsigned otherKeyDataLen; - unsigned sigDataOffset; // optional - unsigned sigDataLen; // 0 means no signature - unsigned userData; -} cFileHeader; - -/* - * Private data, represented by a feeCipherFile handle. - */ -typedef struct { - cFileHeader header; - unsigned char *dataRep; // raw data - unsigned dataRepLen; -} cFileInst; - -static unsigned lengthOfByteRepCfileHdr(void); -static unsigned cfileHdrToByteRep(cFileHeader *hdr, - unsigned char *s); -static void byteRepToCfileHdr(const unsigned char *s, - cFileHeader *hdr); - - -/* - * alloc, free cFileInst - */ -static cFileInst *cFileInstAlloc() -{ - cFileInst *cfinst = (cFileInst *) fmalloc(sizeof(cFileInst)); - - bzero(cfinst, sizeof(cFileInst)); - return cfinst; -} - -static void cFileInstFree(cFileInst *cfinst) -{ - if(cfinst->dataRep) { - ffree(cfinst->dataRep); - } - ffree(cfinst); -} - -/* - * Alloc and return a new feeCipherFile object associated with the specified - * data. - */ -feeCipherFile feeCFileNewFromCipherText(cipherFileEncrType encrType, - const unsigned char *cipherText, - unsigned cipherTextLen, - const unsigned char *sendPubKeyData, // optional - unsigned sendPubKeyDataLen, // 0 if sendPubKeyData is NULL - const unsigned char *otherKeyData, // optional - unsigned otherKeyDataLen, // 0 if otherKeyData is NULL - const unsigned char *sigData, // optional; NULL means no signature - unsigned sigDataLen, // 0 if sigData is NULL - unsigned userData) // for caller's convenience -{ - cFileInst *cfinst; - cFileHeader *header; - unsigned char *data; - - if(cipherTextLen == 0) { - return NULL; - } - cfinst = cFileInstAlloc(); - header = &cfinst->header; - - /* - * Init the header. - */ - header->magic = CFILE_MAGIC; - header->version = CFILE_VERSION; - header->minVersion = CFILE_MIN_VERSION; - header->totalLength = lengthOfByteRepCfileHdr() + cipherTextLen + - sendPubKeyDataLen + otherKeyDataLen + - sigDataLen; - header->encrType = encrType; - header->cipherTextOffset = lengthOfByteRepCfileHdr(); - header->cipherTextLen = cipherTextLen; - header->sendPubKeyDataOffset = header->cipherTextOffset + - cipherTextLen; - header->sendPubKeyDataLen = sendPubKeyDataLen; - header->otherKeyDataOffset = header->sendPubKeyDataOffset + - sendPubKeyDataLen; - header->otherKeyDataLen = otherKeyDataLen; - header->sigDataOffset = header->otherKeyDataOffset + - otherKeyDataLen; - header->sigDataLen = sigDataLen; - header->userData = userData; - - /* - * Alloc a data representation, copy various components to it. - */ - cfinst->dataRepLen = header->totalLength; - data = cfinst->dataRep = (unsigned char*) fmalloc(cfinst->dataRepLen); - cfileHdrToByteRep(header, data); - - data = cfinst->dataRep + header->cipherTextOffset; - bcopy(cipherText, data, cipherTextLen); - if(sendPubKeyDataLen) { - data = cfinst->dataRep + header->sendPubKeyDataOffset; - bcopy(sendPubKeyData, data, sendPubKeyDataLen); - } - if(otherKeyDataLen) { - data = cfinst->dataRep + header->otherKeyDataOffset; - bcopy(otherKeyData, data, otherKeyDataLen); - } - if(sigDataLen) { - data = cfinst->dataRep + header->sigDataOffset; - bcopy(sigData, data, sigDataLen); - } - return (feeCipherFile)cfinst; -} - -/* - * Obtain the contents of a feeCipherFile as a byte stream. - */ -feeReturn feeCFileDataRepresentation(feeCipherFile cipherFile, - const unsigned char **dataRep, - unsigned *dataRepLen) -{ - cFileInst *cfinst = (cFileInst *)cipherFile; - - if(cfinst->dataRepLen == 0) { - *dataRep = NULL; - *dataRepLen = 0; - return FR_BadCipherFile; - } - *dataRep = (unsigned char*) fmallocWithData(cfinst->dataRep, cfinst->dataRepLen); - *dataRepLen = cfinst->dataRepLen; - return FR_Success; -} - -/* - * Alloc and return a new feeCipherFile object, given a byte stream (originally - * obtained from feeCFDataRepresentation()). - */ -feeReturn feeCFileNewFromDataRep(const unsigned char *dataRep, - unsigned dataRepLen, - feeCipherFile *cipherFile) // RETURNED if sucessful -{ - cFileInst *cfinst = cFileInstAlloc(); - cFileHeader *header; - - if(dataRepLen < lengthOfByteRepCfileHdr()) { - dbgLog(("datRep too short\n")); - goto abort; - } - cfinst->dataRep = (unsigned char*) fmallocWithData(dataRep, dataRepLen); - cfinst->dataRepLen = dataRepLen; - header = &cfinst->header; - byteRepToCfileHdr(dataRep, header); - - /* - * As much consistency checking as we can manage here. - */ - if(header->magic != CFILE_MAGIC) { - dbgLog(("Bad cipherFile magic number\n")); - goto abort; - } - if(header->minVersion > CFILE_VERSION) { - dbgLog(("Incompatible cipherFile version\n")); - goto abort; - } - if(header->totalLength != dataRepLen) { - dbgLog(("Bad totalLength in cipherFile header\n")); - goto abort; - } - if(((header->cipherTextOffset + header->cipherTextLen) > - header->totalLength) || - ((header->sendPubKeyDataOffset + header->sendPubKeyDataLen) > - header->totalLength) || - ((header->otherKeyDataOffset + header->otherKeyDataLen) > - header->totalLength) || - ((header->sigDataOffset + header->sigDataLen) > - header->totalLength)) { - dbgLog(("Bad element lengths in cipherFile header\n")); - goto abort; - } - - /* - * OK, looks good. - */ - *cipherFile = (feeCipherFile)cfinst; - return FR_Success; -abort: - cFileInstFree(cfinst); - *cipherFile = NULL; - return FR_BadCipherFile; -} - -/* - * Free a feeCipherFile object. - */ -void feeCFileFree(feeCipherFile cipherFile) -{ - cFileInstFree((cFileInst *)cipherFile); -} - -/* - * Given a feeCipherFile object (typically obtained from - * feeCFileNewFromData()), obtain its constituent parts. - * - * Data returned must be freed by caller. - * feeCFileSigData() may return NULL, indicating no signature present. - */ -cipherFileEncrType feeCFileEncrType(feeCipherFile cipherFile) -{ - cFileInst *cfinst = (cFileInst *)cipherFile; - - return cfinst->header.encrType; -} - -unsigned char *feeCFileCipherText(feeCipherFile cipherFile, - unsigned *cipherTextLen) -{ - cFileInst *cfinst = (cFileInst *)cipherFile; - - if(cfinst->header.cipherTextLen) { - *cipherTextLen = cfinst->header.cipherTextLen; - return (unsigned char*) fmallocWithData(cfinst->dataRep + - cfinst->header.cipherTextOffset, *cipherTextLen); - } - else { - dbgLog(("feeCFileCipherText: no cipherText\n")); - *cipherTextLen = 0; - return NULL; - } -} - -unsigned char *feeCFileSendPubKeyData(feeCipherFile cipherFile, - unsigned *sendPubKeyDataLen) -{ - cFileInst *cfinst = (cFileInst *)cipherFile; - - if(cfinst->header.sendPubKeyDataLen) { - *sendPubKeyDataLen = cfinst->header.sendPubKeyDataLen; - return (unsigned char*) fmallocWithData(cfinst->dataRep + - cfinst->header.sendPubKeyDataOffset, - *sendPubKeyDataLen); - } - else { - *sendPubKeyDataLen = 0; - return NULL; - } -} - -unsigned char *feeCFileOtherKeyData(feeCipherFile cipherFile, - unsigned *otherKeyDataLen) -{ - cFileInst *cfinst = (cFileInst *)cipherFile; - - if(cfinst->header.otherKeyDataLen) { - *otherKeyDataLen = cfinst->header.otherKeyDataLen; - return (unsigned char*) fmallocWithData(cfinst->dataRep + - cfinst->header.otherKeyDataOffset, *otherKeyDataLen); - } - else { - *otherKeyDataLen = 0; - return NULL; - } -} - -unsigned char *feeCFileSigData(feeCipherFile cipherFile, - unsigned *sigDataLen) -{ - cFileInst *cfinst = (cFileInst *)cipherFile; - - if(cfinst->header.sigDataLen) { - *sigDataLen = cfinst->header.sigDataLen; - return (unsigned char*) fmallocWithData(cfinst->dataRep + - cfinst->header.sigDataOffset, *sigDataLen); - } - else { - /* - * Not an error - */ - *sigDataLen = 0; - return NULL; - } -} - -unsigned feeCFileUserData(feeCipherFile cipherFile) -{ - cFileInst *cfinst = (cFileInst *)cipherFile; - - return cfinst->header.userData; -} - -/* - * Convert between cFileHeader and portable byte representation. - */ - -/* - * Return size of byte rep of cFileHeader. We just happen to know that - * this is the same size as the header.... - */ -static unsigned lengthOfByteRepCfileHdr(void) -{ - return sizeof(cFileHeader); -} - -static unsigned cfileHdrToByteRep(cFileHeader *hdr, - unsigned char *s) -{ - s += intToByteRep(hdr->magic, s); - s += intToByteRep(hdr->version, s); - s += intToByteRep(hdr->minVersion, s); - s += intToByteRep(hdr->totalLength, s); - s += intToByteRep(hdr->encrType, s); - s += intToByteRep(hdr->cipherTextOffset, s); - s += intToByteRep(hdr->cipherTextLen, s); - s += intToByteRep(hdr->sendPubKeyDataOffset, s); - s += intToByteRep(hdr->sendPubKeyDataLen, s); - s += intToByteRep(hdr->otherKeyDataOffset, s); - s += intToByteRep(hdr->otherKeyDataLen, s); - s += intToByteRep(hdr->sigDataOffset, s); - s += intToByteRep(hdr->sigDataLen, s); - s += intToByteRep(hdr->userData, s); - return sizeof(cFileHeader); -} - -#define DEC_INT(n, b) \ - n = byteRepToInt(b); \ - b += sizeof(int); - -static void byteRepToCfileHdr(const unsigned char *s, - cFileHeader *hdr) -{ - DEC_INT(hdr->magic, s); - DEC_INT(hdr->version, s); - DEC_INT(hdr->minVersion, s); - DEC_INT(hdr->totalLength, s); -// DEC_INT(hdr->encrType, s); - hdr->encrType = (cipherFileEncrType) byteRepToInt(s); - s += sizeof(int); - DEC_INT(hdr->cipherTextOffset, s); - DEC_INT(hdr->cipherTextLen, s); - DEC_INT(hdr->sendPubKeyDataOffset, s); - DEC_INT(hdr->sendPubKeyDataLen, s); - DEC_INT(hdr->otherKeyDataOffset, s); - DEC_INT(hdr->otherKeyDataLen, s); - DEC_INT(hdr->sigDataOffset, s); - DEC_INT(hdr->sigDataLen, s); - DEC_INT(hdr->userData, s); -} diff --git a/OSX/libsecurity_cryptkit/lib/feeDES.c b/OSX/libsecurity_cryptkit/lib/feeDES.c deleted file mode 100644 index 57cc150a8..000000000 --- a/OSX/libsecurity_cryptkit/lib/feeDES.c +++ /dev/null @@ -1,529 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * FeeDES.c - generic, portable DES encryption object - * - * Revision History - * ---------------- - * 10/06/98 ap - * Changed to compile with C++. - * 05 Jan 98 at Apple - * Avoid a bcopy() on encrypt/decrypt of each block - * 31 Mar 97 at Apple - * New per-instance API for DES.c - * 26 Aug 96 at NeXT - * Created. - */ - -#include "ckconfig.h" - -#if CRYPTKIT_SYMMETRIC_ENABLE - -#include "feeDES.h" -#include "feeTypes.h" -#include "ckDES.h" -#include "falloc.h" -#include "feeDebug.h" -#include "feeFunctions.h" -#include "platform.h" -#include - -#ifndef NULL -#define NULL ((void *)0) -#endif /* NULL */ - -typedef struct { - int blockMode; /* default = 0 */ - unsigned char lastBlock[DES_BLOCK_SIZE_BYTES]; /* for CBC */ - struct _desInst dinst; -} fdesInst; - -static void feeDESInit(desInst dinst) -{ - desinit(dinst, DES_MODE_STD); // detects redundant calls -} - -/* - * Alloc and init a feeDES object with specified initial state. - * State must be at least 8 bytes; only 8 bytes are used, ignoring - * MSB of each bytes. - */ -feeDES feeDESNewWithState(const unsigned char *state, - unsigned stateLen) -{ - fdesInst *fdinst; - - if(stateLen < FEE_DES_MIN_STATE_SIZE) { - return NULL; - } - fdinst = (fdesInst*) fmalloc(sizeof(fdesInst)); - bzero(fdinst, sizeof(fdesInst)); - feeDESInit(&fdinst->dinst); - feeDESSetState((feeDES)fdinst, state, stateLen); - return fdinst; -} - -void feeDESFree(feeDES des) -{ - memset(des, 0, sizeof(fdesInst)); - ffree(des); -} - -/* - * Set new initial state. - */ -feeReturn feeDESSetState(feeDES des, - const unsigned char *state, - unsigned stateLen) -{ - fdesInst *fdinst = (fdesInst*) des; - char Key[DES_KEY_SIZE_BYTES_EXTERNAL]; - // 'key' causes problems with - // some weird Unix header - unsigned byte; - - if(stateLen < (DES_KEY_SIZE_BYTES_EXTERNAL)) { - return FR_IllegalArg; - } - bzero(fdinst->lastBlock, DES_BLOCK_SIZE_BYTES); - bcopy(state, Key, DES_KEY_SIZE_BYTES_EXTERNAL); - - /* - * Set up parity bits - */ - for(byte=0; bytedinst, Key); - return FR_Success; -} - -void feeDESSetBlockMode(feeDES des) -{ - fdesInst *fdinst = (fdesInst*) des; - - fdinst->blockMode = 1; -} - -void feeDESSetChainMode(feeDES des) -{ - fdesInst *fdinst = (fdesInst*) des; - - fdinst->blockMode = 0; -} - -unsigned feeDESPlainBlockSize(feeDES des) -{ - return DES_BLOCK_SIZE_BYTES; -} - -unsigned feeDESCipherBlockSize(feeDES des) -{ - return DES_BLOCK_SIZE_BYTES; -} - -unsigned feeDESCipherBufSize(feeDES des) -{ - /* - * Normally DES_BLOCK_SIZE, two blocks for finalBlock - */ - return 2 * DES_BLOCK_SIZE_BYTES; -} - -/* - - * Return the size of ciphertext to hold specified size of plaintext. - - */ - -unsigned feeDESCipherTextSize(feeDES des, unsigned plainTextSize) - -{ - - unsigned blocks = (plainTextSize + DES_BLOCK_SIZE_BYTES - 1) / - DES_BLOCK_SIZE_BYTES; - - if((plainTextSize % DES_BLOCK_SIZE_BYTES) == 0) { - /* - * One more block for resid count - */ - blocks++; - } - - return blocks * DES_BLOCK_SIZE_BYTES; - -} - - -/* - * Key size in bits. - */ -unsigned feeDESKeySize(feeDES des) -{ - return DES_KEY_SIZE_BITS; -} - -/* - * Encrypt a block or less of data. Caller malloc's cipherText. - */ -feeReturn feeDESEncryptBlock(feeDES des, - const unsigned char *plainText, - unsigned plainTextLen, - unsigned char *cipherText, - unsigned *cipherTextLen, // RETURNED - int finalBlock) -{ - fdesInst *fdinst = (fdesInst*) des; - feeReturn frtn = FR_Success; - unsigned cipherLen; - - if(plainTextLen > DES_BLOCK_SIZE_BYTES) { - return FR_IllegalArg; - } - if(plainTextLen) { - /* - * We're called with plainTextLen = 0 and finalBlock - * recursively to clean up last block. - */ - bcopy(plainText, cipherText, plainTextLen); - } - if(plainTextLen < DES_BLOCK_SIZE_BYTES) { - if(!finalBlock) { - /* - * odd-size block only legal last time thru - */ - return FR_IllegalArg; - } - - /* - * Last block, final byte = residual length. - */ - cipherText[DES_BLOCK_SIZE_BYTES - 1] = plainTextLen; - } - - if(!fdinst->blockMode) { - /* - * CBC mode; chain in last cipher word - */ - unsigned char *cp = cipherText; - unsigned char *cp1 = fdinst->lastBlock; - int i; - - for(i=0; idinst, (char *)cipherText); /* Encrypt block */ - if(!fdinst->blockMode){ - /* - * Save outgoing ciphertext for chain - */ - bcopy(cipherText, fdinst->lastBlock, DES_BLOCK_SIZE_BYTES); - } - cipherLen = DES_BLOCK_SIZE_BYTES; - - if(finalBlock) { - if(plainTextLen == DES_BLOCK_SIZE_BYTES) { - /* - * Special case: finalBlock true, plainTextLen == blockSize. - * In this case we generate one more block of ciphertext, - * with a resid length of zero. - */ - unsigned moreCipher; // additional cipherLen - - frtn = feeDESEncryptBlock(des, - NULL, // plainText not used - 0, // resid - cipherText + DES_BLOCK_SIZE_BYTES, // append... - &moreCipher, - 1); - if(frtn == FR_Success) { - cipherLen += moreCipher; - } - - } - if(plainTextLen != 0) { - /* - * Reset internal state in prep for next encrypt/decrypt. - * Note we avoid this in the recursive call (plainTextLen = 0). - */ - bzero(fdinst->lastBlock, DES_BLOCK_SIZE_BYTES); - } - } - - if(frtn == FR_Success) { - *cipherTextLen = cipherLen; - } - return frtn; -} - -/* - * Decrypt a block of data. Caller malloc's plainText. Always - * generates DES_BLOCK_SIZE_BYTES bytes or less of plainText. - */ -feeReturn feeDESDecryptBlock(feeDES des, - const unsigned char *cipherText, - unsigned cipherTextLen, - unsigned char *plainText, - unsigned *plainTextLen, // RETURNED - int finalBlock) -{ - fdesInst *fdinst = (fdesInst*) des; - unsigned char work[DES_BLOCK_SIZE_BYTES]; - unsigned char ivtmp[DES_BLOCK_SIZE_BYTES]; - - if(cipherTextLen != DES_BLOCK_SIZE_BYTES) { - /* - * We always generate ciphertext in multiples of block size. - */ - return FR_IllegalArg; - } - - bcopy(cipherText, work, DES_BLOCK_SIZE_BYTES); - if(!fdinst->blockMode && !finalBlock) { - /* - * Save incoming ciphertext for chain - */ - bcopy(cipherText, ivtmp, DES_BLOCK_SIZE_BYTES); - } - dedes(&fdinst->dinst, (char *)work); - if(!fdinst->blockMode){ - /* - * Unchain block using previous block's ciphertext; - * save current ciphertext for next - */ - char *cp = (char *)work; - char *cp1 = (char*)fdinst->lastBlock; - int i; - - for(i=0; ilastBlock, DES_BLOCK_SIZE_BYTES); - } - } - if(finalBlock) { - /* - * deal with residual block; its size is in last byte of - * work[] - */ - unsigned resid = work[DES_BLOCK_SIZE_BYTES-1]; - - if(resid > (DES_BLOCK_SIZE_BYTES-1)) { - return FR_BadCipherText; - } - if(resid > 0) { - bcopy(work, plainText, resid); - } - *plainTextLen = resid; - - /* - * Reset internal state in prep for next encrypt/decrypt. - */ - bzero(fdinst->lastBlock, DES_BLOCK_SIZE_BYTES); - } - else { - bcopy(work, plainText, DES_BLOCK_SIZE_BYTES); - *plainTextLen = DES_BLOCK_SIZE_BYTES; - } - return FR_Success; -} - -/* - * Convenience routines to encrypt & decrypt multi-block data. - */ -feeReturn feeDESEncrypt(feeDES des, - const unsigned char *plainText, - unsigned plainTextLen, - unsigned char **cipherText, // malloc'd and RETURNED - unsigned *cipherTextLen) // RETURNED -{ - const unsigned char *ptext; // per block - unsigned ptextLen; // total to go - unsigned thisPtextLen; // per block - unsigned ctextLen; // per block - unsigned char *ctextResult; // to return - unsigned char *ctextPtr; - unsigned ctextLenTotal; // running total - feeReturn frtn; - int finalBlock; - unsigned ctextMallocd; - - if(plainTextLen == 0) { - dbgLog(("feeDESDecrypt: NULL plainText\n")); - return FR_IllegalArg; - } - - ptext = plainText; - ptextLen = plainTextLen; - ctextMallocd = feeDESCipherTextSize(des, plainTextLen); - ctextResult = (unsigned char*) fmalloc(ctextMallocd); - ctextPtr = ctextResult; - ctextLenTotal = 0; - - while(1) { - if(ptextLen <= DES_BLOCK_SIZE_BYTES) { - finalBlock = 1; - thisPtextLen = ptextLen; - } - else { - finalBlock = 0; - thisPtextLen = DES_BLOCK_SIZE_BYTES; - } - frtn = feeDESEncryptBlock(des, - ptext, - thisPtextLen, - ctextPtr, - &ctextLen, - finalBlock); - if(frtn) { - dbgLog(("feeDESEncrypt: encrypt error: %s\n", - feeReturnString(frtn))); - break; - } - if(ctextLen == 0) { - dbgLog(("feeDESEncrypt: null ciphertext\n")); - frtn = FR_Internal; - break; - } - ctextLenTotal += ctextLen; - if(ctextLenTotal > (plainTextLen + DES_BLOCK_SIZE_BYTES)) { - dbgLog(("feeDESEncrypt: ciphertext overflow\n")); - frtn = FR_Internal; - break; - } - if(finalBlock) { - break; - } - ctextPtr += ctextLen; - ptext += thisPtextLen; - ptextLen -= thisPtextLen; - } - if(frtn) { - ffree(ctextResult); - *cipherText = NULL; - *cipherTextLen = 0; - } - else { - #if FEE_DEBUG - if(ctextLenTotal != ctextMallocd) { - dbgLog(("feeDESEncrypt: ctextLen error\n")); - } - #endif /* FEE_DEBUG */ - *cipherText = ctextResult; - *cipherTextLen = ctextLenTotal; - } - return frtn; - -} - -feeReturn feeDESDecrypt(feeDES des, - const unsigned char *cipherText, - unsigned cipherTextLen, - unsigned char **plainText, // malloc'd and RETURNED - unsigned *plainTextLen) // RETURNED -{ - const unsigned char *ctext; - unsigned ctextLen; // total to go - unsigned ptextLen; // per block - unsigned char *ptextResult; // to return - unsigned char *ptextPtr; - unsigned ptextLenTotal; // running total - feeReturn frtn = FR_Success; - int finalBlock; - - if(cipherTextLen % DES_BLOCK_SIZE_BYTES) { - dbgLog(("feeDESDecrypt: unaligned cipherText\n")); - return FR_BadCipherText; - } - if(cipherTextLen == 0) { - dbgLog(("feeDESDecrypt: NULL cipherText\n")); - return FR_BadCipherText; - } - - ctext = cipherText; - ctextLen = cipherTextLen; - - /* - * Plaintext length always <= cipherTextLen - */ - ptextResult = (unsigned char*) fmalloc(cipherTextLen); - ptextPtr = ptextResult; - ptextLenTotal = 0; - - while(ctextLen) { - if(ctextLen == DES_BLOCK_SIZE_BYTES) { - finalBlock = 1; - } - else { - finalBlock = 0; - } - frtn = feeDESDecryptBlock(des, - ctext, - DES_BLOCK_SIZE_BYTES, - ptextPtr, - &ptextLen, - finalBlock); - if(frtn) { - dbgLog(("feeDESDecrypt decrypt: %s\n", - feeReturnString(frtn))); - break; - } - if(ptextLen == 0) { - /* - * Normal termination case for - * plainTextLen % DES_BLOCK_SIZE_BYTES == 0 - */ - if(!finalBlock) { - dbgLog(("feeDESDecrypt: decrypt sync" - " error!\n")); - frtn = FR_BadCipherText; - break; - } - else { - break; - } - } - else { - ptextPtr += ptextLen; - ptextLenTotal += ptextLen; - } - ctext += DES_BLOCK_SIZE_BYTES; - ctextLen -= DES_BLOCK_SIZE_BYTES; - } - - if(frtn) { - ffree(ptextResult); - *plainText = NULL; - *plainTextLen = 0; - } - else { - *plainText = ptextResult; - *plainTextLen = ptextLenTotal; - } - return frtn; -} - -#endif /* CRYPTKIT_SYMMETRIC_ENABLE */ diff --git a/OSX/libsecurity_cryptkit/lib/feeDES.h b/OSX/libsecurity_cryptkit/lib/feeDES.h deleted file mode 100644 index 07a8da9cb..000000000 --- a/OSX/libsecurity_cryptkit/lib/feeDES.h +++ /dev/null @@ -1,141 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * FeeDES.h - generic, portable DES encryption object - * - * Revision History - * ---------------- - * 26 Aug 96 at NeXT - * Created. - */ - -#ifndef _CK_FEEDES_H_ -#define _CK_FEEDES_H_ - -#if !defined(__MACH__) -#include -#include -#else -#include -#include -#endif - -#if CRYPTKIT_SYMMETRIC_ENABLE - -#ifdef __cplusplus -extern "C" { -#endif - -#define FEE_DES_MIN_STATE_SIZE 8 - -/* - * Opaque object handle. - */ -typedef void *feeDES; - -/* - * Alloc and init a feeDES object with specified initial state. - * State must be at least 8 bytes; only 8 bytes are used, ignoring - * MSB of each bytes. - */ -feeDES feeDESNewWithState(const unsigned char *state, - unsigned stateLen); - -void feeDESFree(feeDES des); - -/* - * Set new initial state. - */ -feeReturn feeDESSetState(feeDES des, - const unsigned char *state, - unsigned stateLen); - -/* - * Set block or chain (CBC) mode. CBC is default. - */ -void feeDESSetBlockMode(feeDES des); -void feeDESSetChainMode(feeDES des); - -/* - * Plaintext block size. - */ -unsigned feeDESPlainBlockSize(feeDES des); - -/* - * Ciphertext block size used for decryption. - */ -unsigned feeDESCipherBlockSize(feeDES des); - -/* - * Required size of buffer for ciphertext, upon encrypting one - * block of plaintext. - */ -unsigned feeDESCipherBufSize(feeDES des); - -/* - - * Return the size of ciphertext to hold specified size of plaintext. - - */ - -unsigned feeDESCipherTextSize(feeDES des, unsigned plainTextSize); - - -/* - * Key size in bits. - */ -unsigned feeDESKeySize(feeDES des); - -/* - * Encrypt a block or less of data. Caller malloc's cipherText. Generates - * up to (2 * feeDESBlockSize) bytes of cipherText. If plainTextLen is - * less than feeDESBlockSize, finalBlock must be true. - */ -feeReturn feeDESEncryptBlock(feeDES des, - const unsigned char *plainText, - unsigned plainTextLen, - unsigned char *cipherText, - unsigned *cipherTextLen, // RETURNED - int finalBlock); - -/* - * Decrypt (exactly) a block of data. Caller malloc's plainText. Always - * generates feeDESBlockSize bytes of plainText, unless 'finalBlock' is - * non-zero (in which case feeDESBlockSize or less bytes of plainText are - * generated). - */ -feeReturn feeDESDecryptBlock(feeDES des, - const unsigned char *cipherText, - unsigned cipherTextLen, - unsigned char *plainText, - unsigned *plainTextLen, // RETURNED - int finalBlock); - -/* - * Convenience routines to encrypt & decrypt multi-block data. - */ -feeReturn feeDESEncrypt(feeDES des, - const unsigned char *plainText, - unsigned plainTextLen, - unsigned char **cipherText, // malloc'd and RETURNED - unsigned *cipherTextLen); // RETURNED - -feeReturn feeDESDecrypt(feeDES des, - const unsigned char *cipherText, - unsigned cipherTextLen, - unsigned char **plainText, // malloc'd and RETURNED - unsigned *plainTextLen); // RETURNED - -#ifdef __cplusplus -} -#endif - -#endif /* CRYPTKIT_SYMMETRIC_ENABLE */ -#endif /*_CK_FEEDES_H_*/ diff --git a/OSX/libsecurity_cryptkit/lib/feeDigitalSignature.c b/OSX/libsecurity_cryptkit/lib/feeDigitalSignature.c index c2499709e..57775255e 100644 --- a/OSX/libsecurity_cryptkit/lib/feeDigitalSignature.c +++ b/OSX/libsecurity_cryptkit/lib/feeDigitalSignature.c @@ -41,9 +41,7 @@ #include "platform.h" #include "byteRep.h" #include "feeECDSA.h" -#if CRYPTKIT_DER_ENABLE #include "CryptKitDER.h" -#endif #include #include "ellipticProj.h" @@ -70,10 +68,8 @@ int sigDebug=1; // tweakable at runtime via debugger typedef struct { giant PmX; // m 'o' P1; m = random - #if CRYPTKIT_ELL_PROJ_ENABLE giant PmY; // y-coord of m 'o' P1 if we're // using projective coords - #endif /* CRYPTKIT_ELL_PROJ_ENABLE */ giant u; giant randGiant; // random m as giant - only known @@ -144,8 +140,6 @@ feeSig feeSigNewWithKey( /* PmX := randGiant 'o' P1 */ sinst->PmX = newGiant(cp->maxDigits); - #if CRYPTKIT_ELL_PROJ_ENABLE - if(cp->curveType == FCT_Weierstrass) { pointProjStruct pt0; @@ -177,17 +171,6 @@ feeSig feeSigNewWithKey( #pragma clang diagnostic pop elliptic_simple(sinst->PmX, sinst->randGiant, cp); } - #else /* CRYPTKIT_ELL_PROJ_ENABLE */ - - if(SIG_CURVE == CURVE_PLUS) { - gtog(cp->x1Plus, sinst->PmX); - } - else { - gtog(cp->x1Minus, sinst->PmX); - } - elliptic_simple(sinst->PmX, sinst->randGiant, cp); - - #endif /* CRYPTKIT_ELL_PROJ_ENABLE */ return sinst; } @@ -200,12 +183,12 @@ void feeSigFree(feeSig sig) clearGiant(sinst->PmX); freeGiant(sinst->PmX); } - #if CRYPTKIT_ELL_PROJ_ENABLE + if(sinst->PmY) { clearGiant(sinst->PmY); freeGiant(sinst->PmY); } - #endif /* CRYPTKIT_ELL_PROJ_ENABLE */ + if(sinst->u) { clearGiant(sinst->u); freeGiant(sinst->u); @@ -351,19 +334,8 @@ feeReturn feeSigData(feeSig sig, { sigInst *sinst = (sigInst*) sig; - #if CRYPTKIT_DER_ENABLE return feeDEREncodeElGamalSignature(sinst->u, sinst->PmX, sigData, sigDataLen); - #else - *sigDataLen = lengthOfByteRepSig(sinst->u, sinst->PmX); - *sigData = (unsigned char*) fmalloc(*sigDataLen); - sigToByteRep(FEE_SIG_MAGIC, - FEE_SIG_VERSION, - FEE_SIG_VERSION_MIN, - sinst->u, - sinst->PmX, - *sigData); - return FR_Success; - #endif + } /* @@ -377,43 +349,14 @@ feeReturn feeSigParse(const unsigned char *sigData, { sigInst *sinst = NULL; feeReturn frtn; - #if !CRYPTKIT_DER_ENABLE - int version; - int magic; - int minVersion; - int rtn; - #endif sinst = sinstAlloc(); - #if CRYPTKIT_DER_ENABLE + frtn = feeDERDecodeElGamalSignature(sigData, sigDataLen, &sinst->u, &sinst->PmX); if(frtn) { goto abort; } - #else - rtn = byteRepToSig(sigData, - sigDataLen, - FEE_SIG_VERSION, - &magic, - &version, - &minVersion, - &sinst->u, - &sinst->PmX); - if(rtn == 0) { - frtn = FR_BadSignatureFormat; - goto abort; - } - switch(magic) { - case FEE_ECDSA_MAGIC: - frtn = FR_WrongSignatureType; // ECDSA! - goto abort; - case FEE_SIG_MAGIC: - break; // proceed - default: - frtn = FR_BadSignatureFormat; - goto abort; - } - #endif /* CRYPTKIT_DER_ENABLE */ + #if SIG_DEBUG if(sigDebug) { @@ -441,8 +384,6 @@ feeReturn feeSigParse(const unsigned char *sigData, #define LOG_BAD_SIG 0 -#if CRYPTKIT_ELL_PROJ_ENABLE - feeReturn feeSigVerifyNoProj(feeSig sig, const unsigned char *data, unsigned dataLen, @@ -549,12 +490,6 @@ feeReturn feeSigVerify(feeSig sig, return frtn; } -#else /* CRYPTKIT_ELL_PROJ_ENABLE */ - -#define feeSigVerifyNoProj(s, d, l, k) feeSigVerify(s, d, l, k) - -#endif /* CRYPTKIT_ELL_PROJ_ENABLE */ - /* * FEE_SIG_USING_PROJ true : this is the "no Weierstrass" case * feeSigVerifyNoProj false : this is redefined to feeSigVerify @@ -671,10 +606,8 @@ feeReturn feeSigSize( if(cp == NULL) { return FR_BadPubKey; } - #if CRYPTKIT_DER_ENABLE + *maxSigLen = feeSizeOfDERSig(cp->basePrime, cp->basePrime); - #else - *maxSigLen = (unsigned)lengthOfByteRepSig(cp->basePrime, cp->basePrime); - #endif + return FR_Success; } diff --git a/OSX/libsecurity_cryptkit/lib/feeECDSA.c b/OSX/libsecurity_cryptkit/lib/feeECDSA.c index 57736073d..37382a18f 100644 --- a/OSX/libsecurity_cryptkit/lib/feeECDSA.c +++ b/OSX/libsecurity_cryptkit/lib/feeECDSA.c @@ -70,8 +70,6 @@ #include "ckconfig.h" -#if CRYPTKIT_ECDSA_ENABLE - #include "feeTypes.h" #include "feePublicKey.h" #include "feePublicKeyPrivate.h" @@ -90,9 +88,7 @@ #include "feeDigitalSignature.h" #include "ECDSA_Profile.h" #include "ellipticProj.h" -#if CRYPTKIT_DER_ENABLE #include "CryptKitDER.h" -#endif #ifndef ECDSA_VERIFY_ONLY static void ECDSA_encode( @@ -613,22 +609,11 @@ static void ECDSA_encode( unsigned char **sigData, // malloc'd and RETURNED unsigned *sigDataLen) // RETURNED { - #if CRYPTKIT_DER_ENABLE if (format==FSF_RAW) { feeRAWEncodeECDSASignature(groupBytesLen,c, d, sigData, sigDataLen); } else { feeDEREncodeECDSASignature(c, d, sigData, sigDataLen); } - #else - *sigDataLen = lengthOfByteRepSig(c, d); - *sigData = (unsigned char*) fmalloc(*sigDataLen); - sigToByteRep(FEE_ECDSA_MAGIC, - FEE_ECDSA_VERSION, - FEE_ECDSA_VERSION_MIN, - c, - d, - *sigData); - #endif } #endif /* ECDSA_VERIFY_ONLY */ @@ -642,7 +627,6 @@ static feeReturn ECDSA_decode( giant *d, // alloc'd & RETURNED unsigned *sigVersion) // RETURNED { - #if CRYPTKIT_DER_ENABLE feeReturn frtn; if (format==FSF_RAW) { frtn = feeRAWDecodeECDSASignature(groupBytesLen, sigData, sigDataLen, c, d); @@ -653,31 +637,6 @@ static feeReturn ECDSA_decode( *sigVersion = FEE_ECDSA_VERSION; } return frtn; - #else - int magic; - int minVersion; - int rtn; - - rtn = byteRepToSig(sigData, - sigDataLen, - FEE_ECDSA_VERSION, - &magic, - (int *)sigVersion, - &minVersion, - c, - d); - if(rtn == 0) { - return FR_BadSignatureFormat; - } - switch(magic) { - case FEE_ECDSA_MAGIC: - return FR_Success; - case FEE_SIG_MAGIC: // ElGamal sig! - return FR_WrongSignatureType; - default: - return FR_BadSignatureFormat; - } - #endif } /* @@ -696,13 +655,9 @@ feeReturn feeECDSASigSize( if(cp == NULL) { return FR_BadPubKey; } - #if CRYPTKIT_DER_ENABLE + *maxSigLen = feeSizeOfDERSig(cp->basePrime, cp->basePrime); - #else - *maxSigLen = (unsigned)lengthOfByteRepSig(cp->basePrime, cp->basePrime); - #endif return FR_Success; } -#endif /* CRYPTKIT_ECDSA_ENABLE */ diff --git a/OSX/libsecurity_cryptkit/lib/feeECDSA.h b/OSX/libsecurity_cryptkit/lib/feeECDSA.h index fc0cb28b6..7a07be326 100644 --- a/OSX/libsecurity_cryptkit/lib/feeECDSA.h +++ b/OSX/libsecurity_cryptkit/lib/feeECDSA.h @@ -35,8 +35,6 @@ */ #define FEE_ECDSA_MAGIC 0xfee00517 -#if CRYPTKIT_ECDSA_ENABLE - #ifdef __cplusplus extern "C" { #endif @@ -79,6 +77,4 @@ feeReturn feeECDSASigSize( } #endif -#endif /* CRYPTKIT_ECDSA_ENABLE */ - #endif /*_CK_FEEECDSA_H_*/ diff --git a/OSX/libsecurity_cryptkit/lib/feeFEED.c b/OSX/libsecurity_cryptkit/lib/feeFEED.c index 144f73453..9c6ae1d33 100644 --- a/OSX/libsecurity_cryptkit/lib/feeFEED.c +++ b/OSX/libsecurity_cryptkit/lib/feeFEED.c @@ -32,8 +32,6 @@ */ #include "ckconfig.h" -#if CRYPTKIT_ASYMMETRIC_ENABLE - #include "feeTypes.h" #include "feeFEED.h" #include "feeFEEDExp.h" @@ -1230,4 +1228,3 @@ feeReturn feeFEEDDecrypt(feeFEED feed, } -#endif /* CRYPTKIT_ASYMMETRIC_ENABLE */ diff --git a/OSX/libsecurity_cryptkit/lib/feeFEED.h b/OSX/libsecurity_cryptkit/lib/feeFEED.h index ce84de8aa..787dccca2 100644 --- a/OSX/libsecurity_cryptkit/lib/feeFEED.h +++ b/OSX/libsecurity_cryptkit/lib/feeFEED.h @@ -29,8 +29,6 @@ #include #endif -#if CRYPTKIT_ASYMMETRIC_ENABLE - #ifdef __cplusplus extern "C" { #endif @@ -135,6 +133,4 @@ feeReturn feeFEEDDecrypt(feeFEED feed, } #endif -#endif /* CRYPTKIT_ASYMMETRIC_ENABLE */ - #endif /*_CK_FEEFEED_H_*/ diff --git a/OSX/libsecurity_cryptkit/lib/feeFEEDExp.c b/OSX/libsecurity_cryptkit/lib/feeFEEDExp.c index 673289bba..b112e234a 100644 --- a/OSX/libsecurity_cryptkit/lib/feeFEEDExp.c +++ b/OSX/libsecurity_cryptkit/lib/feeFEEDExp.c @@ -32,8 +32,6 @@ #include "ckconfig.h" -#if CRYPTKIT_ASYMMETRIC_ENABLE - #include "feeTypes.h" #include "feeFEEDExp.h" #include "feePublicKey.h" @@ -732,4 +730,3 @@ feeReturn feeFEEDExpDecrypt(feeFEEDExp feed, } -#endif /* CRYPTKIT_ASYMMETRIC_ENABLE */ diff --git a/OSX/libsecurity_cryptkit/lib/feeFEEDExp.h b/OSX/libsecurity_cryptkit/lib/feeFEEDExp.h index aa1903790..22e9b2570 100644 --- a/OSX/libsecurity_cryptkit/lib/feeFEEDExp.h +++ b/OSX/libsecurity_cryptkit/lib/feeFEEDExp.h @@ -29,8 +29,6 @@ #include #endif -#if CRYPTKIT_ASYMMETRIC_ENABLE - #ifdef __cplusplus extern "C" { #endif @@ -121,6 +119,4 @@ feeReturn feeFEEDExpDecrypt(feeFEEDExp feed, } #endif -#endif /* CRYPTKIT_ASYMMETRIC_ENABLE */ - #endif /*_CK_FEEFEEDEXP_H_*/ diff --git a/OSX/libsecurity_cryptkit/lib/feeFunctions.h b/OSX/libsecurity_cryptkit/lib/feeFunctions.h index 928fb5c52..6c41ccfc3 100644 --- a/OSX/libsecurity_cryptkit/lib/feeFunctions.h +++ b/OSX/libsecurity_cryptkit/lib/feeFunctions.h @@ -25,11 +25,7 @@ #ifndef _CK_FEEFUNCTIONS_H_ #define _CK_FEEFUNCTIONS_H_ -#ifdef macintosh -#include -#else #include -#endif #ifdef __cplusplus extern "C" { @@ -45,18 +41,6 @@ void initCryptKit(void); */ void terminateCryptKit(void); -#if defined(NeXT) && !defined(WIN32) - -#define PHRASELEN 128 - -/* - * Prompt for password, get it in secure manner. Max password length is - * PHRASELEN. NEXTSTEP only. - */ -extern void getpassword(const char *prompt, char *pbuf); - -#endif /* NeXT */ - /* * obtain a string describing a feeReturn. */ diff --git a/OSX/libsecurity_cryptkit/lib/feeHash.c b/OSX/libsecurity_cryptkit/lib/feeHash.c index b193af240..7f9e773ed 100644 --- a/OSX/libsecurity_cryptkit/lib/feeHash.c +++ b/OSX/libsecurity_cryptkit/lib/feeHash.c @@ -20,8 +20,6 @@ #include "ckconfig.h" -#if CRYPTKIT_MD5_ENABLE - #include "feeTypes.h" #include "feeHash.h" #include "ckMD5.h" @@ -107,4 +105,3 @@ unsigned feeHashDigestLen(void) return MD5_DIGEST_SIZE; } -#endif /* CRYPTKIT_MD5_ENABLE*/ diff --git a/OSX/libsecurity_cryptkit/lib/feeHash.h b/OSX/libsecurity_cryptkit/lib/feeHash.h index bcb66398a..17134c40a 100644 --- a/OSX/libsecurity_cryptkit/lib/feeHash.h +++ b/OSX/libsecurity_cryptkit/lib/feeHash.h @@ -27,8 +27,6 @@ #include #endif -#if CRYPTKIT_MD5_ENABLE - #ifdef __cplusplus extern "C" { #endif @@ -76,6 +74,4 @@ unsigned feeHashDigestLen(void); } #endif -#endif /* CRYPTKIT_MD5_ENABLE */ - #endif /*_CK_FEEHASH_H_*/ diff --git a/OSX/libsecurity_cryptkit/lib/feePublicKey.c b/OSX/libsecurity_cryptkit/lib/feePublicKey.c index d15f14d0f..ef1435361 100644 --- a/OSX/libsecurity_cryptkit/lib/feePublicKey.c +++ b/OSX/libsecurity_cryptkit/lib/feePublicKey.c @@ -60,11 +60,8 @@ #include "feeECDSA.h" #include "platform.h" #include "enc64.h" -#include "feeDES.h" #include "byteRep.h" -#if CRYPTKIT_DER_ENABLE #include "CryptKitDER.h" -#endif #include /* @@ -86,9 +83,7 @@ #define PUBLIC_KEY_BLOB_VERSION 6 #define PUBLIC_KEY_BLOB_MINVERSION 6 -#if CRYPTKIT_DER_ENABLE #define PUBLIC_DER_KEY_BLOB_VERSION 1 -#endif /* * Private data. All "instance" routines are passed a feePubKey (actually @@ -107,9 +102,7 @@ static feeReturn feeGenPrivate(pubKeyInst *pkinst, char hashPasswd); static pubKeyInst *pubKeyInstAlloc(void); static void pubKeyInstFree(pubKeyInst *pkinst); -#if GIANTS_VIA_STACK -static void feePubKeyInitGiants(void); -#endif + static feeReturn createKeyBlob(pubKeyInst *pkinst, int isPrivate, // 0 : public 1 : private unsigned char **keyBlob, // mallocd and RETURNED @@ -127,9 +120,7 @@ feePubKey feePubKeyAlloc(void) { pubKeyInst *pkinst = pubKeyInstAlloc(); - #if GIANTS_VIA_STACK - feePubKeyInitGiants(); - #endif + return pkinst; } @@ -173,12 +164,6 @@ feeReturn feePubKeyInitFromPrivDataDepth(feePubKey pubKey, pubKeyInst *pkinst = (pubKeyInst *) pubKey; feeReturn frtn; - #if ENGINE_127_BITS - if(depth != FEE_DEPTH_127_1) { - dbgLog(("Illegal Depth\n")); - return FR_IllegalDepth; - } - #endif // ENGINE_127_BITS if(depth > FEE_DEPTH_MAX) { dbgLog(("Illegal Depth\n")); return FR_IllegalDepth; @@ -412,229 +397,6 @@ int feePubKeyIsPrivate(feePubKey key) return ((myPkinst->privGiant != NULL) ? 1 : 0); } -#ifndef ECDSA_VERIFY_ONLY - -#if CRYPTKIT_KEY_EXCHANGE - -feeReturn feePubKeyCreatePad(feePubKey myKey, - feePubKey theirKey, - unsigned char **padData, /* RETURNED */ - unsigned *padDataLen) /* RETURNED padData length in bytes */ -{ - pubKeyInst *myPkinst = (pubKeyInst *) myKey; - pubKeyInst *theirPkinst = (pubKeyInst *) theirKey; - giant pad; - unsigned char *result; - unsigned padLen; - key pkey; - - /* - * Do some compatibility checking (myKey, theirKey) here...? - */ - if(DEFAULT_CURVE == CURVE_PLUS) { - pkey = theirPkinst->plus; - } - else { - pkey = theirPkinst->minus; - } - pad = make_pad(myPkinst->privGiant, pkey); - result = mem_from_giant(pad, &padLen); - freeGiant(pad); - - /* - * Ensure we have a the minimum necessary for DES. A bit of a hack, - * to be sure. - */ - if(padLen >= FEE_DES_MIN_STATE_SIZE) { - *padData = result; - *padDataLen = padLen; - } - else { - *padData = (unsigned char*) fmalloc(FEE_DES_MIN_STATE_SIZE); - *padDataLen = FEE_DES_MIN_STATE_SIZE; - bzero(*padData, FEE_DES_MIN_STATE_SIZE); - bcopy(result, *padData, padLen); - ffree(result); - } - return FR_Success; -} - -#endif /* CRYPTKIT_KEY_EXCHANGE */ - -#if CRYPTKIT_HIGH_LEVEL_SIG - -#warning HLS -/* - * Generate digital signature, ElGamal style. - */ -feeReturn feePubKeyCreateSignature(feePubKey pubKey, - const unsigned char *data, - unsigned dataLen, - unsigned char **signature, /* fmalloc'd and RETURNED */ - unsigned *signatureLen) /* RETURNED */ -{ - pubKeyInst *pkinst = (pubKeyInst *) pubKey; - feeHash hash; - feeSig sig; - unsigned char *Pm = NULL; - unsigned PmLen; - feeReturn frtn; - - if(pkinst->privGiant == NULL) { - dbgLog(("feePubKeyCreateSignature: Attempt to Sign without" - " private data\n")); - return FR_BadPubKey; - } - hash = feeHashAlloc(); - sig = feeSigNewWithKey(pubKey, NULL, NULL); - if(sig == NULL) { - /* - * Shouldn't happen, but... - */ - feeHashFree(hash); - return FR_BadPubKey; - } - - /* - * Get Pm to salt hash object - */ - Pm = feeSigPm(sig, &PmLen); - feeHashAddData(hash, Pm, PmLen); - - /* - * Now hash the data proper, then sign the hash - */ - feeHashAddData(hash, data, dataLen); - frtn = feeSigSign(sig, - feeHashDigest(hash), - feeHashDigestLen(), - pubKey); - if(frtn == FR_Success) { - frtn = feeSigData(sig, signature, signatureLen); - } - feeHashFree(hash); - feeSigFree(sig); - ffree(Pm); - return frtn; -} - -/* - * Verify digital signature, ElGamal style. If the signature is ECDSA, - * we'll use that format for compatibility. - */ -feeReturn feePubKeyVerifySignature(feePubKey pubKey, - const unsigned char *data, - unsigned dataLen, - const unsigned char *signature, - unsigned signatureLen) -{ - feeHash hash; - feeSig sig; - unsigned char *Pm = NULL; - unsigned PmLen; - feeReturn frtn; - - hash = feeHashAlloc(); - frtn = feeSigParse(signature, signatureLen, &sig); - if(frtn) { - feeHashFree(hash); - #if CRYPTKIT_ECDSA_ENABLE - if(frtn == FR_WrongSignatureType) { - return feePubKeyVerifyECDSASignature(pubKey, - data, - dataLen, - signature, - signatureLen); - } - #endif /* CRYPTKIT_ECDSA_ENABLE */ - return frtn; - } - - /* - * Get PM as salt; eat salt, then hash data - */ - Pm = feeSigPm(sig, &PmLen); - feeHashAddData(hash, Pm, PmLen); - feeHashAddData(hash, data, dataLen); - frtn = feeSigVerify(sig, - feeHashDigest(hash), - feeHashDigestLen(), - pubKey); - - feeHashFree(hash); - feeSigFree(sig); - ffree(Pm); - return frtn; -} - -#pragma mark --- ECDSA signature: high level routines --- - -#if CRYPTKIT_ECDSA_ENABLE -/* - * Generate digital signature, ECDSA style. - */ -feeReturn feePubKeyCreateECDSASignature(feePubKey pubKey, - const unsigned char *data, - unsigned dataLen, - unsigned char **signature, /* fmalloc'd and RETURNED */ - unsigned *signatureLen) /* RETURNED */ -{ - pubKeyInst *pkinst = (pubKeyInst *) pubKey; - sha1Obj sha1; - feeReturn frtn; - - if(pkinst->privGiant == NULL) { - dbgLog(("feePubKeyCreateECDSASignature: Attempt to Sign " - "without private data\n")); - return FR_BadPubKey; - } - sha1 = sha1Alloc(); - sha1AddData(sha1, data, dataLen); - frtn = feeECDSASign(pubKey, - sha1Digest(sha1), - sha1DigestLen(), - NULL, // randFcn - NULL, - signature, - signatureLen); - sha1Free(sha1); - return frtn; -} -#endif /* CRYPTKIT_ECDSA_ENABLE */ -#endif /* CRYPTKIT_HIGH_LEVEL_SIG */ -#endif /* ECDSA_VERIFY_ONLY */ - -#if CRYPTKIT_HIGH_LEVEL_SIG - -#if CRYPTKIT_ECDSA_ENABLE - -/* - * Verify digital signature, ECDSA style. - */ -feeReturn feePubKeyVerifyECDSASignature(feePubKey pubKey, - const unsigned char *data, - unsigned dataLen, - const unsigned char *signature, - unsigned signatureLen) -{ - sha1Obj sha1; - feeReturn frtn; - - sha1 = sha1Alloc(); - sha1AddData(sha1, data, dataLen); - frtn = feeECDSAVerify(signature, - signatureLen, - sha1Digest(sha1), - sha1DigestLen(), - pubKey); - sha1Free(sha1); - return frtn; -} - -#endif /* CRYPTKIT_ECDSA_ENABLE */ - -#endif /* CRYPTKIT_HIGH_LEVEL_SIG */ - #pragma mark --- ECDH --- /* @@ -957,22 +719,6 @@ void printPubKey(feePubKey pubKey) void printPubKey(feePubKey pubKey) {} #endif // FEE_DEBUG -/* - * Prime the curveParams and giants modules for quick allocs of giants. - */ -#if GIANTS_VIA_STACK - -static int giantsInitd = 0; - -static void feePubKeyInitGiants(void) -{ - if(giantsInitd) { - return; - } - curveParamsInitGiants(); - giantsInitd = 1; -} -#endif #pragma mark --- Native (custom) key blob formatting --- @@ -1180,7 +926,6 @@ feeReturn feePubKeyInitFromPrivBlob(feePubKey pubKey, #endif /* ECDSA_VERIFY_ONLY */ -#if CRYPTKIT_DER_ENABLE #ifndef ECDSA_VERIFY_ONLY /* @@ -1481,8 +1226,6 @@ feeReturn feePubKeyInitFromOpenSSLBlob( return frtn; } -#endif /* CRYPTKIT_DER_ENABLE */ - /* * ANSI X9.62/Certicom key support. * Public key is 04 || x || y diff --git a/OSX/libsecurity_cryptkit/lib/feePublicKey.h b/OSX/libsecurity_cryptkit/lib/feePublicKey.h index 6f88fa629..c368a66ea 100644 --- a/OSX/libsecurity_cryptkit/lib/feePublicKey.h +++ b/OSX/libsecurity_cryptkit/lib/feePublicKey.h @@ -131,8 +131,6 @@ feeReturn feePubKeyInitFromKeyString(feePubKey pubKey, const char *keyStr, unsigned keyStrLen); -#if CRYPTKIT_DER_ENABLE - /* * DER format support. * Obtain portable public and private DER-encoded key blobs from a key. @@ -196,8 +194,6 @@ feeReturn feePubKeyInitFromOpenSSLBlob( unsigned char *keyBlob, size_t keyBlobLen); -#endif /* CRYPTKIT_DER_ENABLE */ - /* * ANSI X9.62/Certicom key support. * Public key is 04 || x || y @@ -246,69 +242,6 @@ int feePubKeyIsEqual(feePubKey key1, */ int feePubKeyIsPrivate(feePubKey key); -#if CRYPTKIT_KEY_EXCHANGE - -/* - * Generate a pad, for use with symmetric encryption, derived from two keys. - * 'myKey' must be created with private data (via feePubKeyInitFromPrivData() - * or feePubKeyInitFromKey(). - */ -feeReturn feePubKeyCreatePad(feePubKey myKey, - feePubKey theirKey, - unsigned char **padData, /* fmalloc'd & RETURNED */ - unsigned *padDataLen); /* RETURNED padData length in bytes */ - -#endif /* CRYPTKIT_KEY_EXCHANGE */ - -#if CRYPTKIT_HIGH_LEVEL_SIG - -/* - * The following two routines are implemented using primitives in the - * feeHash and feeDigitalSignature objects. - * - * Generate digital signature, ElGamal style. - */ -feeReturn feePubKeyCreateSignature(feePubKey pubKey, - const unsigned char *data, - unsigned dataLen, - unsigned char **signature, /* fmalloc'd and RETURNED */ - unsigned *signatureLen); /* RETURNED */ - -/* - * Verify digital signature, ElGamal style. - */ -feeReturn feePubKeyVerifySignature(feePubKey pubKey, - const unsigned char *data, - unsigned dataLen, - const unsigned char *signature, - unsigned signatureLen); - -#if CRYPTKIT_ECDSA_ENABLE - -/* - * The following two routines are implemented using primitives in the - * feeHash and feeECDSA objects. - * - * Generate digital signature, ECDSA style. - */ -feeReturn feePubKeyCreateECDSASignature(feePubKey pubKey, - const unsigned char *data, - unsigned dataLen, - unsigned char **signature, /* fmalloc'd and RETURNED */ - unsigned *signatureLen); /* RETURNED */ - -/* - * Verify digital signature, ECDSA style. - */ -feeReturn feePubKeyVerifyECDSASignature(feePubKey pubKey, - const unsigned char *data, - unsigned dataLen, - const unsigned char *signature, - unsigned signatureLen); - -#endif /* CRYPTKIT_ECDSA_ENABLE */ - -#endif /* CRYPTKIT_HIGH_LEVEL_SIG */ /* * Diffie-Hellman. Public key is specified either as a feePubKey or diff --git a/OSX/libsecurity_cryptkit/lib/feeRandom.c b/OSX/libsecurity_cryptkit/lib/feeRandom.c index 1fedc6ca4..83ba0a927 100644 --- a/OSX/libsecurity_cryptkit/lib/feeRandom.c +++ b/OSX/libsecurity_cryptkit/lib/feeRandom.c @@ -23,184 +23,46 @@ */ #include "feeRandom.h" -#include "giantIntegers.h" -#include "elliptic.h" -#include "falloc.h" -#include "feeDebug.h" -#include "byteRep.h" -#include #include "platform.h" +#include -/* - * 1 ==> do extra nextNum on feeRandAllocWithSeed() - */ -#define EXTRA_NEXT_NUM 0 - -#define RANDBITS 128 /* must be 0 mod GIANT_BITS_PER_DIGIT */ -#define RAND_GIANT_DIGITS (RANDBITS/GIANT_BITS_PER_DIGIT) - -typedef struct { - giant A; - giant C; - giant SEED; - giant x; -} randInst; - -#if GIANTS_VIA_STACK - -/* - * Prime the curveParams and giants modules for quick allocs of giants. - */ -static int giantsInitd = 0; - -static void feeRandInitGiants() +feeRand feeRandAllocWithSeed(__attribute__((unused)) unsigned seed) { - if(giantsInitd) { - return; - } - curveParamsInitGiants(); - giantsInitd = 1; -} -#endif - -static void pmod(giant x, int bits) { - /* Force x to be x (mod 2^bits). */ - int j; - int digits = bits / GIANT_BITS_PER_DIGIT; - - for(j = (digits-1); j >= 0; j--) { - if(x->n[j] != 0) break; - } - x->sign = j+1; -} - - -feeRand feeRandAllocWithSeed(unsigned seed) -{ - randInst *rinst = (randInst *) fmalloc(sizeof(randInst)); - int digits = RAND_GIANT_DIGITS * 4; - unsigned j; - - #if GIANTS_VIA_STACK - feeRandInitGiants(); - #endif - rinst->SEED = newGiant(digits); - rinst->C = newGiant(digits); - rinst->A = newGiant(digits); - rinst->x = newGiant(digits); - rinst->C->sign = rinst->A->sign = rinst->SEED->sign = RAND_GIANT_DIGITS; - for(j=0; jC->n[j] = (giantDigit)(seed + 0xdddddddd - j); - rinst->A->n[j] = (giantDigit)(seed + 0xfff12223 + j); - rinst->SEED->n[j] = (giantDigit)(seed + j); - } - - /* - * on the first feeRandBytes or feeRandNextNum, bytes 4 and 5 of - * the result are duplicated 4.5 times (up to byte 15). Subsequent - * data is indeed random. Thus... - */ - #if EXTRA_NEXT_NUM - feeRandNextNum(rinst); - #endif // EXTRA_NEXT_NUM - return rinst; + return NULL; } feeRand feeRandAlloc(void) { - return feeRandAllocWithSeed(createRandomSeed()); + return NULL; } -void feeRandFree(feeRand frand) +void feeRandFree(__attribute__((unused)) feeRand frand) { - randInst *rinst = (randInst *) frand; - clearGiant(rinst->A); - freeGiant(rinst->A); - clearGiant(rinst->C); - freeGiant(rinst->C); - clearGiant(rinst->SEED); - freeGiant(rinst->SEED); - clearGiant(rinst->x); - freeGiant(rinst->x); - ffree(rinst); } unsigned feeRandNextNum(feeRand frand) { - randInst *rinst = (randInst *) frand; - unsigned rtn; + unsigned rand; - mulg(rinst->A, rinst->SEED); - addg(rinst->C, rinst->SEED); - pmod(rinst->SEED, RANDBITS); - gtog(rinst->SEED, rinst->x); + feeRandBytes(frand, &rand, sizeof(rand)); - /* - * FIXME - this is not quite correct; rinst->x only has 4 bytes - * of valid data if RANDBITS is known to be greater than or equal - * to 32. - */ - rtn = byteRepToInt((unsigned char *)&rinst->x->n); - return rtn; + return rand; } -void feeRandBytes(feeRand frand, - unsigned char *bytes, /* must be alloc'd by caller */ - unsigned numBytes) +void feeRandBytes(__attribute__((unused)) feeRand frand, void *bytes, unsigned numBytes) { - randInst *rinst = (randInst *) frand; - int length; - unsigned toCopy; - unsigned char *cp = bytes; + int err; - for (length = numBytes; length > 0; length -= RANDBITS/8) { - mulg(rinst->A, rinst->SEED); - addg(rinst->C, rinst->SEED); - pmod(rinst->SEED, RANDBITS); - gtog(rinst->SEED, rinst->x); - - toCopy = RANDBITS/8; - if(length < toCopy) { - toCopy = length; - } - - /* - * FIXME - not 100% platform independent.... - */ - bcopy(rinst->x->n, cp, toCopy); - cp += toCopy; - } + err = SecRandomCopyBytes(kSecRandomDefault, numBytes, bytes); + if (err != errSecSuccess) { + CKRaise("feeRandBytes"); + } } /* new function, 5 March 1999 - dmitch */ -void feeRandAddEntropy(feeRand frand, unsigned entropy) +void feeRandAddEntropy(__attribute__((unused)) feeRand frand, __attribute__((unused)) unsigned entropy) { - randInst *rinst = (randInst *) frand; - giant tmp = borrowGiant(RAND_GIANT_DIGITS); - unsigned i; - - if(entropy == 0) { - /* boy would that be a mistake */ - entropy = 0x12345; - } - for(i=0; in[i] = (giantDigit)entropy; - } - tmp->sign = RAND_GIANT_DIGITS; - mulg(tmp, rinst->SEED); - addg(rinst->C, rinst->SEED); - pmod(rinst->SEED, RANDBITS); - entropy ^= 0xff0ff0ff; - if(entropy == 0) { - entropy = 0x12345; - } - for(i=0; in[i] = (giantDigit)entropy; - } - mulg(tmp, rinst->A); - addg(rinst->C, rinst->A); - pmod(rinst->A, RANDBITS); - /* leave C alone */ - returnGiant(tmp); + } + diff --git a/OSX/libsecurity_cryptkit/lib/feeRandom.h b/OSX/libsecurity_cryptkit/lib/feeRandom.h index 1bffef061..0ae3167dd 100644 --- a/OSX/libsecurity_cryptkit/lib/feeRandom.h +++ b/OSX/libsecurity_cryptkit/lib/feeRandom.h @@ -20,7 +20,7 @@ * Created. */ -#ifndef _CK_FEERANDOM_H_ +#ifndef _CK_FEERANDOM_H_ #define _CK_FEERANDOM_H_ #ifdef __cplusplus @@ -37,8 +37,8 @@ void feeRandFree(feeRand frand); unsigned feeRandNextNum(feeRand frand); void feeRandBytes(feeRand frand, - unsigned char *bytes, /* must be alloc'd by caller */ - unsigned numBytes); + void *bytes, + unsigned numBytes); void feeRandAddEntropy(feeRand frand, unsigned entropy); @@ -46,4 +46,4 @@ void feeRandAddEntropy(feeRand frand, unsigned entropy); } #endif -#endif /* _CK_FEERANDOM_H_ */ +#endif /* _CK_FEERANDOM_H_ */ diff --git a/OSX/libsecurity_cryptkit/lib/feeTypes.h b/OSX/libsecurity_cryptkit/lib/feeTypes.h index 87db4052d..1f31dd04a 100644 --- a/OSX/libsecurity_cryptkit/lib/feeTypes.h +++ b/OSX/libsecurity_cryptkit/lib/feeTypes.h @@ -89,47 +89,6 @@ typedef enum { FCT_General /* Other */ } feeCurveType; -/* - * Some commonly used feeDepth values. In these definitions, q and k are - * from the expression (2^q - k), the base modulus of the curve. The case - * k=1 implies a Mersenne prime as the modulus. - */ -#define FEE_PROTOTYPE_CURVES 0 - -#if FEE_PROTOTYPE_CURVES - - /* q k a b c */ - /* ---- ---- ---- ---- ---- */ -#define FEE_DEPTH_31_1_W 0 /* 31 1 7 1 0 */ -#define FEE_DEPTH_31_1_M 1 /* 31 1 1 0 666 */ -#define FEE_DEPTH_31_1_P 2 /* 31 1 5824692 2067311435 0 */ -#define FEE_DEPTH_40_213 3 /* 40 213 1627500953 523907505 0 */ -#define FEE_DEPTH_127_1 4 /* 127 1 1 0 666 */ -#define FEE_DEPTH_127_1W 5 /* 127 1 666 1 0 */ -#define FEE_DEPTH_160_57 6 /* 160 57 0 3 0 */ -#define FEE_DEPTH_192_1425 7 /* 192 1425 0 -11 0 */ -#define FEE_DEPTH_192_M529891 8 /* 192 -529891 -152 722 0 */ - -/* - * The remaining curves are implemented as PT_GENERAL curves; modulo - * arithmetic does not utilize any FEE or Mersenne optimizations. These - * are here for performance measurements and DVT. - */ -#define FEE_DEPTH_127_GEN 9 /* 127 1 1 0 666 */ -#define FEE_DEPTH_160_GEN 10 /* 160 57 0 3 0 */ -#define FEE_DEPTH_161_GEN 11 /* 161 .. -152 722 0 */ - -/* - * The default depth. - */ -#define FEE_DEPTH_DEFAULT FEE_DEPTH_160_57 - -/* - * Last enumerated depth. - */ -#define FEE_DEPTH_MAX FEE_DEPTH_161_GEN - -#else /* FEE_PROTOTYPE_CURVES */ /* * The real curves as of 4/9/2001. @@ -161,7 +120,6 @@ typedef enum { */ #define FEE_DEPTH_MAX FEE_DEPTH_secp521r1 -#endif /* FEE_PROTOTYPE_CURVES */ /* * Random number generator callback function. diff --git a/OSX/libsecurity_cryptkit/lib/giantIntegers.c b/OSX/libsecurity_cryptkit/lib/giantIntegers.c index d5a195373..b67d833ba 100644 --- a/OSX/libsecurity_cryptkit/lib/giantIntegers.c +++ b/OSX/libsecurity_cryptkit/lib/giantIntegers.c @@ -185,260 +185,20 @@ static void absg(giant g); /* g := |g|. */ * CryptKit without the giant stacks enabled. */ -#if GIANTS_VIA_STACK -#if LOG_GIANT_STACK -#define gstackDbg(x) printf x -#else // LOG_GIANT_STACK -#define gstackDbg(x) -#endif // LOG_GIANT_STACK - -typedef struct { - unsigned numDigits; // capacity of giants in this stack - unsigned numFree; // number of free giants in stack - unsigned totalGiants; // total number in *stack - giant *stack; -} gstack; - -static gstack *gstacks = NULL; // array of stacks -static unsigned numGstacks = 0; // # of elements in gstacks -static int gstackInitd = 0; // this module has been init'd - -#define INIT_NUM_GIANTS 16 /* initial # of giants / stack */ -#define MIN_GIANT_SIZE 4 /* numDigits for gstack[0] */ -#define GIANT_SIZE_INCR 2 /* in << bits */ - -/* - * Initialize giant stacks, with up to specified max giant size. - */ -void initGiantStacks(unsigned maxDigits) -{ - unsigned curSize = MIN_GIANT_SIZE; - unsigned sz; - unsigned i; - - dblog0("initGiantStacks\n"); - - if(gstackInitd) { - /* - * Shouldn't be called more than once... - */ - printf("multiple initGiantStacks calls\n"); - return; - } - gstackDbg(("initGiantStacks(%d)\n", maxDigits)); - - /* - * How many stacks? - */ - numGstacks = 1; - while(curSize<=maxDigits) { - curSize <<= GIANT_SIZE_INCR; - numGstacks++; - } - - sz = sizeof(gstack) * numGstacks; - gstacks = (gstack*) fmalloc(sz); - bzero(gstacks, sz); - - curSize = MIN_GIANT_SIZE; - for(i=0; inumFree; j++) { - freeGiant(gs->stack[j]); - gs->stack[j] = NULL; - } - /* and the stack itself - may be null if this was never used */ - if(gs->stack != NULL) { - ffree(gs->stack); - gs->stack = NULL; - } - } - ffree(gstacks); - gstacks = NULL; - gstackInitd = 0; -} - -#endif // GIANTS_VIA_STACK giant borrowGiant(unsigned numDigits) { giant result; - - #if GIANTS_VIA_STACK - - unsigned stackNum; - gstack *gs = gstacks; - - #if WARN_ZERO_GIANT_SIZE - if(numDigits == 0) { - printf("borrowGiant(0)\n"); - numDigits = gstacks[numGstacks-1].numDigits; - } - #endif // WARN_ZERO_GIANT_SIZE - - /* - * Find appropriate stack - */ - if(numDigits <= MIN_GIANT_SIZE) - stackNum = 0; - else if (numDigits <= (MIN_GIANT_SIZE << GIANT_SIZE_INCR)) - stackNum = 1; - else if (numDigits <= (MIN_GIANT_SIZE << (2 * GIANT_SIZE_INCR))) - stackNum = 2; - else if (numDigits <= (MIN_GIANT_SIZE << (3 * GIANT_SIZE_INCR))) - stackNum = 3; - else if (numDigits <= (MIN_GIANT_SIZE << (4 * GIANT_SIZE_INCR))) - stackNum = 4; - else - stackNum = numGstacks; - - if(stackNum >= numGstacks) { - /* - * out of bounds; just malloc - */ - #if LOG_GIANT_STACK_OVERFLOW - gstackDbg(("giantFromStack overflow; numDigits %d\n", - numDigits)); - #endif // LOG_GIANT_STACK_OVERFLOW - return newGiant(numDigits); - } - gs = &gstacks[stackNum]; - - #if GIANT_MAC_DEBUG - if((gs->numFree != 0) && (gs->stack == NULL)) { - dblog0("borrowGiant: null stack!\n"); - } - #endif - - if(gs->numFree != 0) { - result = gs->stack[--gs->numFree]; - } - else { - /* - * Stack empty; malloc - */ - result = newGiant(gs->numDigits); - } - - #else /* GIANTS_VIA_STACK */ - result = newGiant(numDigits); - #endif /* GIANTS_VIA_STACK */ - PROF_INCR(numBorrows); return result; } void returnGiant(giant g) { - - #if GIANTS_VIA_STACK - - unsigned stackNum; - gstack *gs; - unsigned cap = g->capacity; - - - #if FEE_DEBUG - if(!gstackInitd) { - CKRaise("returnGiant before stacks initialized!"); - } - #endif // FEE_DEBUG - - #if GIANT_MAC_DEBUG - if(g == NULL) { - dblog0("returnGiant: null g!\n"); - } - #endif - - /* - * Find appropriate stack. Note we expect exact match of - * capacity and stack's giant size. - */ - /* - * Optimized unrolled loop. Just make sure there are enough cases - * to handle all of the stacks. Errors in this case will be flagged - * via LOG_GIANT_STACK_OVERFLOW. - */ - switch(cap) { - case MIN_GIANT_SIZE: - stackNum = 0; - break; - case MIN_GIANT_SIZE << GIANT_SIZE_INCR: - stackNum = 1; - break; - case MIN_GIANT_SIZE << (2 * GIANT_SIZE_INCR): - stackNum = 2; - break; - case MIN_GIANT_SIZE << (3 * GIANT_SIZE_INCR): - stackNum = 3; - break; - case MIN_GIANT_SIZE << (4 * GIANT_SIZE_INCR): - stackNum = 4; - break; - default: - stackNum = numGstacks; - break; - } - - if(stackNum >= numGstacks) { - /* - * out of bounds; just free - */ - #if LOG_GIANT_STACK_OVERFLOW - gstackDbg(("giantToStack overflow; numDigits %d\n", cap)); - #endif // LOG_GIANT_STACK_OVERFLOW - freeGiant(g); - return; - } - gs = &gstacks[stackNum]; - if(gs->numFree == gs->totalGiants) { - if(gs->totalGiants == 0) { - gstackDbg(("Initial alloc of gstack(%d)\n", - gs->numDigits)); - gs->totalGiants = INIT_NUM_GIANTS; - } - else { - gs->totalGiants *= 2; - gstackDbg(("Bumping gstack(%d) to %d\n", - gs->numDigits, gs->totalGiants)); - } - gs->stack = (giantstruct**) frealloc(gs->stack, gs->totalGiants*sizeof(giant)); - } - g->sign = 0; // not sure this is important... - gs->stack[gs->numFree++] = g; - - #if GIANT_MAC_DEBUG - if((gs->numFree != 0) && (gs->stack == NULL)) { - dblog0("borrowGiant: null stack!\n"); - } - #endif - - #else /* GIANTS_VIA_STACK */ - freeGiant(g); - - #endif /* GIANTS_VIA_STACK */ } void freeGiant(giant x) { @@ -453,12 +213,8 @@ giant newGiant(unsigned numDigits) { #if WARN_ZERO_GIANT_SIZE if(numDigits == 0) { printf("newGiant(0)\n"); - #if GIANTS_VIA_STACK - numDigits = gstacks[numGstacks-1].totalGiants; - #else /* HACK */ numDigits = 20; - #endif } #endif // WARN_ZERO_GIANT_SIZE @@ -1529,18 +1285,6 @@ void clearGiant(giant g) g->sign = 0; } -#if ENGINE_127_BITS -/* - * only used by engineNSA127.c, which is obsolete as of 16 Jan 1997 - */ -int -scompg(int n, giant g) { - if((g->sign == 1) && (g->n[0] == n)) return(1); - return(0); -} - -#endif // ENGINE_127_BITS - /* */ diff --git a/OSX/libsecurity_cryptkit/lib/giantIntegers.h b/OSX/libsecurity_cryptkit/lib/giantIntegers.h index 34acf7648..cb9082cfc 100644 --- a/OSX/libsecurity_cryptkit/lib/giantIntegers.h +++ b/OSX/libsecurity_cryptkit/lib/giantIntegers.h @@ -64,14 +64,6 @@ typedef unsigned short giantDigit; #define MAX_DIGITS ((1<<18)+(1<<17)) /* 2^(16*MAX_DIGITS)-1 will fit into a giant. */ -/* - * The giant stack package is a local cache which allows us to avoid calls - * to malloc() for borrowGiant(). On a 90 Mhz Pentium, enabling the - * giant stack package shows about a 1.35 speedup factor over an identical - * CryptKit without the giant stacks enabled. - */ -#define GIANTS_VIA_STACK CRYPTKIT_GIANT_STACK_ENABLE - typedef struct { int sign; /* number of giantDigits = abs(sign) */ unsigned capacity; /* largest possible number of giantDigits */ @@ -79,25 +71,6 @@ typedef struct { } giantstruct; typedef giantstruct *giant; -#if GIANTS_VIA_STACK -/* - * For giant stack debug only - * Set default giant size (i.e., for newGiant(0) and borrowGiant(0)) - */ -void setGiantSize(unsigned numDigits); - -/* - * Initialize giant stacks, with up to specified max giant size. - */ -void initGiantStacks(unsigned maxDigits); - -/* - * Free giant stacks on shutdown. - */ -void freeGiantStacks(void); - -#endif /* GIANTS_VIA_STACK */ - giant newGiant(unsigned numDigits); giant copyGiant(giant x); void freeGiant(giant x); diff --git a/OSX/libsecurity_cryptkit/lib/giantPortCommon.h b/OSX/libsecurity_cryptkit/lib/giantPortCommon.h index a5d1de926..ca381fd5c 100644 --- a/OSX/libsecurity_cryptkit/lib/giantPortCommon.h +++ b/OSX/libsecurity_cryptkit/lib/giantPortCommon.h @@ -27,15 +27,6 @@ * inline C functions */ #include "giantPort_Generic.h" -#elif defined(__ppc__) && defined(__MACH__) -/* Mac OS X, PPC, Gnu compiler */ -#include "giantPort_PPC_Gnu.h" - -#elif defined(__ppc__ ) && defined(macintosh) - -/* Mac OS 9, PPC, Metrowerks */ -#include "giantPort_PPC.h" - #else /* Others */ diff --git a/OSX/libsecurity_cryptkit/lib/giantPort_PPC.c b/OSX/libsecurity_cryptkit/lib/giantPort_PPC.c deleted file mode 100644 index c9b264509..000000000 --- a/OSX/libsecurity_cryptkit/lib/giantPort_PPC.c +++ /dev/null @@ -1,236 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * giantPort_PPC.c - PPC-dependent giant definitions. - * - * Revision History - * ---------------- - * 10/06/98 ap - * Changed to compile with C++. - * 06 Apr 1998 at Apple - * Created. - */ - -#include "feeDebug.h" -#include "platform.h" -#include "giantPort_PPC.h" - -#if !PPC_GIANT_PORT_INLINE - - -/* - * Multiple-precision arithmetic routines/macros. - */ - -asm giantDigit giantAddDigits( - register giantDigit dig1, - register giantDigit dig2, - register giantDigit *carry) /* RETURNED, 0 or 1 */ - -{ - /* - * dig1 : r3 - * dig2 : r4 - * carry : r5 - * sum : r6 - */ - - /* sum = dig1 + dig2 */ - add r6, dig1, dig2; - - /* if((sum < dig1) || (sum < dig2)) */ - cmpl crf0,0,r6,dig1 - bc 12,0,*+12 - cmpl crf0,0,r6,dig2 - bc 4,0,*+16 - - /* *carry = 1; */ - li r7,1 - stw r7, 0(r5) - b *+12 - - /* else *carry = 0; */ - li r7,0 - stw r7, 0(r5) - - /* return sum in r3 */ - mr. r3,r6 - blr -} - -/* - * Add a single digit value to a double digit accumulator in place. - * Carry out of the MSD of the accumulator is not handled. - * This should work any size giantDigits up to unsigned int. - */ -asm void giantAddDouble( - register giantDigit *accLow, /* IN/OUT */ - register giantDigit *accHigh, /* IN/OUT */ - register giantDigit val) -{ - /* - * r3 : accLow - * r4 : accHi - * r5 : val - * r6 : sumLo - * r7 : *accLow - */ - - /* giantDigit sumLo = *accLow + val; */ - lwz r7,0(accLow) - add r6,r7,val - - /* if((sumLo < *accLow) || (sumLo < val)) { */ - cmpl crf0,0,r6,r7 - bc 12,0,*+12 - cmpl crf0,0,r6,val - bc 4,0,*+16 - - /* (*accHigh)++; */ - lwz r7, 0(accHigh) - addi r7,r7,1 - stw r7, 0(accHigh) - - /* *accLow = sumLo; */ - stw r6,0(accLow) - blr -} - -asm giantDigit giantSubDigits( - register giantDigit a, - register giantDigit b, - register giantDigit *borrow) /* RETURNED, 0 or 1 */ - -{ - /* a : r3 - b : r4 - borrow : r5 - diff : r6 */ - - /* giantDigit diff = a - b; */ - subf r6, b, a; - - /* if(a < b) */ - cmpl crf0,0,a,b - bc 4,0,*+16 - - /* *borrow = 1; */ - li r7,1 - stw r7, 0(borrow) - b *+12 - - /* else *borrow = 0; */ - li r7,0 - stw r7, 0(borrow) - - /* return diff in r3 */ - mr. r3,r6 - blr -} - -asm void giantMulDigits( - register giantDigit dig1, - register giantDigit dig2, - register giantDigit *lowProduct, /* RETURNED, low digit */ - register giantDigit *hiProduct) /* RETURNED, high digit */ -{ - /* r3 : dig1 - r4 : dig2 - r5 : lowProduct - r6 : hiProduct */ - - /* dprod = (unsigned long long)dig1 * (unsigned long long)dig2; */ - mullw r7, dig1, dig2 /* r7 = low(dig1 * dig2) */ - mulhwu r8, dig1, dig2 /* r8 - hi(dig1 * dig2) */ - - /* *hiProduct = (giantDigit)(dprod >> GIANT_BITS_PER_DIGIT); */ - stw r8, 0(hiProduct) - - /* *lowProduct = (giantDigit)dprod; */ - stw r7, 0(lowProduct) - blr -} - -asm giantDigit VectorMultiply( - register giantDigit plierDigit, /* r3 */ - register giantDigit *candVector, /* r4 */ - register unsigned candLength, /* r5 */ - register giantDigit *prodVector) /* r6 */ -{ - register unsigned candDex; /* index into multiplicandVector */ - register giantDigit lastCarry; - register giantDigit prodLo; - register giantDigit prodHi; - register unsigned scr1; - register unsigned sumLo; - - fralloc - - /* giantDigit lastCarry = 0; */ - li lastCarry,0 - - - /* for(candDex=0; candDex scr1 */ - addi candVector,candVector,4 /* candVector++ */ - - mullw prodLo,scr1,plierDigit /* prodLo = low(*candVector * plierDigit) */ - mulhwu prodHi,scr1,plierDigit /* prodHi = high(*candVector * plierDigit) */ - - /* giantAddDouble(&prodLo, &prodHi, *prodVector); */ - lwz scr1,0(prodVector) /* *prodVector --> r9 */ - add sumLo,prodLo,scr1 /* prodLo + *prodVector --> sumLo */ - cmpl crf0,0,sumLo,prodLo /* sumLo < prodLo? */ - bc 12,0,_carry1 - cmpl crf0,0,sumLo,scr1 /* sumLo < *prodVector? */ - bc 4,0,_noCar1 -_carry1: - addi prodHi,prodHi,1 /* prodHi++ */ -_noCar1: - mr. prodLo,sumLo /* prodLo := sumLo */ - - /* giantAddDouble(&prodLo, &prodHi, lastCarry); */ - add sumLo,sumLo,lastCarry /* sumLo += lastCarry */ - cmpl crf0,0,sumLo,prodLo /* sumLo < prodLo? */ - bc 12,0,_carry2 - cmpl crf0,0,sumLo,lastCarry /* sumLo < lastCarry? */ - bc 4,0,_noCar2 -_carry2: - addi prodHi,prodHi,1 /* prodHi++ */ -_noCar2: - mr. prodLo,sumLo /* prodLo := sumLo */ - - /* *(prodVector++) = prodLo; */ - stw prodLo,0(prodVector) /* prodLo --> *prodVector */ - addi prodVector,prodVector,4 /* prodVector++ */ - - /* lastCarry = prodHi; */ - mr. lastCarry,prodHi - - /* } */ - addi candDex,candDex,1 /* candDex++ */ -_endLoop: - cmpl crf0,0,candDex,candLength /* candDex < candLength? */ - bc 12,0,_topLoop - - /* return lastCarry; */ - mr. r3,lastCarry /* return lastCarry in r3 */ - frfree - blr -} - -#endif // PPC_GIANT_PORT_INLINE diff --git a/OSX/libsecurity_cryptkit/lib/giantPort_PPC.h b/OSX/libsecurity_cryptkit/lib/giantPort_PPC.h deleted file mode 100644 index 44ebeb3b6..000000000 --- a/OSX/libsecurity_cryptkit/lib/giantPort_PPC.h +++ /dev/null @@ -1,119 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * giantPort_PPC.h - PPC-dependent giant definitions. - * - * Revision History - * ---------------- - * 10/06/98 ap - * Changed to compile with C++. - * 06 Apr 1998 at Apple - * Created. - */ - -#ifndef _CK_NSGIANT_PORT_PPC_H_ -#define _CK_NSGIANT_PORT_PPC_H_ - -#include "feeDebug.h" -#include "platform.h" -#include "giantIntegers.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/**** FIXME - implement asm giant digits! ****/ -/* - * 0 ==> use function declarations from this file and implementation - * in giantPort_PPC.c - * 1 ==> use static inline C function in giantPort_Generic.h - */ -/*@@@ HACK @@@ -#if defined NeXT -#define PPC_GIANT_PORT_INLINE 1 -#else -#define PPC_GIANT_PORT_INLINE 0 -#endif -*/ -#define PPC_GIANT_PORT_INLINE 1 - -#if PPC_GIANT_PORT_INLINE - -#include "giantPort_Generic.h" - -#else // PPC_GIANT_PORT_INLINE - -/* - * We'll be using the compiler's 64-bit long long for these routines. - * - * Mask for upper word. - */ -#define GIANT_UPPER_DIGIT_MASK (~(unsigned long long(GIANT_DIGIT_MASK))) - -/* - * Multiple-precision arithmetic routines/macros. C for now, eventually - * they'll be in assembly. - */ - -/* - * Add two digits, return sum. Carry bit returned as an out parameter. - * This should work any size giantDigits up to unsigned int. - */ -extern giantDigit giantAddDigits( - giantDigit dig1, - giantDigit dig2, - giantDigit *carry); /* RETURNED, 0 or 1 */ - -/* - * Add a single digit value to a double digit accumulator in place. - * Carry out of the MSD of the accumulator is not handled. - */ -void giantAddDouble( - giantDigit *accLow, /* IN/OUT */ - giantDigit *accHigh, /* IN/OUT */ - giantDigit val); - - -/* - * Subtract a - b, return difference. Borrow bit returned as an out parameter. - */ -giantDigit giantSubDigits( - giantDigit a, - giantDigit b, - giantDigit *borrow); /* RETURNED, 0 or 1 */ - - -/* - * Multiply two digits, return two digits. - */ -void giantMulDigits( - giantDigit dig1, - giantDigit dig2, - giantDigit *lowProduct, /* RETURNED, low digit */ - giantDigit *hiProduct); /* RETURNED, high digit */ - -/* - * Multiply a vector of giantDigits, candVector, by a single giantDigit, - * plierDigit, adding results into prodVector. Returns m.s. digit from - * final multiply; only candLength digits of *prodVector will be written. - */ -giantDigit VectorMultiply( - giantDigit plierDigit, - giantDigit *candVector, - unsigned candLength, - giantDigit *prodVector); - -#ifdef __cplusplus -} -#endif - -#endif /* !PPC_GIANT_PORT_INLINE */ - -#endif /*_CK_NSGIANT_PORT_PPC_H_*/ diff --git a/OSX/libsecurity_cryptkit/lib/giantPort_PPC_Gnu.h b/OSX/libsecurity_cryptkit/lib/giantPort_PPC_Gnu.h deleted file mode 100644 index 3676da990..000000000 --- a/OSX/libsecurity_cryptkit/lib/giantPort_PPC_Gnu.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * giantPort_PPC_Gnu.h - giant definitions, PPC/GNU version. - */ - -#ifndef _CK_NSGIANT_PORT_PPC_GNU_H_ -#define _CK_NSGIANT_PORT_PPC_GNU_H_ - -#include "feeDebug.h" -#include "platform.h" -#include "giantIntegers.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* define this true to disable this module and use generic C versions instead */ -#define PPC_GIANT_PORT_INLINE 0 - -#if PPC_GIANT_PORT_INLINE - -#include "giantPort_Generic.h" - -#else // PPC_GIANT_PORT_INLINE - -/* - * Multiple-precision arithmetic routines/macros implemented in - * giantPort_PPC_Gnu.s - */ - -/* - * Add two digits, return sum. Carry bit returned as an out parameter. - */ -extern giantDigit giantAddDigits( - giantDigit dig1, - giantDigit dig2, - giantDigit *carry); /* RETURNED, 0 or 1 */ - -/* - * Add a single digit value to a double digit accumulator in place. - * Carry out of the MSD of the accumulator is not handled. - */ -void giantAddDouble( - giantDigit *accLow, /* IN/OUT */ - giantDigit *accHigh, /* IN/OUT */ - giantDigit val); - - -/* - * Subtract a - b, return difference. Borrow bit returned as an out parameter. - */ -giantDigit giantSubDigits( - giantDigit a, - giantDigit b, - giantDigit *borrow); /* RETURNED, 0 or 1 */ - - -/* - * Multiply two digits, return two digits. - */ -void giantMulDigits( - giantDigit dig1, - giantDigit dig2, - giantDigit *lowProduct, /* RETURNED, low digit */ - giantDigit *hiProduct); /* RETURNED, high digit */ - -/* - * Multiply a vector of giantDigits, candVector, by a single giantDigit, - * plierDigit, adding results into prodVector. Returns m.s. digit from - * final multiply; only candLength digits of *prodVector will be written. - */ -giantDigit VectorMultiply( - giantDigit plierDigit, - giantDigit *candVector, - unsigned candLength, - giantDigit *prodVector); - -#ifdef __cplusplus -} -#endif - -#endif /* !PPC_GIANT_PORT_INLINE */ - -#endif /*_CK_NSGIANT_PORT_PPC_GNU_H_*/ diff --git a/OSX/libsecurity_cryptkit/lib/giantPort_PPC_Gnu.s b/OSX/libsecurity_cryptkit/lib/giantPort_PPC_Gnu.s deleted file mode 100644 index 1319b53a9..000000000 --- a/OSX/libsecurity_cryptkit/lib/giantPort_PPC_Gnu.s +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright (c) 2001,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@ - */ - - -/* - * As of 3/19/2001, using this module results in no change in runtime - * performance compared to using the inline C functions in - * giantPort_Generic.h. Examination of the compiled code shows that - * the GNU C compiler, when configured for -O2, generates almost - * exactly the same code as we have here. - * We'll leave this code in, to protect against changes in gcc, changes - * in CFLAGS, and to serve as an example for other PPC implementations. - */ - -#if defined(__ppc__) && defined(__MACH__) - -/********************************************* - -Add two digits, return sum. Carry bit returned as an out parameter. - -giantDigit giantAddDigits( - register giantDigit dig1, - register giantDigit dig2, - register giantDigit *carry) ...RETURNED, 0 or 1 -**********************************************/ - .text - .align 2 -.globl _giantAddDigits -_giantAddDigits: - /* - * dig1 : r3 - * dig2 : r4 - * carry : r5 - * sum : r6 - */ - - /* sum = dig1 + dig2 */ - add r6, r3, r4; - - /* if((sum < dig1) || (sum < dig2)) */ - cmplw cr0,r6,r3 - blt L1 - cmplw cr0,r6,r4 - bge L2 - -L1: - /* *carry = 1; */ - li r7,1 - stw r7, 0(r5) - b L3 - -L2: - /* else *carry = 0; */ - li r7,0 - stw r7, 0(r5) - -L3: - /* return sum in r3 */ - mr. r3,r6 - blr - -/********************************************* - -Add a single digit value to a double digit accumulator in place. -Carry out of the MSD of the accumulator is not handled. - -void giantAddDouble( - giantDigit *accLow, -- IN/OUT - giantDigit *accHigh, -- IN/OUT - giantDigit val); -**********************************************/ - - .align 2 -.globl _giantAddDouble -_giantAddDouble: - /* - * r3 : accLow - * r4 : accHi - * r5 : val - * r6 : sumLo - * r7 : *accLow - */ - - /* giantDigit sumLo = *accLow + val; */ - lwz r7,0(r3) - add r6,r7,r5 - - /* if((sumLo < *accLow) || (sumLo < val)) { */ - cmplw cr0,r6,r7 - blt L10 - cmplw cr0,r6,r5 - bge L11 - -L10: - /* (*accHigh)++; */ - lwz r7, 0(r4) - addi r7,r7,1 - stw r7, 0(r4) - -L11: - /* *accLow = sumLo; */ - stw r6,0(r3) - blr - -/***************************************************************************** - -Subtract a - b, return difference. Borrow bit returned as an out parameter. - -giantDigit giantSubDigits( - giantDigit a, - giantDigit b, - giantDigit *borrow) -- RETURNED, 0 or 1 - -******************************************************************************/ - - .align 2 -.globl _giantSubDigits -_giantSubDigits: - - /* a : r3 - b : r4 - borrow : r5 - diff : r6 */ - - /* giantDigit diff = a - b; */ - subf r6, r4, r3; - - /* if(a < b) */ - cmplw cr0,r3,r4 - bge L20 - - /* *borrow = 1; */ - li r7,1 - stw r7, 0(r5) - b L21 - -L20: - /* else *borrow = 0; */ - li r7,0 - stw r7, 0(r5) - -L21: - /* return diff in r3 */ - mr. r3,r6 - blr - -/***************************************************************************** - -Multiply two digits, return two digits. - -void giantMulDigits( - giantDigit dig1, - giantDigit dig2, - giantDigit *lowProduct, -- RETURNED, low digit - giantDigit *hiProduct) -- RETURNED, high digit - -******************************************************************************/ - - .align 2 -.globl _giantMulDigits -_giantMulDigits: - - /* r3 : dig1 - r4 : dig2 - r5 : lowProduct - r6 : hiProduct */ - - /* dprod = (unsigned long long)dig1 * (unsigned long long)dig2; */ - mullw r7, r3, r4 /* r7 = low(dig1 * dig2) */ - mulhwu r8, r3, r4 /* r8 - hi(dig1 * dig2) */ - - /* *hiProduct = (giantDigit)(dprod >> GIANT_BITS_PER_DIGIT); */ - stw r8, 0(r6) - - /* *lowProduct = (giantDigit)dprod; */ - stw r7, 0(r5) - blr - - -/***************************************************************************** - -Multiply a vector of giantDigits, candVector, by a single giantDigit, -plierDigit, adding results into prodVector. Returns m.s. digit from -final multiply; only candLength digits of *prodVector will be written. - -giantDigit VectorMultiply( - giantDigit plierDigit, - giantDigit *candVector, - unsigned candLength, - giantDigit *prodVector) - -******************************************************************************/ - -/* - * Register definitions - * Input paramters: - */ -#define plierDigit r3 -#define candVector r4 -#define candLength r5 -#define prodVector r6 - -/* - * PPC ABI specifies: - * r3..r10 for parameter passing - * r11, r12 volatile (caller saved, we can write) - * - * We'll use the remainder of the registers normally used for parameter passing - * and also the other volatile register for local variables. - */ -#define candDex r7 -#define lastCarry r8 -#define prodLo r9 -#define prodHi r10 -#define scr1 r11 -#define sumLo r12 - - .align 2 -.globl _VectorMultiply -_VectorMultiply: - - /* giantDigit lastCarry = 0; */ - li lastCarry,0 - - - /* for(candDex=0; candDex scr1 */ - addi candVector,candVector,4 /* candVector++ */ - - mullw prodLo,scr1,plierDigit /* prodLo = low(*candVector * plierDigit) */ - mulhwu prodHi,scr1,plierDigit /* prodHi = high(*candVector * plierDigit) */ - - /* giantAddDouble(&prodLo, &prodHi, *prodVector); */ - lwz scr1,0(prodVector) /* *prodVector --> r9 */ - add sumLo,prodLo,scr1 /* prodLo + *prodVector --> sumLo */ - cmplw cr0,sumLo,prodLo /* sumLo < prodLo? */ - blt L_carry1 - cmplw cr0,sumLo,scr1 /* sumLo < *prodVector? */ - bge L_noCar1 -L_carry1: - addi prodHi,prodHi,1 /* prodHi++ */ -L_noCar1: - mr. prodLo,sumLo /* prodLo := sumLo */ - - /* giantAddDouble(&prodLo, &prodHi, lastCarry); */ - add sumLo,sumLo,lastCarry /* sumLo += lastCarry */ - cmplw cr0,sumLo,prodLo /* sumLo < prodLo? */ - blt L_carry2 - cmplw cr0,sumLo,lastCarry /* sumLo < lastCarry? */ - bge L_noCar2 -L_carry2: - addi prodHi,prodHi,1 /* prodHi++ */ -L_noCar2: - mr. prodLo,sumLo /* prodLo := sumLo */ - - /* *(prodVector++) = prodLo; */ - stw prodLo,0(prodVector) /* prodLo --> *prodVector */ - addi prodVector,prodVector,4 /* prodVector++ */ - - /* lastCarry = prodHi; */ - mr. lastCarry,prodHi - - /* } */ - addi candDex,candDex,1 /* candDex++ */ -L_endLoop: - cmplw cr0,candDex,candLength /* candDex < candLength? */ - blt L_topLoop - - /* return lastCarry; */ - mr. r3,lastCarry /* return lastCarry in r3 */ - blr - -#endif /* defined(__ppc__) && defined(__MACH__) */ diff --git a/OSX/libsecurity_cryptkit/lib/giantPort_i486.h b/OSX/libsecurity_cryptkit/lib/giantPort_i486.h deleted file mode 100644 index b0e74f7b9..000000000 --- a/OSX/libsecurity_cryptkit/lib/giantPort_i486.h +++ /dev/null @@ -1,126 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * giantPorti486.h - OpenStep-dependent giant definitions. - * - * Revision History - * ---------------- - * 06 Apr 1998 at Apple - * Created. - */ - -#ifndef _CK_NSGIANT_PORT_I486_H_ -#define _CK_NSGIANT_PORT_I486_H_ - -#include "giantIntegers.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Add two digits, return sum. Carry bit returned as an out parameter. - */ -static inline giantDigit giantAddDigits( - giantDigit dig1, - giantDigit dig2, - giantDigit *carry) /* RETURNED, 0 or 1 */ -{ - giantDigit _sum; /* r/w %0 */ - asm volatile( - "movl %2, %0 /* _sum = dig1 */ \n" - "addl %3, %0 /* _sum += dig2 */ \n" - "jc .+9 \n" - "movl $0, %1 /* carry = 0 */ \n" - "jmp .+7 \n" - "movl $1, %1 /* carry = 1 */ \n" - : "=&r" (_sum), "=&r" (*carry) - : "r" (dig1), "r" (dig2)); - return _sum; -} - -/* - * Add a single digit value to a double digit accumulator in place. - * Carry out of the MSD of the accumulator is not handled. - */ -static inline void giantAddDouble( - giantDigit *accLow, /* IN/OUT */ - giantDigit *accHigh, /* IN/OUT */ - giantDigit val) -{ - asm volatile( - "addl %4, %0 /* accLow += val */ \n" - "jnc .+3 \n" - "incl %1 /* accHigh++ */ \n" - : "=&r" (*accLow), "=&r" (*accHigh) - : "0" (*accLow), "1" (*accHigh), "r" (val)); -} - -/* - * Subtract a - b, return difference. Borrow bit returned as an out parameter. - */ -static inline giantDigit giantSubDigits( - giantDigit a, - giantDigit b, - giantDigit *borrow) /* RETURNED, 0 or 1 */ -{ - giantDigit _diff; /* r/w %0 */ - asm volatile( - "movl %2, %0 /* _diff = a */ \n" - "subl %3, %0 /* _diff -= b */ \n" - "jc .+9 \n" - "movl $0, %1 /* borrow = 0 */ \n" - "jmp .+7 \n" - "movl $1, %1 /* borrow = 1 */ \n" - : "=&r" (_diff), "=&r" (*borrow) - : "r" (a), "r" (b)); - return _diff; -} - -/* - * Multiply two digits, return two digits. - */ -static inline void giantMulDigits( - giantDigit dig1, - giantDigit dig2, - giantDigit *lowProduct, // RETURNED, low digit - giantDigit *hiProduct) // RETURNED, high digit - -{ - asm volatile( - "movl %2, %%eax /* eax = dig1 */ \n" - "movl %3, %%edx /* edx = dig2 */ \n" - "mull %%edx /* eax *= dig2 */ \n" - : "=&a" (*lowProduct), "=&d" (*hiProduct) - : "r" (dig1), "r" (dig2) - : "%eax", "%edx" ); -} - -/* - * Multiply a vector of giantDigits, candVector, by a single giantDigit, - * plierDigit, adding results into prodVector. Returns m.s. digit from - * final multiply; only candLength digits of *prodVector will be written. - * - * This one's implemented in a .s file. - */ -extern giantDigit vectorMult_x86( - giantDigit plierDigit, - giantDigit *candVector, - unsigned candLength, - giantDigit *prodVector); - -#define VectorMultiply(pd, cv, cl, pv) vectorMult_x86(pd, cv, cl, pv) - - -#ifdef __cplusplus -} -#endif - -#endif _CK_NSGIANT_PORT_I486_H_ diff --git a/OSX/libsecurity_cryptkit/lib/mutils.h b/OSX/libsecurity_cryptkit/lib/mutils.h deleted file mode 100644 index 57023f742..000000000 --- a/OSX/libsecurity_cryptkit/lib/mutils.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * mutils.h - general private ObjC routine declarations - * - * Revision History - * ---------------- - * 2 Aug 96 at NeXT - * Broke out from Blaine Garst's original NSCryptors.m - */ - -#ifndef _CK_MUTILS_H_ -#define _CK_MUTILS_H_ - -#include -#include "giantIntegers.h" - -#ifdef __cplusplus -extern "C" { -#endif - -extern NSMutableData *data_with_giant(giant u); -extern void canonicalize_data(NSMutableData *data); - -#ifdef __cplusplus -} -#endif - -#endif /*_CK_MUTILS_H_*/ diff --git a/OSX/libsecurity_cryptkit/lib/mutils.m b/OSX/libsecurity_cryptkit/lib/mutils.m deleted file mode 100644 index 129c905c3..000000000 --- a/OSX/libsecurity_cryptkit/lib/mutils.m +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. - * - * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT - * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE - * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE - * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, - * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL - * EXPOSE YOU TO LIABILITY. - *************************************************************************** - * - * mutils.m - general private ObjC routine declarations - * - * Revision History - * ---------------- - * 2 Aug 96 at NeXT - * Broke out from Blaine Garst's original NSCryptors.m - */ - -#import -#import "giantIntegers.h" -#import "ckutilities.h" -#import "mutils.h" -#import "feeFunctions.h" -#import - -#if defined(NeXT) && !defined(WIN32) - -/* - * Public, declared in NSCryptors.h - */ -NSString *NSPromptForPassPhrase(NSString *prompt) { - // useful for command line (/dev/tty) programs - char buffer[PHRASELEN]; - NSString *result; - - getpassword([prompt cString], buffer); - if (buffer[0] == 0) return nil; - result = [NSString stringWithCString:buffer]; - bzero(buffer, PHRASELEN); - return result; -} - - -#endif NeXT diff --git a/OSX/libsecurity_cryptkit/lib/platform.c b/OSX/libsecurity_cryptkit/lib/platform.c index b34746e97..371d98f17 100644 --- a/OSX/libsecurity_cryptkit/lib/platform.c +++ b/OSX/libsecurity_cryptkit/lib/platform.c @@ -19,93 +19,14 @@ #include "platform.h" #include #include "feeDebug.h" -#ifdef NeXT - -/* - * OpenStep.... - */ -void CKRaise(const char *reason) { - #if FEE_DEBUG - printf("CryptKit fatal error: %s\n", reason); - #endif - abort(); -} #import "feeDebug.h" -#if !defined(NeXT_PDO) && FEE_DEBUG - -/* - * Mach, private build. use quick microsecond-accurate system clock. - */ - -#include - -unsigned createRandomSeed() -{ - struct tsval tsp; - - (void)kern_timestamp(&tsp); - return tsp.low_val; -} - -#else - -/* - * OpenStep, normal case. - */ -#include -#include - -extern int getpid(); - -unsigned createRandomSeed(void) -{ - time_t curTime; - unsigned thisPid; - - time(&curTime); - thisPid = (unsigned)getpid(); - - return (unsigned)curTime ^ (unsigned)thisPid; -} - -#endif /* FEE_DEBUG */ - -#elif WIN32 - -/* - * OpenStep on Windows. - */ -#include /* for _getpid() */ - -void CKRaise(const char *reason) { - #if FEE_DEBUG - printf("CryptKit fatal error: %s\n", reason); - #endif - abort(); -} - -extern void time(unsigned *tp); - -unsigned createRandomSeed() -{ - unsigned curTime; - unsigned thisPid; - - time(&curTime); - thisPid = _getpid(); - return (unsigned)curTime ^ (unsigned)thisPid; -} - - -#elif __MAC_BUILD__ - +#if __MAC_BUILD__ /* * Macintosh, all flavors. */ #include -#include #include void CKRaise(const char *reason) { @@ -121,82 +42,6 @@ void CKRaise(const char *reason) { abort(); } -/* for X, this isn't used except for testing when SecurityServer when - * Yarrow is not running. So let's strip it down so we don't have - * to link against CarbonCore. - */ -#define BARE_BONES_SEED 1 -#if BARE_BONES_SEED - -#include - -extern int getpid(); - -unsigned createRandomSeed() -{ - time_t curTime; - unsigned thisPid; - - time(&curTime); - thisPid = (unsigned)getpid(); - - return (unsigned)curTime ^ (unsigned)thisPid; -} - -#else /* BARE_BONES_SEED */ - -#include -#include - -// this is mighty pitiful anyway... -unsigned createRandomSeed() -{ - UnsignedWide curTime; - //unsigned ticks; /* use 16 bits */ - unsigned rtnHi; - unsigned rtnLo; - - /* FIXME - need a way to distinguish OS9x from Carbon. Carbon - * doesn't have LMGetTicks(). */ - - Microseconds(&curTime); /* low 16 bits are pretty good */ - - // Carbon hack - // rtnHi = LMGetTicks(); - rtnHi = 0x5a5aa5a5; - rtnLo = curTime.lo & 0xffff; - return (rtnHi ^ rtnLo); -} -#endif /* BARE_BONES_SEED */ - -#elif unix - -/* try for generic UNIX */ - -void CKRaise(const char *reason) { - #if FEE_DEBUG - printf("CryptKit fatal error: %s\n", reason); - #endif - abort(); -} - -#include -#include - -extern int getpid(); - -unsigned createRandomSeed() -{ - time_t curTime; - unsigned thisPid; - - time(&curTime); - thisPid = (unsigned)getpid(); - - return (unsigned)curTime ^ (unsigned)thisPid; -} - - #else #error platform-specific work needed in security_cryptkit/platform.c diff --git a/OSX/libsecurity_cryptkit/lib/platform.h b/OSX/libsecurity_cryptkit/lib/platform.h index 4101e4f6e..3fb50e38b 100644 --- a/OSX/libsecurity_cryptkit/lib/platform.h +++ b/OSX/libsecurity_cryptkit/lib/platform.h @@ -54,12 +54,6 @@ extern "C" { extern void CKRaise(const char *reason) __attribute__((noreturn)); -/* - * Come up with some kind of "really" random int with which to seed the - * random number generator. - */ -extern unsigned createRandomSeed(void); - #ifdef __cplusplus } #endif diff --git a/OSX/libsecurity_cssm/lib/cssmaci.h b/OSX/libsecurity_cssm/lib/cssmaci.h index f1535aef7..d7306c1ec 100644 --- a/OSX/libsecurity_cssm/lib/cssmaci.h +++ b/OSX/libsecurity_cssm/lib/cssmaci.h @@ -35,7 +35,7 @@ extern "C" { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" -typedef struct cssm_spi_ac_funcs { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_spi_ac_funcs { CSSM_RETURN (CSSMACI *AuthCompute) (CSSM_AC_HANDLE ACHandle, const CSSM_TUPLEGROUP *BaseAuthorizations, diff --git a/OSX/libsecurity_cssm/lib/cssmapplePriv.h b/OSX/libsecurity_cssm/lib/cssmapplePriv.h index 9bf4e4722..c9dbc7272 100644 --- a/OSX/libsecurity_cssm/lib/cssmapplePriv.h +++ b/OSX/libsecurity_cssm/lib/cssmapplePriv.h @@ -26,6 +26,10 @@ #ifndef _CSSMAPPLE_PRIV_H_ #define _CSSMAPPLE_PRIV_H_ 1 +#include + +#if TARGET_OS_OSX + #include #include @@ -63,12 +67,12 @@ enum { CSSM_TP_OCSP_REQUIRE_RESP_NONCE = 0x00000080 }; -typedef struct { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER { uint32 Version; CSSM_APPLE_TP_OCSP_OPT_FLAGS Flags; CSSM_DATA_PTR LocalResponder; /* URI */ CSSM_DATA_PTR LocalResponderCert; /* X509 DER encoded cert */ -} CSSM_APPLE_TP_OCSP_OPTIONS; +} CSSM_APPLE_TP_OCSP_OPTIONS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; enum { @@ -131,40 +135,40 @@ enum }; /* AppleCSPDL passthrough parameters */ -typedef struct cssm_applecspdl_db_recode_parameters +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_applecspdl_db_recode_parameters { CSSM_DATA dbBlob; CSSM_DATA extraData; -} CSSM_APPLECSPDL_RECODE_PARAMETERS, *CSSM_APPLECSPDL_RECODE_PARAMETERS_PTR; +} CSSM_APPLECSPDL_RECODE_PARAMETERS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_APPLECSPDL_RECODE_PARAMETERS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_applecspdl_db_copy_blob_parameters +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_applecspdl_db_copy_blob_parameters { CSSM_DATA blob; -} CSSM_APPLECSPDL_DB_COPY_BLOB_PARAMETERS; +} CSSM_APPLECSPDL_DB_COPY_BLOB_PARAMETERS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_applecspdl_db_insert_without_encryption_parameters +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_applecspdl_db_insert_without_encryption_parameters { CSSM_DB_RECORDTYPE recordType; CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR attributes; CSSM_DATA data; -} CSSM_APPLECSPDL_DB_INSERT_WITHOUT_ENCRYPTION_PARAMETERS; +} CSSM_APPLECSPDL_DB_INSERT_WITHOUT_ENCRYPTION_PARAMETERS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_applecspdl_db_modify_without_encryption_parameters +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_applecspdl_db_modify_without_encryption_parameters { CSSM_DB_RECORDTYPE recordType; CSSM_DB_UNIQUE_RECORD_PTR uniqueID; CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR attributes; CSSM_DATA *data; CSSM_DB_MODIFY_MODE modifyMode; -} CSSM_APPLECSPDL_DB_MODIFY_WITHOUT_ENCRYPTION_PARAMETERS; +} CSSM_APPLECSPDL_DB_MODIFY_WITHOUT_ENCRYPTION_PARAMETERS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_applecspdl_db_get_without_encryption_parameters +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_applecspdl_db_get_without_encryption_parameters { CSSM_DB_UNIQUE_RECORD_PTR uniqueID; CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR attributes; -} CSSM_APPLECSPDL_DB_GET_WITHOUT_ENCRYPTION_PARAMETERS; +} CSSM_APPLECSPDL_DB_GET_WITHOUT_ENCRYPTION_PARAMETERS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_applecspdl_db_create_with_blob_parameters +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_applecspdl_db_create_with_blob_parameters { const char *dbName; const CSSM_NET_ADDRESS *dbLocation; @@ -173,10 +177,12 @@ typedef struct cssm_applecspdl_db_create_with_blob_parameters const CSSM_RESOURCE_CONTROL_CONTEXT *credAndAclEntry; const void *openParameters; const CSSM_DATA *blob; -} CSSM_APPLE_CSPDL_DB_CREATE_WITH_BLOB_PARAMETERS; +} CSSM_APPLE_CSPDL_DB_CREATE_WITH_BLOB_PARAMETERS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; #ifdef __cplusplus } #endif +#endif /* TARGET_OS_OSX */ + #endif /* _CSSMAPPLE_PRIV_H_ */ diff --git a/OSX/libsecurity_cssm/lib/cssmcli.h b/OSX/libsecurity_cssm/lib/cssmcli.h index 504c9d7f3..50195d183 100644 --- a/OSX/libsecurity_cssm/lib/cssmcli.h +++ b/OSX/libsecurity_cssm/lib/cssmcli.h @@ -35,7 +35,7 @@ extern "C" { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" -typedef struct cssm_spi_cl_funcs { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_spi_cl_funcs { CSSM_RETURN (CSSMCLI *CertCreateTemplate) (CSSM_CL_HANDLE CLHandle, uint32 NumberOfFields, diff --git a/OSX/libsecurity_cssm/lib/cssmcspi.h b/OSX/libsecurity_cssm/lib/cssmcspi.h index 165359538..d828582bb 100644 --- a/OSX/libsecurity_cssm/lib/cssmcspi.h +++ b/OSX/libsecurity_cssm/lib/cssmcspi.h @@ -36,7 +36,7 @@ extern "C" { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" -typedef struct cssm_spi_csp_funcs { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_spi_csp_funcs { CSSM_RETURN (CSSMCSPI *EventNotify) (CSSM_CSP_HANDLE CSPHandle, CSSM_CONTEXT_EVENT Event, diff --git a/OSX/libsecurity_cssm/lib/cssmdli.h b/OSX/libsecurity_cssm/lib/cssmdli.h index b755d0adc..170c22dc6 100644 --- a/OSX/libsecurity_cssm/lib/cssmdli.h +++ b/OSX/libsecurity_cssm/lib/cssmdli.h @@ -35,7 +35,7 @@ extern "C" { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" -typedef struct cssm_spi_dl_funcs { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_spi_dl_funcs { CSSM_RETURN (CSSMDLI *DbOpen) (CSSM_DL_HANDLE DLHandle, const char *DbName, diff --git a/OSX/libsecurity_cssm/lib/cssmerr.h b/OSX/libsecurity_cssm/lib/cssmerr.h index 9d518fd5f..4465dbc07 100644 --- a/OSX/libsecurity_cssm/lib/cssmerr.h +++ b/OSX/libsecurity_cssm/lib/cssmerr.h @@ -89,16 +89,11 @@ enum { /* General Error Values. */ enum { - CSSMERR_CSSM_INVALID_ADDIN_HANDLE = - CSSM_CSSM_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT + 1, - CSSMERR_CSSM_NOT_INITIALIZED = - CSSM_CSSM_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT + 2, - CSSMERR_CSSM_INVALID_HANDLE_USAGE = - CSSM_CSSM_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT + 3, - CSSMERR_CSSM_PVC_REFERENT_NOT_FOUND = - CSSM_CSSM_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT + 4, - CSSMERR_CSSM_FUNCTION_INTEGRITY_FAIL = - CSSM_CSSM_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT + 5 + CSSMERR_CSSM_INVALID_ADDIN_HANDLE = -2147417855, + CSSMERR_CSSM_NOT_INITIALIZED = -2147417854, + CSSMERR_CSSM_INVALID_HANDLE_USAGE = -2147417853, + CSSMERR_CSSM_PVC_REFERENT_NOT_FOUND = -2147417852, + CSSMERR_CSSM_FUNCTION_INTEGRITY_FAIL = -2147417851, }; /* Common Error Codes For All Module Types. */ @@ -175,155 +170,102 @@ enum { /* CSSM Error Values Derived from Common Error Codes For All Module Types. */ enum { - CSSMERR_CSSM_INTERNAL_ERROR = - CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_INTERNAL_ERROR, - CSSMERR_CSSM_MEMORY_ERROR = - CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_MEMORY_ERROR, - CSSMERR_CSSM_MDS_ERROR = - CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_MDS_ERROR, - CSSMERR_CSSM_INVALID_POINTER = - CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_INVALID_POINTER, - CSSMERR_CSSM_INVALID_INPUT_POINTER = - CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_INVALID_INPUT_POINTER, - CSSMERR_CSSM_INVALID_OUTPUT_POINTER = - CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_INVALID_OUTPUT_POINTER, - CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED = - CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED, - CSSMERR_CSSM_SELF_CHECK_FAILED = - CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_SELF_CHECK_FAILED, - CSSMERR_CSSM_OS_ACCESS_DENIED = - CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_OS_ACCESS_DENIED, - CSSMERR_CSSM_FUNCTION_FAILED = - CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_FUNCTION_FAILED, - CSSMERR_CSSM_MODULE_MANIFEST_VERIFY_FAILED = - CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_MODULE_MANIFEST_VERIFY_FAILED, - CSSMERR_CSSM_INVALID_GUID = - CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_INVALID_GUID + CSSMERR_CSSM_INTERNAL_ERROR = -2147418111, + CSSMERR_CSSM_MEMORY_ERROR = -2147418110, + CSSMERR_CSSM_MDS_ERROR = -2147418109, + CSSMERR_CSSM_INVALID_POINTER = -2147418108, + CSSMERR_CSSM_INVALID_INPUT_POINTER = -2147418107, + CSSMERR_CSSM_INVALID_OUTPUT_POINTER = -2147418106, + CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED = -2147418105, + CSSMERR_CSSM_SELF_CHECK_FAILED = -2147418104, + CSSMERR_CSSM_OS_ACCESS_DENIED = -2147418103, + CSSMERR_CSSM_FUNCTION_FAILED = -2147418102, + CSSMERR_CSSM_MODULE_MANIFEST_VERIFY_FAILED = -2147418101, + CSSMERR_CSSM_INVALID_GUID = -2147418100, }; /* CSSM Error Values for Specific Data Types. */ enum { - CSSMERR_CSSM_INVALID_CONTEXT_HANDLE = - CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_INVALID_CONTEXT_HANDLE, - CSSMERR_CSSM_INCOMPATIBLE_VERSION = - CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_INCOMPATIBLE_VERSION, - CSSMERR_CSSM_PRIVILEGE_NOT_GRANTED = - CSSM_CSSM_BASE_ERROR + CSSM_ERRCODE_PRIVILEGE_NOT_GRANTED + CSSMERR_CSSM_INVALID_CONTEXT_HANDLE = -2147418048, + CSSMERR_CSSM_INCOMPATIBLE_VERSION = -2147418047, + CSSMERR_CSSM_PRIVILEGE_NOT_GRANTED = -2147418037, }; /* CSSM Module-Specific Error Values */ enum { CSSM_CSSM_BASE_CSSM_ERROR = CSSM_CSSM_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT + 0x10, - CSSMERR_CSSM_SCOPE_NOT_SUPPORTED = CSSM_CSSM_BASE_CSSM_ERROR + 1, - CSSMERR_CSSM_PVC_ALREADY_CONFIGURED = CSSM_CSSM_BASE_CSSM_ERROR + 2, - CSSMERR_CSSM_INVALID_PVC = CSSM_CSSM_BASE_CSSM_ERROR + 3, - CSSMERR_CSSM_EMM_LOAD_FAILED = CSSM_CSSM_BASE_CSSM_ERROR + 4, - CSSMERR_CSSM_EMM_UNLOAD_FAILED = CSSM_CSSM_BASE_CSSM_ERROR + 5, - CSSMERR_CSSM_ADDIN_LOAD_FAILED = CSSM_CSSM_BASE_CSSM_ERROR + 6, - CSSMERR_CSSM_INVALID_KEY_HIERARCHY = CSSM_CSSM_BASE_CSSM_ERROR + 7, - CSSMERR_CSSM_ADDIN_UNLOAD_FAILED = CSSM_CSSM_BASE_CSSM_ERROR + 8, - CSSMERR_CSSM_LIB_REF_NOT_FOUND = CSSM_CSSM_BASE_CSSM_ERROR + 9, - CSSMERR_CSSM_INVALID_ADDIN_FUNCTION_TABLE = CSSM_CSSM_BASE_CSSM_ERROR + 10, - CSSMERR_CSSM_EMM_AUTHENTICATE_FAILED = CSSM_CSSM_BASE_CSSM_ERROR + 11, - CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED = CSSM_CSSM_BASE_CSSM_ERROR + 12, - CSSMERR_CSSM_INVALID_SERVICE_MASK = CSSM_CSSM_BASE_CSSM_ERROR + 13, - CSSMERR_CSSM_MODULE_NOT_LOADED = CSSM_CSSM_BASE_CSSM_ERROR + 14, - CSSMERR_CSSM_INVALID_SUBSERVICEID = CSSM_CSSM_BASE_CSSM_ERROR + 15, - CSSMERR_CSSM_BUFFER_TOO_SMALL = CSSM_CSSM_BASE_CSSM_ERROR + 16, - CSSMERR_CSSM_INVALID_ATTRIBUTE = CSSM_CSSM_BASE_CSSM_ERROR + 17, - CSSMERR_CSSM_ATTRIBUTE_NOT_IN_CONTEXT = CSSM_CSSM_BASE_CSSM_ERROR + 18, - CSSMERR_CSSM_MODULE_MANAGER_INITIALIZE_FAIL = CSSM_CSSM_BASE_CSSM_ERROR + 19, - CSSMERR_CSSM_MODULE_MANAGER_NOT_FOUND = CSSM_CSSM_BASE_CSSM_ERROR + 20, - CSSMERR_CSSM_EVENT_NOTIFICATION_CALLBACK_NOT_FOUND = CSSM_CSSM_BASE_CSSM_ERROR + 21 + CSSMERR_CSSM_SCOPE_NOT_SUPPORTED = -2147417839, + CSSMERR_CSSM_PVC_ALREADY_CONFIGURED = -2147417838, + CSSMERR_CSSM_INVALID_PVC = -2147417837, + CSSMERR_CSSM_EMM_LOAD_FAILED = -2147417836, + CSSMERR_CSSM_EMM_UNLOAD_FAILED = -2147417835, + CSSMERR_CSSM_ADDIN_LOAD_FAILED = -2147417834, + CSSMERR_CSSM_INVALID_KEY_HIERARCHY = -2147417833, + CSSMERR_CSSM_ADDIN_UNLOAD_FAILED = -2147417832, + CSSMERR_CSSM_LIB_REF_NOT_FOUND = -2147417831, + CSSMERR_CSSM_INVALID_ADDIN_FUNCTION_TABLE = -2147417830, + CSSMERR_CSSM_EMM_AUTHENTICATE_FAILED = -2147417829, + CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED = -2147417828, + CSSMERR_CSSM_INVALID_SERVICE_MASK = -2147417827, + CSSMERR_CSSM_MODULE_NOT_LOADED = -2147417826, + CSSMERR_CSSM_INVALID_SUBSERVICEID = -2147417825, + CSSMERR_CSSM_BUFFER_TOO_SMALL = -2147417824, + CSSMERR_CSSM_INVALID_ATTRIBUTE = -2147417823, + CSSMERR_CSSM_ATTRIBUTE_NOT_IN_CONTEXT = -2147417822, + CSSMERR_CSSM_MODULE_MANAGER_INITIALIZE_FAIL = -2147417821, + CSSMERR_CSSM_MODULE_MANAGER_NOT_FOUND = -2147417820, + CSSMERR_CSSM_EVENT_NOTIFICATION_CALLBACK_NOT_FOUND = -2147417819, }; /* CSP Error Values Derived from Common Error Codes For All Module Types. */ enum { - CSSMERR_CSP_INTERNAL_ERROR = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INTERNAL_ERROR, - CSSMERR_CSP_MEMORY_ERROR = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_MEMORY_ERROR, - CSSMERR_CSP_MDS_ERROR = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_MDS_ERROR, - CSSMERR_CSP_INVALID_POINTER = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_POINTER, - CSSMERR_CSP_INVALID_INPUT_POINTER = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_INPUT_POINTER, - CSSMERR_CSP_INVALID_OUTPUT_POINTER = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_OUTPUT_POINTER, - CSSMERR_CSP_FUNCTION_NOT_IMPLEMENTED = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED, - CSSMERR_CSP_SELF_CHECK_FAILED = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_SELF_CHECK_FAILED, - CSSMERR_CSP_OS_ACCESS_DENIED = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_OS_ACCESS_DENIED, - CSSMERR_CSP_FUNCTION_FAILED = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_FUNCTION_FAILED + CSSMERR_CSP_INTERNAL_ERROR = -2147416063, + CSSMERR_CSP_MEMORY_ERROR = -2147416062, + CSSMERR_CSP_MDS_ERROR = -2147416061, + CSSMERR_CSP_INVALID_POINTER = -2147416060, + CSSMERR_CSP_INVALID_INPUT_POINTER = -2147416059, + CSSMERR_CSP_INVALID_OUTPUT_POINTER = -2147416058, + CSSMERR_CSP_FUNCTION_NOT_IMPLEMENTED = -2147416057, + CSSMERR_CSP_SELF_CHECK_FAILED = -2147416056, + CSSMERR_CSP_OS_ACCESS_DENIED = -2147416055, + CSSMERR_CSP_FUNCTION_FAILED = -2147416054, }; /* CSP Error Values Derived from ACL-based Error Codes. */ enum { - CSSMERR_CSP_OPERATION_AUTH_DENIED = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_OPERATION_AUTH_DENIED, - CSSMERR_CSP_OBJECT_USE_AUTH_DENIED = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_OBJECT_USE_AUTH_DENIED, - CSSMERR_CSP_OBJECT_MANIP_AUTH_DENIED = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_OBJECT_MANIP_AUTH_DENIED, - CSSMERR_CSP_OBJECT_ACL_NOT_SUPPORTED = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_OBJECT_ACL_NOT_SUPPORTED, - CSSMERR_CSP_OBJECT_ACL_REQUIRED = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_OBJECT_ACL_REQUIRED, - CSSMERR_CSP_INVALID_ACCESS_CREDENTIALS = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_ACCESS_CREDENTIALS, - CSSMERR_CSP_INVALID_ACL_BASE_CERTS = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_ACL_BASE_CERTS, - CSSMERR_CSP_ACL_BASE_CERTS_NOT_SUPPORTED = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_ACL_BASE_CERTS_NOT_SUPPORTED, - CSSMERR_CSP_INVALID_SAMPLE_VALUE = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_SAMPLE_VALUE, - CSSMERR_CSP_SAMPLE_VALUE_NOT_SUPPORTED = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_SAMPLE_VALUE_NOT_SUPPORTED, - CSSMERR_CSP_INVALID_ACL_SUBJECT_VALUE = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE, - CSSMERR_CSP_ACL_SUBJECT_TYPE_NOT_SUPPORTED = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_ACL_SUBJECT_TYPE_NOT_SUPPORTED, - CSSMERR_CSP_INVALID_ACL_CHALLENGE_CALLBACK = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_ACL_CHALLENGE_CALLBACK, - CSSMERR_CSP_ACL_CHALLENGE_CALLBACK_FAILED = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_ACL_CHALLENGE_CALLBACK_FAILED, - CSSMERR_CSP_INVALID_ACL_ENTRY_TAG = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_ACL_ENTRY_TAG, - CSSMERR_CSP_ACL_ENTRY_TAG_NOT_FOUND = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_ACL_ENTRY_TAG_NOT_FOUND, - CSSMERR_CSP_INVALID_ACL_EDIT_MODE = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_ACL_EDIT_MODE, - CSSMERR_CSP_ACL_CHANGE_FAILED = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_ACL_CHANGE_FAILED, - CSSMERR_CSP_INVALID_NEW_ACL_ENTRY = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_NEW_ACL_ENTRY, - CSSMERR_CSP_INVALID_NEW_ACL_OWNER = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_NEW_ACL_OWNER, - CSSMERR_CSP_ACL_DELETE_FAILED = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_ACL_DELETE_FAILED, - CSSMERR_CSP_ACL_REPLACE_FAILED = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_ACL_REPLACE_FAILED, - CSSMERR_CSP_ACL_ADD_FAILED = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_ACL_ADD_FAILED + CSSMERR_CSP_OPERATION_AUTH_DENIED = -2147416032, + CSSMERR_CSP_OBJECT_USE_AUTH_DENIED = -2147416031, + CSSMERR_CSP_OBJECT_MANIP_AUTH_DENIED = -2147416030, + CSSMERR_CSP_OBJECT_ACL_NOT_SUPPORTED = -2147416029, + CSSMERR_CSP_OBJECT_ACL_REQUIRED = -2147416028, + CSSMERR_CSP_INVALID_ACCESS_CREDENTIALS = -2147416027, + CSSMERR_CSP_INVALID_ACL_BASE_CERTS = -2147416026, + CSSMERR_CSP_ACL_BASE_CERTS_NOT_SUPPORTED = -2147416025, + CSSMERR_CSP_INVALID_SAMPLE_VALUE = -2147416024, + CSSMERR_CSP_SAMPLE_VALUE_NOT_SUPPORTED = -2147416023, + CSSMERR_CSP_INVALID_ACL_SUBJECT_VALUE = -2147416022, + CSSMERR_CSP_ACL_SUBJECT_TYPE_NOT_SUPPORTED = -2147416021, + CSSMERR_CSP_INVALID_ACL_CHALLENGE_CALLBACK = -2147416020, + CSSMERR_CSP_ACL_CHALLENGE_CALLBACK_FAILED = -2147416019, + CSSMERR_CSP_INVALID_ACL_ENTRY_TAG = -2147416018, + CSSMERR_CSP_ACL_ENTRY_TAG_NOT_FOUND = -2147416017, + CSSMERR_CSP_INVALID_ACL_EDIT_MODE = -2147416016, + CSSMERR_CSP_ACL_CHANGE_FAILED = -2147416015, + CSSMERR_CSP_INVALID_NEW_ACL_ENTRY = -2147416014, + CSSMERR_CSP_INVALID_NEW_ACL_OWNER = -2147416013, + CSSMERR_CSP_ACL_DELETE_FAILED = -2147416012, + CSSMERR_CSP_ACL_REPLACE_FAILED = -2147416011, + CSSMERR_CSP_ACL_ADD_FAILED = -2147416010, }; /* CSP Error Values for Specific Data Types. */ enum { - CSSMERR_CSP_INVALID_CONTEXT_HANDLE = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_CONTEXT_HANDLE, - CSSMERR_CSP_PRIVILEGE_NOT_GRANTED = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_PRIVILEGE_NOT_GRANTED, - CSSMERR_CSP_INVALID_DATA = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_DATA, - CSSMERR_CSP_INVALID_PASSTHROUGH_ID = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_PASSTHROUGH_ID, - CSSMERR_CSP_INVALID_CRYPTO_DATA = - CSSM_CSP_BASE_ERROR + CSSM_ERRCODE_INVALID_CRYPTO_DATA + CSSMERR_CSP_INVALID_CONTEXT_HANDLE = -2147416000, + CSSMERR_CSP_PRIVILEGE_NOT_GRANTED = -2147415989, + CSSMERR_CSP_INVALID_DATA = -2147415994, + CSSMERR_CSP_INVALID_PASSTHROUGH_ID = -2147415978, + CSSMERR_CSP_INVALID_CRYPTO_DATA = -2147415976, }; /* CSP Module-Specific Error Values */ @@ -331,488 +273,375 @@ enum { /* General CSP Error Values */ CSSM_CSP_BASE_CSP_ERROR = CSSM_CSP_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT, - CSSMERR_CSP_INPUT_LENGTH_ERROR = CSSM_CSP_BASE_CSP_ERROR + 1, - CSSMERR_CSP_OUTPUT_LENGTH_ERROR = CSSM_CSP_BASE_CSP_ERROR + 2, - CSSMERR_CSP_PRIVILEGE_NOT_SUPPORTED = CSSM_CSP_BASE_CSP_ERROR + 3, - CSSMERR_CSP_DEVICE_ERROR = CSSM_CSP_BASE_CSP_ERROR + 4, - CSSMERR_CSP_DEVICE_MEMORY_ERROR = CSSM_CSP_BASE_CSP_ERROR + 5, - CSSMERR_CSP_ATTACH_HANDLE_BUSY = CSSM_CSP_BASE_CSP_ERROR + 6, - CSSMERR_CSP_NOT_LOGGED_IN = CSSM_CSP_BASE_CSP_ERROR + 7, - CSSMERR_CSP_INVALID_KEY = CSSM_CSP_BASE_CSP_ERROR + 16, - CSSMERR_CSP_INVALID_KEY_REFERENCE = CSSM_CSP_BASE_CSP_ERROR + 17, - CSSMERR_CSP_INVALID_KEY_CLASS = CSSM_CSP_BASE_CSP_ERROR + 18, - CSSMERR_CSP_ALGID_MISMATCH = CSSM_CSP_BASE_CSP_ERROR + 19, - CSSMERR_CSP_KEY_USAGE_INCORRECT = CSSM_CSP_BASE_CSP_ERROR + 20, - CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT = CSSM_CSP_BASE_CSP_ERROR + 21, - CSSMERR_CSP_KEY_HEADER_INCONSISTENT = CSSM_CSP_BASE_CSP_ERROR + 22, - CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT = CSSM_CSP_BASE_CSP_ERROR + 23, - CSSMERR_CSP_UNSUPPORTED_KEY_SIZE = CSSM_CSP_BASE_CSP_ERROR + 24, - CSSMERR_CSP_INVALID_KEY_POINTER = CSSM_CSP_BASE_CSP_ERROR + 25, - CSSMERR_CSP_INVALID_KEYUSAGE_MASK = CSSM_CSP_BASE_CSP_ERROR + 26, - CSSMERR_CSP_UNSUPPORTED_KEYUSAGE_MASK = CSSM_CSP_BASE_CSP_ERROR + 27, - CSSMERR_CSP_INVALID_KEYATTR_MASK = CSSM_CSP_BASE_CSP_ERROR + 28, - CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK = CSSM_CSP_BASE_CSP_ERROR + 29, - CSSMERR_CSP_INVALID_KEY_LABEL = CSSM_CSP_BASE_CSP_ERROR + 30, - CSSMERR_CSP_UNSUPPORTED_KEY_LABEL = CSSM_CSP_BASE_CSP_ERROR + 31, - CSSMERR_CSP_INVALID_KEY_FORMAT = CSSM_CSP_BASE_CSP_ERROR + 32, - - /* CSP Vector of Buffers Error Values. */ - CSSMERR_CSP_INVALID_DATA_COUNT = CSSM_CSP_BASE_CSP_ERROR + 40, - CSSMERR_CSP_VECTOR_OF_BUFS_UNSUPPORTED = CSSM_CSP_BASE_CSP_ERROR + 41, - CSSMERR_CSP_INVALID_INPUT_VECTOR = CSSM_CSP_BASE_CSP_ERROR + 42, - CSSMERR_CSP_INVALID_OUTPUT_VECTOR = CSSM_CSP_BASE_CSP_ERROR + 43, - - /* CSP Cryptographic Context Error Values. */ - CSSMERR_CSP_INVALID_CONTEXT = CSSM_CSP_BASE_CSP_ERROR + 48, - CSSMERR_CSP_INVALID_ALGORITHM = CSSM_CSP_BASE_CSP_ERROR + 49, - CSSMERR_CSP_INVALID_ATTR_KEY = CSSM_CSP_BASE_CSP_ERROR + 54, - CSSMERR_CSP_MISSING_ATTR_KEY = CSSM_CSP_BASE_CSP_ERROR + 55, - CSSMERR_CSP_INVALID_ATTR_INIT_VECTOR = CSSM_CSP_BASE_CSP_ERROR + 56, - CSSMERR_CSP_MISSING_ATTR_INIT_VECTOR = CSSM_CSP_BASE_CSP_ERROR + 57, - CSSMERR_CSP_INVALID_ATTR_SALT = CSSM_CSP_BASE_CSP_ERROR + 58, - CSSMERR_CSP_MISSING_ATTR_SALT = CSSM_CSP_BASE_CSP_ERROR + 59, - CSSMERR_CSP_INVALID_ATTR_PADDING = CSSM_CSP_BASE_CSP_ERROR + 60, - CSSMERR_CSP_MISSING_ATTR_PADDING = CSSM_CSP_BASE_CSP_ERROR + 61, - CSSMERR_CSP_INVALID_ATTR_RANDOM = CSSM_CSP_BASE_CSP_ERROR + 62, - CSSMERR_CSP_MISSING_ATTR_RANDOM = CSSM_CSP_BASE_CSP_ERROR + 63, - CSSMERR_CSP_INVALID_ATTR_SEED = CSSM_CSP_BASE_CSP_ERROR + 64, - CSSMERR_CSP_MISSING_ATTR_SEED = CSSM_CSP_BASE_CSP_ERROR + 65, - CSSMERR_CSP_INVALID_ATTR_PASSPHRASE = CSSM_CSP_BASE_CSP_ERROR + 66, - CSSMERR_CSP_MISSING_ATTR_PASSPHRASE = CSSM_CSP_BASE_CSP_ERROR + 67, - CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH = CSSM_CSP_BASE_CSP_ERROR + 68, - CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH = CSSM_CSP_BASE_CSP_ERROR + 69, - CSSMERR_CSP_INVALID_ATTR_BLOCK_SIZE = CSSM_CSP_BASE_CSP_ERROR + 70, - CSSMERR_CSP_MISSING_ATTR_BLOCK_SIZE = CSSM_CSP_BASE_CSP_ERROR + 71, - CSSMERR_CSP_INVALID_ATTR_OUTPUT_SIZE = CSSM_CSP_BASE_CSP_ERROR + 100, - CSSMERR_CSP_MISSING_ATTR_OUTPUT_SIZE = CSSM_CSP_BASE_CSP_ERROR + 101, - CSSMERR_CSP_INVALID_ATTR_ROUNDS = CSSM_CSP_BASE_CSP_ERROR + 102, - CSSMERR_CSP_MISSING_ATTR_ROUNDS = CSSM_CSP_BASE_CSP_ERROR + 103, - CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS = CSSM_CSP_BASE_CSP_ERROR + 104, - CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS = CSSM_CSP_BASE_CSP_ERROR + 105, - CSSMERR_CSP_INVALID_ATTR_LABEL = CSSM_CSP_BASE_CSP_ERROR + 106, - CSSMERR_CSP_MISSING_ATTR_LABEL = CSSM_CSP_BASE_CSP_ERROR + 107, - CSSMERR_CSP_INVALID_ATTR_KEY_TYPE = CSSM_CSP_BASE_CSP_ERROR + 108, - CSSMERR_CSP_MISSING_ATTR_KEY_TYPE = CSSM_CSP_BASE_CSP_ERROR + 109, - CSSMERR_CSP_INVALID_ATTR_MODE = CSSM_CSP_BASE_CSP_ERROR + 110, - CSSMERR_CSP_MISSING_ATTR_MODE = CSSM_CSP_BASE_CSP_ERROR + 111, - CSSMERR_CSP_INVALID_ATTR_EFFECTIVE_BITS = CSSM_CSP_BASE_CSP_ERROR + 112, - CSSMERR_CSP_MISSING_ATTR_EFFECTIVE_BITS = CSSM_CSP_BASE_CSP_ERROR + 113, - CSSMERR_CSP_INVALID_ATTR_START_DATE = CSSM_CSP_BASE_CSP_ERROR + 114, - CSSMERR_CSP_MISSING_ATTR_START_DATE = CSSM_CSP_BASE_CSP_ERROR + 115, - CSSMERR_CSP_INVALID_ATTR_END_DATE = CSSM_CSP_BASE_CSP_ERROR + 116, - CSSMERR_CSP_MISSING_ATTR_END_DATE = CSSM_CSP_BASE_CSP_ERROR + 117, - CSSMERR_CSP_INVALID_ATTR_VERSION = CSSM_CSP_BASE_CSP_ERROR + 118, - CSSMERR_CSP_MISSING_ATTR_VERSION = CSSM_CSP_BASE_CSP_ERROR + 119, - CSSMERR_CSP_INVALID_ATTR_PRIME = CSSM_CSP_BASE_CSP_ERROR + 120, - CSSMERR_CSP_MISSING_ATTR_PRIME = CSSM_CSP_BASE_CSP_ERROR + 121, - CSSMERR_CSP_INVALID_ATTR_BASE = CSSM_CSP_BASE_CSP_ERROR + 122, - CSSMERR_CSP_MISSING_ATTR_BASE = CSSM_CSP_BASE_CSP_ERROR + 123, - CSSMERR_CSP_INVALID_ATTR_SUBPRIME = CSSM_CSP_BASE_CSP_ERROR + 124, - CSSMERR_CSP_MISSING_ATTR_SUBPRIME = CSSM_CSP_BASE_CSP_ERROR + 125, - CSSMERR_CSP_INVALID_ATTR_ITERATION_COUNT = CSSM_CSP_BASE_CSP_ERROR + 126, - CSSMERR_CSP_MISSING_ATTR_ITERATION_COUNT = CSSM_CSP_BASE_CSP_ERROR + 127, - CSSMERR_CSP_INVALID_ATTR_DL_DB_HANDLE = CSSM_CSP_BASE_CSP_ERROR + 128, - CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE = CSSM_CSP_BASE_CSP_ERROR + 129, - CSSMERR_CSP_INVALID_ATTR_ACCESS_CREDENTIALS = CSSM_CSP_BASE_CSP_ERROR + 130, - CSSMERR_CSP_MISSING_ATTR_ACCESS_CREDENTIALS = CSSM_CSP_BASE_CSP_ERROR + 131, - CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT = CSSM_CSP_BASE_CSP_ERROR + 132, - CSSMERR_CSP_MISSING_ATTR_PUBLIC_KEY_FORMAT = CSSM_CSP_BASE_CSP_ERROR + 133, - CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT = CSSM_CSP_BASE_CSP_ERROR + 134, - CSSMERR_CSP_MISSING_ATTR_PRIVATE_KEY_FORMAT = CSSM_CSP_BASE_CSP_ERROR + 135, - CSSMERR_CSP_INVALID_ATTR_SYMMETRIC_KEY_FORMAT = CSSM_CSP_BASE_CSP_ERROR + 136, - CSSMERR_CSP_MISSING_ATTR_SYMMETRIC_KEY_FORMAT = CSSM_CSP_BASE_CSP_ERROR + 137, - CSSMERR_CSP_INVALID_ATTR_WRAPPED_KEY_FORMAT = CSSM_CSP_BASE_CSP_ERROR + 138, - CSSMERR_CSP_MISSING_ATTR_WRAPPED_KEY_FORMAT = CSSM_CSP_BASE_CSP_ERROR + 139, - - /* CSP Staged Cryptographic API Error Values. */ - CSSMERR_CSP_STAGED_OPERATION_IN_PROGRESS = CSSM_CSP_BASE_CSP_ERROR + 72, - CSSMERR_CSP_STAGED_OPERATION_NOT_STARTED = CSSM_CSP_BASE_CSP_ERROR + 73, - CSSMERR_CSP_VERIFY_FAILED = CSSM_CSP_BASE_CSP_ERROR + 74, - CSSMERR_CSP_INVALID_SIGNATURE = CSSM_CSP_BASE_CSP_ERROR + 75, - CSSMERR_CSP_QUERY_SIZE_UNKNOWN = CSSM_CSP_BASE_CSP_ERROR + 76, - CSSMERR_CSP_BLOCK_SIZE_MISMATCH = CSSM_CSP_BASE_CSP_ERROR + 77, - CSSMERR_CSP_PRIVATE_KEY_NOT_FOUND = CSSM_CSP_BASE_CSP_ERROR + 78, - CSSMERR_CSP_PUBLIC_KEY_INCONSISTENT = CSSM_CSP_BASE_CSP_ERROR + 79, - CSSMERR_CSP_DEVICE_VERIFY_FAILED = CSSM_CSP_BASE_CSP_ERROR + 80, - CSSMERR_CSP_INVALID_LOGIN_NAME = CSSM_CSP_BASE_CSP_ERROR + 81, - CSSMERR_CSP_ALREADY_LOGGED_IN = CSSM_CSP_BASE_CSP_ERROR + 82, - CSSMERR_CSP_PRIVATE_KEY_ALREADY_EXISTS = CSSM_CSP_BASE_CSP_ERROR + 83, - CSSMERR_CSP_KEY_LABEL_ALREADY_EXISTS = CSSM_CSP_BASE_CSP_ERROR + 84, - CSSMERR_CSP_INVALID_DIGEST_ALGORITHM = CSSM_CSP_BASE_CSP_ERROR + 85, - CSSMERR_CSP_CRYPTO_DATA_CALLBACK_FAILED = CSSM_CSP_BASE_CSP_ERROR + 86 + CSSMERR_CSP_INPUT_LENGTH_ERROR = -2147415807, + CSSMERR_CSP_OUTPUT_LENGTH_ERROR = -2147415806, + CSSMERR_CSP_PRIVILEGE_NOT_SUPPORTED = -2147415805, + CSSMERR_CSP_DEVICE_ERROR = -2147415804, + CSSMERR_CSP_DEVICE_MEMORY_ERROR = -2147415803, + CSSMERR_CSP_ATTACH_HANDLE_BUSY = -2147415802, + CSSMERR_CSP_NOT_LOGGED_IN = -2147415801, + CSSMERR_CSP_INVALID_KEY = -2147415792, + CSSMERR_CSP_INVALID_KEY_REFERENCE = -2147415791, + CSSMERR_CSP_INVALID_KEY_CLASS = -2147415790, + CSSMERR_CSP_ALGID_MISMATCH = -2147415789, + CSSMERR_CSP_KEY_USAGE_INCORRECT = -2147415788, + CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT = -2147415787, + CSSMERR_CSP_KEY_HEADER_INCONSISTENT = -2147415786, + CSSMERR_CSP_UNSUPPORTED_KEY_FORMAT = -2147415785, + CSSMERR_CSP_UNSUPPORTED_KEY_SIZE = -2147415784, + CSSMERR_CSP_INVALID_KEY_POINTER = -2147415783, + CSSMERR_CSP_INVALID_KEYUSAGE_MASK = -2147415782, + CSSMERR_CSP_UNSUPPORTED_KEYUSAGE_MASK = -2147415781, + CSSMERR_CSP_INVALID_KEYATTR_MASK = -2147415780, + CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK = -2147415779, + CSSMERR_CSP_INVALID_KEY_LABEL = -2147415778, + CSSMERR_CSP_UNSUPPORTED_KEY_LABEL = -2147415777, + CSSMERR_CSP_INVALID_KEY_FORMAT = -2147415776, + + CSSMERR_CSP_INVALID_DATA_COUNT = -2147415768, + CSSMERR_CSP_VECTOR_OF_BUFS_UNSUPPORTED = -2147415767, + CSSMERR_CSP_INVALID_INPUT_VECTOR = -2147415766, + CSSMERR_CSP_INVALID_OUTPUT_VECTOR = -2147415765, + + CSSMERR_CSP_INVALID_CONTEXT = -2147415760, + CSSMERR_CSP_INVALID_ALGORITHM = -2147415759, + CSSMERR_CSP_INVALID_ATTR_KEY = -2147415754, + CSSMERR_CSP_MISSING_ATTR_KEY = -2147415753, + CSSMERR_CSP_INVALID_ATTR_INIT_VECTOR = -2147415752, + CSSMERR_CSP_MISSING_ATTR_INIT_VECTOR = -2147415751, + CSSMERR_CSP_INVALID_ATTR_SALT = -2147415750, + CSSMERR_CSP_MISSING_ATTR_SALT = -2147415749, + CSSMERR_CSP_INVALID_ATTR_PADDING = -2147415748, + CSSMERR_CSP_MISSING_ATTR_PADDING = -2147415747, + CSSMERR_CSP_INVALID_ATTR_RANDOM = -2147415746, + CSSMERR_CSP_MISSING_ATTR_RANDOM = -2147415745, + CSSMERR_CSP_INVALID_ATTR_SEED = -2147415744, + CSSMERR_CSP_MISSING_ATTR_SEED = -2147415743, + CSSMERR_CSP_INVALID_ATTR_PASSPHRASE = -2147415742, + CSSMERR_CSP_MISSING_ATTR_PASSPHRASE = -2147415741, + CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH = -2147415740, + CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH = -2147415739, + CSSMERR_CSP_INVALID_ATTR_BLOCK_SIZE = -2147415738, + CSSMERR_CSP_MISSING_ATTR_BLOCK_SIZE = -2147415737, + CSSMERR_CSP_INVALID_ATTR_OUTPUT_SIZE = -2147415708, + CSSMERR_CSP_MISSING_ATTR_OUTPUT_SIZE = -2147415707, + CSSMERR_CSP_INVALID_ATTR_ROUNDS = -2147415706, + CSSMERR_CSP_MISSING_ATTR_ROUNDS = -2147415705, + CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS = -2147415704, + CSSMERR_CSP_MISSING_ATTR_ALG_PARAMS = -2147415703, + CSSMERR_CSP_INVALID_ATTR_LABEL = -2147415702, + CSSMERR_CSP_MISSING_ATTR_LABEL = -2147415701, + CSSMERR_CSP_INVALID_ATTR_KEY_TYPE = -2147415700, + CSSMERR_CSP_MISSING_ATTR_KEY_TYPE = -2147415699, + CSSMERR_CSP_INVALID_ATTR_MODE = -2147415698, + CSSMERR_CSP_MISSING_ATTR_MODE = -2147415697, + CSSMERR_CSP_INVALID_ATTR_EFFECTIVE_BITS = -2147415696, + CSSMERR_CSP_MISSING_ATTR_EFFECTIVE_BITS = -2147415695, + CSSMERR_CSP_INVALID_ATTR_START_DATE = -2147415694, + CSSMERR_CSP_MISSING_ATTR_START_DATE = -2147415693, + CSSMERR_CSP_INVALID_ATTR_END_DATE = -2147415692, + CSSMERR_CSP_MISSING_ATTR_END_DATE = -2147415691, + CSSMERR_CSP_INVALID_ATTR_VERSION = -2147415690, + CSSMERR_CSP_MISSING_ATTR_VERSION = -2147415689, + CSSMERR_CSP_INVALID_ATTR_PRIME = -2147415688, + CSSMERR_CSP_MISSING_ATTR_PRIME = -2147415687, + CSSMERR_CSP_INVALID_ATTR_BASE = -2147415686, + CSSMERR_CSP_MISSING_ATTR_BASE = -2147415685, + CSSMERR_CSP_INVALID_ATTR_SUBPRIME = -2147415684, + CSSMERR_CSP_MISSING_ATTR_SUBPRIME = -2147415683, + CSSMERR_CSP_INVALID_ATTR_ITERATION_COUNT = -2147415682, + CSSMERR_CSP_MISSING_ATTR_ITERATION_COUNT = -2147415681, + CSSMERR_CSP_INVALID_ATTR_DL_DB_HANDLE = -2147415680, + CSSMERR_CSP_MISSING_ATTR_DL_DB_HANDLE = -2147415679, + CSSMERR_CSP_INVALID_ATTR_ACCESS_CREDENTIALS = -2147415678, + CSSMERR_CSP_MISSING_ATTR_ACCESS_CREDENTIALS = -2147415677, + CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT = -2147415676, + CSSMERR_CSP_MISSING_ATTR_PUBLIC_KEY_FORMAT = -2147415675, + CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT = -2147415674, + CSSMERR_CSP_MISSING_ATTR_PRIVATE_KEY_FORMAT = -2147415673, + CSSMERR_CSP_INVALID_ATTR_SYMMETRIC_KEY_FORMAT = -2147415672, + CSSMERR_CSP_MISSING_ATTR_SYMMETRIC_KEY_FORMAT = -2147415671, + CSSMERR_CSP_INVALID_ATTR_WRAPPED_KEY_FORMAT = -2147415670, + CSSMERR_CSP_MISSING_ATTR_WRAPPED_KEY_FORMAT = -2147415669, + + CSSMERR_CSP_STAGED_OPERATION_IN_PROGRESS = -2147415736, + CSSMERR_CSP_STAGED_OPERATION_NOT_STARTED = -2147415735, + CSSMERR_CSP_VERIFY_FAILED = -2147415734, + CSSMERR_CSP_INVALID_SIGNATURE = -2147415733, + CSSMERR_CSP_QUERY_SIZE_UNKNOWN = -2147415732, + CSSMERR_CSP_BLOCK_SIZE_MISMATCH = -2147415731, + CSSMERR_CSP_PRIVATE_KEY_NOT_FOUND = -2147415730, + CSSMERR_CSP_PUBLIC_KEY_INCONSISTENT = -2147415729, + CSSMERR_CSP_DEVICE_VERIFY_FAILED = -2147415728, + CSSMERR_CSP_INVALID_LOGIN_NAME = -2147415727, + CSSMERR_CSP_ALREADY_LOGGED_IN = -2147415726, + CSSMERR_CSP_PRIVATE_KEY_ALREADY_EXISTS = -2147415725, + CSSMERR_CSP_KEY_LABEL_ALREADY_EXISTS = -2147415724, + CSSMERR_CSP_INVALID_DIGEST_ALGORITHM = -2147415723, + CSSMERR_CSP_CRYPTO_DATA_CALLBACK_FAILED = -2147415722, }; /* TP Error Values Derived from Common Error Codes For All Module Types. */ enum { - CSSMERR_TP_INTERNAL_ERROR = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INTERNAL_ERROR, - CSSMERR_TP_MEMORY_ERROR = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_MEMORY_ERROR, - CSSMERR_TP_MDS_ERROR = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_MDS_ERROR, - CSSMERR_TP_INVALID_POINTER = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_POINTER, - CSSMERR_TP_INVALID_INPUT_POINTER = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_INPUT_POINTER, - CSSMERR_TP_INVALID_OUTPUT_POINTER = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_OUTPUT_POINTER, - CSSMERR_TP_FUNCTION_NOT_IMPLEMENTED = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED, - CSSMERR_TP_SELF_CHECK_FAILED = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_SELF_CHECK_FAILED, - CSSMERR_TP_OS_ACCESS_DENIED = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_OS_ACCESS_DENIED, - CSSMERR_TP_FUNCTION_FAILED = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_FUNCTION_FAILED, - CSSMERR_TP_INVALID_CONTEXT_HANDLE = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_CONTEXT_HANDLE, - CSSMERR_TP_INVALID_DATA = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_DATA, - CSSMERR_TP_INVALID_DB_LIST = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_DB_LIST, - CSSMERR_TP_INVALID_CERTGROUP_POINTER = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_CERTGROUP_POINTER, - CSSMERR_TP_INVALID_CERT_POINTER = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_CERT_POINTER, - CSSMERR_TP_INVALID_CRL_POINTER = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_CRL_POINTER, - CSSMERR_TP_INVALID_FIELD_POINTER = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_FIELD_POINTER, - CSSMERR_TP_INVALID_NETWORK_ADDR = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_NETWORK_ADDR, - CSSMERR_TP_CRL_ALREADY_SIGNED = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_CRL_ALREADY_SIGNED, - CSSMERR_TP_INVALID_NUMBER_OF_FIELDS = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_NUMBER_OF_FIELDS, - CSSMERR_TP_VERIFICATION_FAILURE = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_VERIFICATION_FAILURE, - CSSMERR_TP_INVALID_DB_HANDLE = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_DB_HANDLE, - CSSMERR_TP_UNKNOWN_FORMAT = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_UNKNOWN_FORMAT, - CSSMERR_TP_UNKNOWN_TAG = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_UNKNOWN_TAG, - CSSMERR_TP_INVALID_PASSTHROUGH_ID = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_PASSTHROUGH_ID, - CSSMERR_TP_INVALID_CSP_HANDLE = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_CSP_HANDLE, - CSSMERR_TP_INVALID_DL_HANDLE = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_DL_HANDLE, - CSSMERR_TP_INVALID_CL_HANDLE = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_CL_HANDLE, - CSSMERR_TP_INVALID_DB_LIST_POINTER = - CSSM_TP_BASE_ERROR + CSSM_ERRCODE_INVALID_DB_LIST_POINTER + CSSMERR_TP_INTERNAL_ERROR = -2147409919, + CSSMERR_TP_MEMORY_ERROR = -2147409918, + CSSMERR_TP_MDS_ERROR = -2147409917, + CSSMERR_TP_INVALID_POINTER = -2147409916, + CSSMERR_TP_INVALID_INPUT_POINTER = -2147409915, + CSSMERR_TP_INVALID_OUTPUT_POINTER = -2147409914, + CSSMERR_TP_FUNCTION_NOT_IMPLEMENTED = -2147409913, + CSSMERR_TP_SELF_CHECK_FAILED = -2147409912, + CSSMERR_TP_OS_ACCESS_DENIED = -2147409911, + CSSMERR_TP_FUNCTION_FAILED = -2147409910, + CSSMERR_TP_INVALID_CONTEXT_HANDLE = -2147409856, + CSSMERR_TP_INVALID_DATA = -2147409850, + CSSMERR_TP_INVALID_DB_LIST = -2147409844, + CSSMERR_TP_INVALID_CERTGROUP_POINTER = -2147409854, + CSSMERR_TP_INVALID_CERT_POINTER = -2147409853, + CSSMERR_TP_INVALID_CRL_POINTER = -2147409852, + CSSMERR_TP_INVALID_FIELD_POINTER = -2147409851, + CSSMERR_TP_INVALID_NETWORK_ADDR = -2147409833, + CSSMERR_TP_CRL_ALREADY_SIGNED = -2147409849, + CSSMERR_TP_INVALID_NUMBER_OF_FIELDS = -2147409848, + CSSMERR_TP_VERIFICATION_FAILURE = -2147409847, + CSSMERR_TP_INVALID_DB_HANDLE = -2147409846, + CSSMERR_TP_UNKNOWN_FORMAT = -2147409842, + CSSMERR_TP_UNKNOWN_TAG = -2147409841, + CSSMERR_TP_INVALID_PASSTHROUGH_ID = -2147409834, + CSSMERR_TP_INVALID_CSP_HANDLE = -2147409840, + CSSMERR_TP_INVALID_DL_HANDLE = -2147409839, + CSSMERR_TP_INVALID_CL_HANDLE = -2147409838, + CSSMERR_TP_INVALID_DB_LIST_POINTER = -2147409843, }; /* TP Module-Specific Error Values */ enum { CSSM_TP_BASE_TP_ERROR = CSSM_TP_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT, - CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER = CSSM_TP_BASE_TP_ERROR + 1, - CSSMERR_TP_INVALID_IDENTIFIER_POINTER = CSSM_TP_BASE_TP_ERROR + 2, - CSSMERR_TP_INVALID_KEYCACHE_HANDLE = CSSM_TP_BASE_TP_ERROR + 3, - CSSMERR_TP_INVALID_CERTGROUP = CSSM_TP_BASE_TP_ERROR + 4, - CSSMERR_TP_INVALID_CRLGROUP = CSSM_TP_BASE_TP_ERROR + 5, - CSSMERR_TP_INVALID_CRLGROUP_POINTER = CSSM_TP_BASE_TP_ERROR + 6, - CSSMERR_TP_AUTHENTICATION_FAILED = CSSM_TP_BASE_TP_ERROR + 7, - CSSMERR_TP_CERTGROUP_INCOMPLETE = CSSM_TP_BASE_TP_ERROR + 8, - CSSMERR_TP_CERTIFICATE_CANT_OPERATE = CSSM_TP_BASE_TP_ERROR + 9, - CSSMERR_TP_CERT_EXPIRED = CSSM_TP_BASE_TP_ERROR + 10, - CSSMERR_TP_CERT_NOT_VALID_YET = CSSM_TP_BASE_TP_ERROR + 11, - CSSMERR_TP_CERT_REVOKED = CSSM_TP_BASE_TP_ERROR + 12, - CSSMERR_TP_CERT_SUSPENDED = CSSM_TP_BASE_TP_ERROR + 13, - CSSMERR_TP_INSUFFICIENT_CREDENTIALS = CSSM_TP_BASE_TP_ERROR + 14, - CSSMERR_TP_INVALID_ACTION = CSSM_TP_BASE_TP_ERROR + 15, - CSSMERR_TP_INVALID_ACTION_DATA = CSSM_TP_BASE_TP_ERROR + 16, - CSSMERR_TP_INVALID_ANCHOR_CERT = CSSM_TP_BASE_TP_ERROR + 18, - CSSMERR_TP_INVALID_AUTHORITY = CSSM_TP_BASE_TP_ERROR + 19, - CSSMERR_TP_VERIFY_ACTION_FAILED = CSSM_TP_BASE_TP_ERROR + 20, - CSSMERR_TP_INVALID_CERTIFICATE = CSSM_TP_BASE_TP_ERROR + 21, - CSSMERR_TP_INVALID_CERT_AUTHORITY = CSSM_TP_BASE_TP_ERROR + 22, - CSSMERR_TP_INVALID_CRL_AUTHORITY = CSSM_TP_BASE_TP_ERROR + 23, - CSSMERR_TP_INVALID_CRL_ENCODING = CSSM_TP_BASE_TP_ERROR + 24, - CSSMERR_TP_INVALID_CRL_TYPE = CSSM_TP_BASE_TP_ERROR + 25, - CSSMERR_TP_INVALID_CRL = CSSM_TP_BASE_TP_ERROR + 26, - CSSMERR_TP_INVALID_FORM_TYPE = CSSM_TP_BASE_TP_ERROR + 27, - CSSMERR_TP_INVALID_ID = CSSM_TP_BASE_TP_ERROR + 28, - CSSMERR_TP_INVALID_IDENTIFIER = CSSM_TP_BASE_TP_ERROR + 29, - CSSMERR_TP_INVALID_INDEX = CSSM_TP_BASE_TP_ERROR + 30, - CSSMERR_TP_INVALID_NAME = CSSM_TP_BASE_TP_ERROR + 31, - CSSMERR_TP_INVALID_POLICY_IDENTIFIERS = CSSM_TP_BASE_TP_ERROR + 32, - CSSMERR_TP_INVALID_TIMESTRING = CSSM_TP_BASE_TP_ERROR + 33, - CSSMERR_TP_INVALID_REASON = CSSM_TP_BASE_TP_ERROR + 34, - CSSMERR_TP_INVALID_REQUEST_INPUTS = CSSM_TP_BASE_TP_ERROR + 35, - CSSMERR_TP_INVALID_RESPONSE_VECTOR = CSSM_TP_BASE_TP_ERROR + 36, - CSSMERR_TP_INVALID_SIGNATURE = CSSM_TP_BASE_TP_ERROR + 37, - CSSMERR_TP_INVALID_STOP_ON_POLICY = CSSM_TP_BASE_TP_ERROR + 38, - CSSMERR_TP_INVALID_CALLBACK = CSSM_TP_BASE_TP_ERROR + 39, - CSSMERR_TP_INVALID_TUPLE = CSSM_TP_BASE_TP_ERROR + 40, - CSSMERR_TP_NOT_SIGNER = CSSM_TP_BASE_TP_ERROR + 41, - CSSMERR_TP_NOT_TRUSTED = CSSM_TP_BASE_TP_ERROR + 42, - CSSMERR_TP_NO_DEFAULT_AUTHORITY = CSSM_TP_BASE_TP_ERROR + 43, - CSSMERR_TP_REJECTED_FORM = CSSM_TP_BASE_TP_ERROR + 44, - CSSMERR_TP_REQUEST_LOST = CSSM_TP_BASE_TP_ERROR + 45, - CSSMERR_TP_REQUEST_REJECTED = CSSM_TP_BASE_TP_ERROR + 46, - CSSMERR_TP_UNSUPPORTED_ADDR_TYPE = CSSM_TP_BASE_TP_ERROR + 47, - CSSMERR_TP_UNSUPPORTED_SERVICE = CSSM_TP_BASE_TP_ERROR + 48, - CSSMERR_TP_INVALID_TUPLEGROUP_POINTER = CSSM_TP_BASE_TP_ERROR + 49, - CSSMERR_TP_INVALID_TUPLEGROUP = CSSM_TP_BASE_TP_ERROR + 50 + CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER = -2147409663, + CSSMERR_TP_INVALID_IDENTIFIER_POINTER = -2147409662, + CSSMERR_TP_INVALID_KEYCACHE_HANDLE = -2147409661, + CSSMERR_TP_INVALID_CERTGROUP = -2147409660, + CSSMERR_TP_INVALID_CRLGROUP = -2147409659, + CSSMERR_TP_INVALID_CRLGROUP_POINTER = -2147409658, + CSSMERR_TP_AUTHENTICATION_FAILED = -2147409657, + CSSMERR_TP_CERTGROUP_INCOMPLETE = -2147409656, + CSSMERR_TP_CERTIFICATE_CANT_OPERATE = -2147409655, + CSSMERR_TP_CERT_EXPIRED = -2147409654, + CSSMERR_TP_CERT_NOT_VALID_YET = -2147409653, + CSSMERR_TP_CERT_REVOKED = -2147409652, + CSSMERR_TP_CERT_SUSPENDED = -2147409651, + CSSMERR_TP_INSUFFICIENT_CREDENTIALS = -2147409650, + CSSMERR_TP_INVALID_ACTION = -2147409649, + CSSMERR_TP_INVALID_ACTION_DATA = -2147409648, + CSSMERR_TP_INVALID_ANCHOR_CERT = -2147409646, + CSSMERR_TP_INVALID_AUTHORITY = -2147409645, + CSSMERR_TP_VERIFY_ACTION_FAILED = -2147409644, + CSSMERR_TP_INVALID_CERTIFICATE = -2147409643, + CSSMERR_TP_INVALID_CERT_AUTHORITY = -2147409642, + CSSMERR_TP_INVALID_CRL_AUTHORITY = -2147409641, + CSSMERR_TP_INVALID_CRL_ENCODING = -2147409640, + CSSMERR_TP_INVALID_CRL_TYPE = -2147409639, + CSSMERR_TP_INVALID_CRL = -2147409638, + CSSMERR_TP_INVALID_FORM_TYPE = -2147409637, + CSSMERR_TP_INVALID_ID = -2147409636, + CSSMERR_TP_INVALID_IDENTIFIER = -2147409635, + CSSMERR_TP_INVALID_INDEX = -2147409634, + CSSMERR_TP_INVALID_NAME = -2147409633, + CSSMERR_TP_INVALID_POLICY_IDENTIFIERS = -2147409632, + CSSMERR_TP_INVALID_TIMESTRING = -2147409631, + CSSMERR_TP_INVALID_REASON = -2147409630, + CSSMERR_TP_INVALID_REQUEST_INPUTS = -2147409629, + CSSMERR_TP_INVALID_RESPONSE_VECTOR = -2147409628, + CSSMERR_TP_INVALID_SIGNATURE = -2147409627, + CSSMERR_TP_INVALID_STOP_ON_POLICY = -2147409626, + CSSMERR_TP_INVALID_CALLBACK = -2147409625, + CSSMERR_TP_INVALID_TUPLE = -2147409624, + CSSMERR_TP_NOT_SIGNER = -2147409623, + CSSMERR_TP_NOT_TRUSTED = -2147409622, + CSSMERR_TP_NO_DEFAULT_AUTHORITY = -2147409621, + CSSMERR_TP_REJECTED_FORM = -2147409620, + CSSMERR_TP_REQUEST_LOST = -2147409619, + CSSMERR_TP_REQUEST_REJECTED = -2147409618, + CSSMERR_TP_UNSUPPORTED_ADDR_TYPE = -2147409617, + CSSMERR_TP_UNSUPPORTED_SERVICE = -2147409616, + CSSMERR_TP_INVALID_TUPLEGROUP_POINTER = -2147409615, + CSSMERR_TP_INVALID_TUPLEGROUP = -2147409614, }; /* AC Error Values Derived from Common Error Codes For All Module Types. */ enum { - CSSMERR_AC_INTERNAL_ERROR = - CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INTERNAL_ERROR, - CSSMERR_AC_MEMORY_ERROR = - CSSM_AC_BASE_ERROR + CSSM_ERRCODE_MEMORY_ERROR, - CSSMERR_AC_MDS_ERROR = - CSSM_AC_BASE_ERROR + CSSM_ERRCODE_MDS_ERROR, - CSSMERR_AC_INVALID_POINTER = - CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_POINTER, - CSSMERR_AC_INVALID_INPUT_POINTER = - CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_INPUT_POINTER, - CSSMERR_AC_INVALID_OUTPUT_POINTER = - CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_OUTPUT_POINTER, - CSSMERR_AC_FUNCTION_NOT_IMPLEMENTED = - CSSM_AC_BASE_ERROR + CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED, - CSSMERR_AC_SELF_CHECK_FAILED = - CSSM_AC_BASE_ERROR + CSSM_ERRCODE_SELF_CHECK_FAILED, - CSSMERR_AC_OS_ACCESS_DENIED = - CSSM_AC_BASE_ERROR + CSSM_ERRCODE_OS_ACCESS_DENIED, - CSSMERR_AC_FUNCTION_FAILED = - CSSM_AC_BASE_ERROR + CSSM_ERRCODE_FUNCTION_FAILED, - CSSMERR_AC_INVALID_CONTEXT_HANDLE = - CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_CONTEXT_HANDLE, - CSSMERR_AC_INVALID_DATA = - CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_DATA, - CSSMERR_AC_INVALID_DB_LIST = - CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_DB_LIST, - CSSMERR_AC_INVALID_PASSTHROUGH_ID = - CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_PASSTHROUGH_ID, - CSSMERR_AC_INVALID_DL_HANDLE = - CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_DL_HANDLE, - CSSMERR_AC_INVALID_CL_HANDLE = - CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_CL_HANDLE, - CSSMERR_AC_INVALID_TP_HANDLE = - CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_TP_HANDLE, - CSSMERR_AC_INVALID_DB_HANDLE = - CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_DB_HANDLE, - CSSMERR_AC_INVALID_DB_LIST_POINTER = - CSSM_AC_BASE_ERROR + CSSM_ERRCODE_INVALID_DB_LIST_POINTER + CSSMERR_AC_INTERNAL_ERROR = -2147405823, + CSSMERR_AC_MEMORY_ERROR = -2147405822, + CSSMERR_AC_MDS_ERROR = -2147405821, + CSSMERR_AC_INVALID_POINTER = -2147405820, + CSSMERR_AC_INVALID_INPUT_POINTER = -2147405819, + CSSMERR_AC_INVALID_OUTPUT_POINTER = -2147405818, + CSSMERR_AC_FUNCTION_NOT_IMPLEMENTED = -2147405817, + CSSMERR_AC_SELF_CHECK_FAILED = -2147405816, + CSSMERR_AC_OS_ACCESS_DENIED = -2147405815, + CSSMERR_AC_FUNCTION_FAILED = -2147405814, + CSSMERR_AC_INVALID_CONTEXT_HANDLE = -2147405760, + CSSMERR_AC_INVALID_DATA = -2147405754, + CSSMERR_AC_INVALID_DB_LIST = -2147405748, + CSSMERR_AC_INVALID_PASSTHROUGH_ID = -2147405738, + CSSMERR_AC_INVALID_DL_HANDLE = -2147405743, + CSSMERR_AC_INVALID_CL_HANDLE = -2147405742, + CSSMERR_AC_INVALID_TP_HANDLE = -2147405741, + CSSMERR_AC_INVALID_DB_HANDLE = -2147405750, + CSSMERR_AC_INVALID_DB_LIST_POINTER = -2147405747, }; /* AC Module-Specific Error Values */ enum { CSSM_AC_BASE_AC_ERROR = CSSM_AC_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT, - CSSMERR_AC_INVALID_BASE_ACLS = CSSM_AC_BASE_AC_ERROR + 1, - CSSMERR_AC_INVALID_TUPLE_CREDENTIALS = CSSM_AC_BASE_AC_ERROR + 2, - CSSMERR_AC_INVALID_ENCODING = CSSM_AC_BASE_AC_ERROR + 3, - CSSMERR_AC_INVALID_VALIDITY_PERIOD = CSSM_AC_BASE_AC_ERROR + 4, - CSSMERR_AC_INVALID_REQUESTOR = CSSM_AC_BASE_AC_ERROR + 5, - CSSMERR_AC_INVALID_REQUEST_DESCRIPTOR = CSSM_AC_BASE_AC_ERROR + 6 + CSSMERR_AC_INVALID_BASE_ACLS = -2147405567, + CSSMERR_AC_INVALID_TUPLE_CREDENTIALS = -2147405566, + CSSMERR_AC_INVALID_ENCODING = -2147405565, + CSSMERR_AC_INVALID_VALIDITY_PERIOD = -2147405564, + CSSMERR_AC_INVALID_REQUESTOR = -2147405563, + CSSMERR_AC_INVALID_REQUEST_DESCRIPTOR = -2147405562, }; /* CL Error Values Derived from Common Error Codes For All Module Types. */ enum { - CSSMERR_CL_INTERNAL_ERROR = - CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INTERNAL_ERROR, - CSSMERR_CL_MEMORY_ERROR = - CSSM_CL_BASE_ERROR + CSSM_ERRCODE_MEMORY_ERROR, - CSSMERR_CL_MDS_ERROR = - CSSM_CL_BASE_ERROR + CSSM_ERRCODE_MDS_ERROR, - CSSMERR_CL_INVALID_POINTER = - CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INVALID_POINTER, - CSSMERR_CL_INVALID_INPUT_POINTER = - CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INVALID_INPUT_POINTER, - CSSMERR_CL_INVALID_OUTPUT_POINTER = - CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INVALID_OUTPUT_POINTER, - CSSMERR_CL_FUNCTION_NOT_IMPLEMENTED = - CSSM_CL_BASE_ERROR + CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED, - CSSMERR_CL_SELF_CHECK_FAILED = - CSSM_CL_BASE_ERROR + CSSM_ERRCODE_SELF_CHECK_FAILED, - CSSMERR_CL_OS_ACCESS_DENIED = - CSSM_CL_BASE_ERROR + CSSM_ERRCODE_OS_ACCESS_DENIED, - CSSMERR_CL_FUNCTION_FAILED = - CSSM_CL_BASE_ERROR + CSSM_ERRCODE_FUNCTION_FAILED, - CSSMERR_CL_INVALID_CONTEXT_HANDLE = - CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INVALID_CONTEXT_HANDLE, - CSSMERR_CL_INVALID_CERTGROUP_POINTER = - CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INVALID_CERTGROUP_POINTER, - CSSMERR_CL_INVALID_CERT_POINTER = - CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INVALID_CERT_POINTER, - CSSMERR_CL_INVALID_CRL_POINTER = - CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INVALID_CRL_POINTER, - CSSMERR_CL_INVALID_FIELD_POINTER = - CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INVALID_FIELD_POINTER, - CSSMERR_CL_INVALID_DATA = - CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INVALID_DATA, - CSSMERR_CL_CRL_ALREADY_SIGNED = - CSSM_CL_BASE_ERROR + CSSM_ERRCODE_CRL_ALREADY_SIGNED, - CSSMERR_CL_INVALID_NUMBER_OF_FIELDS = - CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INVALID_NUMBER_OF_FIELDS, - CSSMERR_CL_VERIFICATION_FAILURE = - CSSM_CL_BASE_ERROR + CSSM_ERRCODE_VERIFICATION_FAILURE, - CSSMERR_CL_UNKNOWN_FORMAT = - CSSM_CL_BASE_ERROR + CSSM_ERRCODE_UNKNOWN_FORMAT, - CSSMERR_CL_UNKNOWN_TAG = - CSSM_CL_BASE_ERROR + CSSM_ERRCODE_UNKNOWN_TAG, - CSSMERR_CL_INVALID_PASSTHROUGH_ID = - CSSM_CL_BASE_ERROR + CSSM_ERRCODE_INVALID_PASSTHROUGH_ID + CSSMERR_CL_INTERNAL_ERROR = -2147411967, + CSSMERR_CL_MEMORY_ERROR = -2147411966, + CSSMERR_CL_MDS_ERROR = -2147411965, + CSSMERR_CL_INVALID_POINTER = -2147411964, + CSSMERR_CL_INVALID_INPUT_POINTER = -2147411963, + CSSMERR_CL_INVALID_OUTPUT_POINTER = -2147411962, + CSSMERR_CL_FUNCTION_NOT_IMPLEMENTED = -2147411961, + CSSMERR_CL_SELF_CHECK_FAILED = -2147411960, + CSSMERR_CL_OS_ACCESS_DENIED = -2147411959, + CSSMERR_CL_FUNCTION_FAILED = -2147411958, + CSSMERR_CL_INVALID_CONTEXT_HANDLE = -2147411904, + CSSMERR_CL_INVALID_CERTGROUP_POINTER = -2147411902, + CSSMERR_CL_INVALID_CERT_POINTER = -2147411901, + CSSMERR_CL_INVALID_CRL_POINTER = -2147411900, + CSSMERR_CL_INVALID_FIELD_POINTER = -2147411899, + CSSMERR_CL_INVALID_DATA = -2147411898, + CSSMERR_CL_CRL_ALREADY_SIGNED = -2147411897, + CSSMERR_CL_INVALID_NUMBER_OF_FIELDS = -2147411896, + CSSMERR_CL_VERIFICATION_FAILURE = -2147411895, + CSSMERR_CL_UNKNOWN_FORMAT = -2147411890, + CSSMERR_CL_UNKNOWN_TAG = -2147411889, + CSSMERR_CL_INVALID_PASSTHROUGH_ID = -2147411882, }; /* CL Module-Specific Error Values */ enum { CSSM_CL_BASE_CL_ERROR = CSSM_CL_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT, - CSSMERR_CL_INVALID_BUNDLE_POINTER = CSSM_CL_BASE_CL_ERROR + 1, - CSSMERR_CL_INVALID_CACHE_HANDLE = CSSM_CL_BASE_CL_ERROR + 2, - CSSMERR_CL_INVALID_RESULTS_HANDLE = CSSM_CL_BASE_CL_ERROR + 3, - CSSMERR_CL_INVALID_BUNDLE_INFO = CSSM_CL_BASE_CL_ERROR + 4, - CSSMERR_CL_INVALID_CRL_INDEX = CSSM_CL_BASE_CL_ERROR + 5, - CSSMERR_CL_INVALID_SCOPE = CSSM_CL_BASE_CL_ERROR + 6, - CSSMERR_CL_NO_FIELD_VALUES = CSSM_CL_BASE_CL_ERROR + 7, - CSSMERR_CL_SCOPE_NOT_SUPPORTED = CSSM_CL_BASE_CL_ERROR + 8 + CSSMERR_CL_INVALID_BUNDLE_POINTER = -2147411711, + CSSMERR_CL_INVALID_CACHE_HANDLE = -2147411710, + CSSMERR_CL_INVALID_RESULTS_HANDLE = -2147411709, + CSSMERR_CL_INVALID_BUNDLE_INFO = -2147411708, + CSSMERR_CL_INVALID_CRL_INDEX = -2147411707, + CSSMERR_CL_INVALID_SCOPE = -2147411706, + CSSMERR_CL_NO_FIELD_VALUES = -2147411705, + CSSMERR_CL_SCOPE_NOT_SUPPORTED = -2147411704, }; /* DL Error Values Derived from Common Error Codes For All Module Types. */ enum { - CSSMERR_DL_INTERNAL_ERROR = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INTERNAL_ERROR, - CSSMERR_DL_MEMORY_ERROR = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_MEMORY_ERROR, - CSSMERR_DL_MDS_ERROR = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_MDS_ERROR, - CSSMERR_DL_INVALID_POINTER = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_POINTER, - CSSMERR_DL_INVALID_INPUT_POINTER = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_INPUT_POINTER, - CSSMERR_DL_INVALID_OUTPUT_POINTER = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_OUTPUT_POINTER, - CSSMERR_DL_FUNCTION_NOT_IMPLEMENTED = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED, - CSSMERR_DL_SELF_CHECK_FAILED = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_SELF_CHECK_FAILED, - CSSMERR_DL_OS_ACCESS_DENIED = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_OS_ACCESS_DENIED, - CSSMERR_DL_FUNCTION_FAILED = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_FUNCTION_FAILED, - CSSMERR_DL_INVALID_CSP_HANDLE = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_CSP_HANDLE, - CSSMERR_DL_INVALID_DL_HANDLE = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_DL_HANDLE, - CSSMERR_DL_INVALID_CL_HANDLE = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_CL_HANDLE, - CSSMERR_DL_INVALID_DB_LIST_POINTER = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_DB_LIST_POINTER + CSSMERR_DL_INTERNAL_ERROR = -2147414015, + CSSMERR_DL_MEMORY_ERROR = -2147414014, + CSSMERR_DL_MDS_ERROR = -2147414013, + CSSMERR_DL_INVALID_POINTER = -2147414012, + CSSMERR_DL_INVALID_INPUT_POINTER = -2147414011, + CSSMERR_DL_INVALID_OUTPUT_POINTER = -2147414010, + CSSMERR_DL_FUNCTION_NOT_IMPLEMENTED = -2147414009, + CSSMERR_DL_SELF_CHECK_FAILED = -2147414008, + CSSMERR_DL_OS_ACCESS_DENIED = -2147414007, + CSSMERR_DL_FUNCTION_FAILED = -2147414006, + CSSMERR_DL_INVALID_CSP_HANDLE = -2147413936, + CSSMERR_DL_INVALID_DL_HANDLE = -2147413935, + CSSMERR_DL_INVALID_CL_HANDLE = -2147413934, + CSSMERR_DL_INVALID_DB_LIST_POINTER = -2147413939, }; /* DL Error Values Derived from ACL-based Error Codes. */ enum { - CSSMERR_DL_OPERATION_AUTH_DENIED = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_OPERATION_AUTH_DENIED, - CSSMERR_DL_OBJECT_USE_AUTH_DENIED = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_OBJECT_USE_AUTH_DENIED, - CSSMERR_DL_OBJECT_MANIP_AUTH_DENIED = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_OBJECT_MANIP_AUTH_DENIED, - CSSMERR_DL_OBJECT_ACL_NOT_SUPPORTED = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_OBJECT_ACL_NOT_SUPPORTED, - CSSMERR_DL_OBJECT_ACL_REQUIRED = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_OBJECT_ACL_REQUIRED, - CSSMERR_DL_INVALID_ACCESS_CREDENTIALS = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_ACCESS_CREDENTIALS, - CSSMERR_DL_INVALID_ACL_BASE_CERTS = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_ACL_BASE_CERTS, - CSSMERR_DL_ACL_BASE_CERTS_NOT_SUPPORTED = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_ACL_BASE_CERTS_NOT_SUPPORTED, - CSSMERR_DL_INVALID_SAMPLE_VALUE = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_SAMPLE_VALUE, - CSSMERR_DL_SAMPLE_VALUE_NOT_SUPPORTED = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_SAMPLE_VALUE_NOT_SUPPORTED, - CSSMERR_DL_INVALID_ACL_SUBJECT_VALUE = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE, - CSSMERR_DL_ACL_SUBJECT_TYPE_NOT_SUPPORTED = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_ACL_SUBJECT_TYPE_NOT_SUPPORTED, - CSSMERR_DL_INVALID_ACL_CHALLENGE_CALLBACK = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_ACL_CHALLENGE_CALLBACK, - CSSMERR_DL_ACL_CHALLENGE_CALLBACK_FAILED = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_ACL_CHALLENGE_CALLBACK_FAILED, - CSSMERR_DL_INVALID_ACL_ENTRY_TAG = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_ACL_ENTRY_TAG, - CSSMERR_DL_ACL_ENTRY_TAG_NOT_FOUND = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_ACL_ENTRY_TAG_NOT_FOUND, - CSSMERR_DL_INVALID_ACL_EDIT_MODE = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_ACL_EDIT_MODE, - CSSMERR_DL_ACL_CHANGE_FAILED = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_ACL_CHANGE_FAILED, - CSSMERR_DL_INVALID_NEW_ACL_ENTRY = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_NEW_ACL_ENTRY, - CSSMERR_DL_INVALID_NEW_ACL_OWNER = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_NEW_ACL_OWNER, - CSSMERR_DL_ACL_DELETE_FAILED = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_ACL_DELETE_FAILED, - CSSMERR_DL_ACL_REPLACE_FAILED = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_ACL_REPLACE_FAILED, - CSSMERR_DL_ACL_ADD_FAILED = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_ACL_ADD_FAILED + CSSMERR_DL_OPERATION_AUTH_DENIED = -2147413984, + CSSMERR_DL_OBJECT_USE_AUTH_DENIED = -2147413983, + CSSMERR_DL_OBJECT_MANIP_AUTH_DENIED = -2147413982, + CSSMERR_DL_OBJECT_ACL_NOT_SUPPORTED = -2147413981, + CSSMERR_DL_OBJECT_ACL_REQUIRED = -2147413980, + CSSMERR_DL_INVALID_ACCESS_CREDENTIALS = -2147413979, + CSSMERR_DL_INVALID_ACL_BASE_CERTS = -2147413978, + CSSMERR_DL_ACL_BASE_CERTS_NOT_SUPPORTED = -2147413977, + CSSMERR_DL_INVALID_SAMPLE_VALUE = -2147413976, + CSSMERR_DL_SAMPLE_VALUE_NOT_SUPPORTED = -2147413975, + CSSMERR_DL_INVALID_ACL_SUBJECT_VALUE = -2147413974, + CSSMERR_DL_ACL_SUBJECT_TYPE_NOT_SUPPORTED = -2147413973, + CSSMERR_DL_INVALID_ACL_CHALLENGE_CALLBACK = -2147413972, + CSSMERR_DL_ACL_CHALLENGE_CALLBACK_FAILED = -2147413971, + CSSMERR_DL_INVALID_ACL_ENTRY_TAG = -2147413970, + CSSMERR_DL_ACL_ENTRY_TAG_NOT_FOUND = -2147413969, + CSSMERR_DL_INVALID_ACL_EDIT_MODE = -2147413968, + CSSMERR_DL_ACL_CHANGE_FAILED = -2147413967, + CSSMERR_DL_INVALID_NEW_ACL_ENTRY = -2147413966, + CSSMERR_DL_INVALID_NEW_ACL_OWNER = -2147413965, + CSSMERR_DL_ACL_DELETE_FAILED = -2147413964, + CSSMERR_DL_ACL_REPLACE_FAILED = -2147413963, + CSSMERR_DL_ACL_ADD_FAILED = -2147413962, }; /* DL Error Values for Specific Data Types. */ enum { - CSSMERR_DL_INVALID_DB_HANDLE = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_DB_HANDLE, - CSSMERR_DL_INVALID_PASSTHROUGH_ID = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_PASSTHROUGH_ID, - CSSMERR_DL_INVALID_NETWORK_ADDR = - CSSM_DL_BASE_ERROR + CSSM_ERRCODE_INVALID_NETWORK_ADDR + CSSMERR_DL_INVALID_DB_HANDLE = -2147413942, + CSSMERR_DL_INVALID_PASSTHROUGH_ID = -2147413930, + CSSMERR_DL_INVALID_NETWORK_ADDR = -2147413929, }; /* DL Module-Specific Error Values */ enum { CSSM_DL_BASE_DL_ERROR = CSSM_DL_BASE_ERROR + CSSM_ERRORCODE_COMMON_EXTENT, - CSSMERR_DL_DATABASE_CORRUPT = CSSM_DL_BASE_DL_ERROR + 1, - CSSMERR_DL_INVALID_RECORD_INDEX = CSSM_DL_BASE_DL_ERROR + 8, - CSSMERR_DL_INVALID_RECORDTYPE = CSSM_DL_BASE_DL_ERROR + 9, - CSSMERR_DL_INVALID_FIELD_NAME = CSSM_DL_BASE_DL_ERROR + 10, - CSSMERR_DL_UNSUPPORTED_FIELD_FORMAT = CSSM_DL_BASE_DL_ERROR + 11, - CSSMERR_DL_UNSUPPORTED_INDEX_INFO = CSSM_DL_BASE_DL_ERROR + 12, - CSSMERR_DL_UNSUPPORTED_LOCALITY = CSSM_DL_BASE_DL_ERROR + 13, - CSSMERR_DL_UNSUPPORTED_NUM_ATTRIBUTES = CSSM_DL_BASE_DL_ERROR + 14, - CSSMERR_DL_UNSUPPORTED_NUM_INDEXES = CSSM_DL_BASE_DL_ERROR + 15, - CSSMERR_DL_UNSUPPORTED_NUM_RECORDTYPES = CSSM_DL_BASE_DL_ERROR + 16, - CSSMERR_DL_UNSUPPORTED_RECORDTYPE = CSSM_DL_BASE_DL_ERROR + 17, - CSSMERR_DL_FIELD_SPECIFIED_MULTIPLE = CSSM_DL_BASE_DL_ERROR + 18, - CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT = CSSM_DL_BASE_DL_ERROR + 19, - CSSMERR_DL_INVALID_PARSING_MODULE = CSSM_DL_BASE_DL_ERROR + 20, - CSSMERR_DL_INVALID_DB_NAME = CSSM_DL_BASE_DL_ERROR + 22, - CSSMERR_DL_DATASTORE_DOESNOT_EXIST = CSSM_DL_BASE_DL_ERROR + 23, - CSSMERR_DL_DATASTORE_ALREADY_EXISTS = CSSM_DL_BASE_DL_ERROR + 24, - CSSMERR_DL_DB_LOCKED = CSSM_DL_BASE_DL_ERROR + 25, - CSSMERR_DL_DATASTORE_IS_OPEN = CSSM_DL_BASE_DL_ERROR + 26, - CSSMERR_DL_RECORD_NOT_FOUND = CSSM_DL_BASE_DL_ERROR + 27, - CSSMERR_DL_MISSING_VALUE = CSSM_DL_BASE_DL_ERROR + 28, - CSSMERR_DL_UNSUPPORTED_QUERY = CSSM_DL_BASE_DL_ERROR + 29, - CSSMERR_DL_UNSUPPORTED_QUERY_LIMITS = CSSM_DL_BASE_DL_ERROR + 30, - CSSMERR_DL_UNSUPPORTED_NUM_SELECTION_PREDS = CSSM_DL_BASE_DL_ERROR + 31, - CSSMERR_DL_UNSUPPORTED_OPERATOR = CSSM_DL_BASE_DL_ERROR + 33, - CSSMERR_DL_INVALID_RESULTS_HANDLE = CSSM_DL_BASE_DL_ERROR + 34, - CSSMERR_DL_INVALID_DB_LOCATION = CSSM_DL_BASE_DL_ERROR + 35, - CSSMERR_DL_INVALID_ACCESS_REQUEST = CSSM_DL_BASE_DL_ERROR + 36, - CSSMERR_DL_INVALID_INDEX_INFO = CSSM_DL_BASE_DL_ERROR + 37, - CSSMERR_DL_INVALID_SELECTION_TAG = CSSM_DL_BASE_DL_ERROR + 38, - CSSMERR_DL_INVALID_NEW_OWNER = CSSM_DL_BASE_DL_ERROR + 39, - CSSMERR_DL_INVALID_RECORD_UID = CSSM_DL_BASE_DL_ERROR + 40, - CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA = CSSM_DL_BASE_DL_ERROR + 41, - CSSMERR_DL_INVALID_MODIFY_MODE = CSSM_DL_BASE_DL_ERROR + 42, - CSSMERR_DL_INVALID_OPEN_PARAMETERS = CSSM_DL_BASE_DL_ERROR + 43, - CSSMERR_DL_RECORD_MODIFIED = CSSM_DL_BASE_DL_ERROR + 44, - CSSMERR_DL_ENDOFDATA = CSSM_DL_BASE_DL_ERROR + 45, - CSSMERR_DL_INVALID_QUERY = CSSM_DL_BASE_DL_ERROR + 46, - CSSMERR_DL_INVALID_VALUE = CSSM_DL_BASE_DL_ERROR + 47, - CSSMERR_DL_MULTIPLE_VALUES_UNSUPPORTED = CSSM_DL_BASE_DL_ERROR + 48, - CSSMERR_DL_STALE_UNIQUE_RECORD = CSSM_DL_BASE_DL_ERROR + 49 + CSSMERR_DL_DATABASE_CORRUPT = -2147413759, + CSSMERR_DL_INVALID_RECORD_INDEX = -2147413752, + CSSMERR_DL_INVALID_RECORDTYPE = -2147413751, + CSSMERR_DL_INVALID_FIELD_NAME = -2147413750, + CSSMERR_DL_UNSUPPORTED_FIELD_FORMAT = -2147413749, + CSSMERR_DL_UNSUPPORTED_INDEX_INFO = -2147413748, + CSSMERR_DL_UNSUPPORTED_LOCALITY = -2147413747, + CSSMERR_DL_UNSUPPORTED_NUM_ATTRIBUTES = -2147413746, + CSSMERR_DL_UNSUPPORTED_NUM_INDEXES = -2147413745, + CSSMERR_DL_UNSUPPORTED_NUM_RECORDTYPES = -2147413744, + CSSMERR_DL_UNSUPPORTED_RECORDTYPE = -2147413743, + CSSMERR_DL_FIELD_SPECIFIED_MULTIPLE = -2147413742, + CSSMERR_DL_INCOMPATIBLE_FIELD_FORMAT = -2147413741, + CSSMERR_DL_INVALID_PARSING_MODULE = -2147413740, + CSSMERR_DL_INVALID_DB_NAME = -2147413738, + CSSMERR_DL_DATASTORE_DOESNOT_EXIST = -2147413737, + CSSMERR_DL_DATASTORE_ALREADY_EXISTS = -2147413736, + CSSMERR_DL_DB_LOCKED = -2147413735, + CSSMERR_DL_DATASTORE_IS_OPEN = -2147413734, + CSSMERR_DL_RECORD_NOT_FOUND = -2147413733, + CSSMERR_DL_MISSING_VALUE = -2147413732, + CSSMERR_DL_UNSUPPORTED_QUERY = -2147413731, + CSSMERR_DL_UNSUPPORTED_QUERY_LIMITS = -2147413730, + CSSMERR_DL_UNSUPPORTED_NUM_SELECTION_PREDS = -2147413729, + CSSMERR_DL_UNSUPPORTED_OPERATOR = -2147413727, + CSSMERR_DL_INVALID_RESULTS_HANDLE = -2147413726, + CSSMERR_DL_INVALID_DB_LOCATION = -2147413725, + CSSMERR_DL_INVALID_ACCESS_REQUEST = -2147413724, + CSSMERR_DL_INVALID_INDEX_INFO = -2147413723, + CSSMERR_DL_INVALID_SELECTION_TAG = -2147413722, + CSSMERR_DL_INVALID_NEW_OWNER = -2147413721, + CSSMERR_DL_INVALID_RECORD_UID = -2147413720, + CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA = -2147413719, + CSSMERR_DL_INVALID_MODIFY_MODE = -2147413718, + CSSMERR_DL_INVALID_OPEN_PARAMETERS = -2147413717, + CSSMERR_DL_RECORD_MODIFIED = -2147413716, + CSSMERR_DL_ENDOFDATA = -2147413715, + CSSMERR_DL_INVALID_QUERY = -2147413714, + CSSMERR_DL_INVALID_VALUE = -2147413713, + CSSMERR_DL_MULTIPLE_VALUES_UNSUPPORTED = -2147413712, + CSSMERR_DL_STALE_UNIQUE_RECORD = -2147413711, }; diff --git a/OSX/libsecurity_cssm/lib/cssmkrapi.h b/OSX/libsecurity_cssm/lib/cssmkrapi.h index 06adece61..b8a8fd26f 100644 --- a/OSX/libsecurity_cssm/lib/cssmkrapi.h +++ b/OSX/libsecurity_cssm/lib/cssmkrapi.h @@ -43,7 +43,7 @@ typedef struct cssm_kr_name { char *Name; /* name string */ } CSSM_KR_NAME DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_kr_profile { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_kr_profile { CSSM_KR_NAME UserName; /* name of the user */ CSSM_CERTGROUP_PTR UserCertificate; /* public key certificate of the user */ CSSM_CERTGROUP_PTR KRSCertChain; /* cert chain for the KRSP coordinator */ @@ -58,7 +58,7 @@ typedef struct cssm_kr_profile { CSSM_DATA_PTR KRSPExtensions; /* reserved for extensions specific to KRSPs */ } CSSM_KR_PROFILE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_KR_PROFILE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_kr_wrappedproductinfo { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_kr_wrappedproductinfo { CSSM_VERSION StandardVersion; CSSM_STRING StandardDescription; CSSM_VERSION ProductVersion; @@ -67,11 +67,11 @@ typedef struct cssm_kr_wrappedproductinfo { uint32 ProductFlags; } CSSM_KR_WRAPPEDPRODUCT_INFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_KR_WRAPPEDPRODUCT_INFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_krsubservice { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_krsubservice { uint32 SubServiceId; char *Description; /* Description of this sub service */ CSSM_KR_WRAPPEDPRODUCT_INFO WrappedProduct; -} CSSM_KRSUBSERVICE, *CSSM_KRSUBSERVICE_PTR; +} CSSM_KRSUBSERVICE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_KRSUBSERVICE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; typedef uint32 CSSM_KR_POLICY_TYPE; #define CSSM_KR_INDIV_POLICY (0x00000001) @@ -89,7 +89,7 @@ typedef uint32 CSSM_KR_POLICY_FLAGS; #define CSSM_KR_OPTIMIZE (0x00000010) #define CSSM_KR_DROP_WORKFACTOR (0x00000020) -typedef struct cssm_kr_policy_list_item { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_kr_policy_list_item { struct kr_policy_list_item *next; CSSM_ALGORITHMS AlgorithmId; CSSM_ENCRYPT_MODE Mode; @@ -100,145 +100,13 @@ typedef struct cssm_kr_policy_list_item { CSSM_CONTEXT_TYPE AlgClass; } CSSM_KR_POLICY_LIST_ITEM DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_KR_POLICY_LIST_ITEM_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_kr_policy_info { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_kr_policy_info { CSSM_BOOL krbNotAllowed; uint32 numberOfEntries; CSSM_KR_POLICY_LIST_ITEM *policyEntry; } CSSM_KR_POLICY_INFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_KR_POLICY_INFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -/* Key Recovery Module Mangement Operations */ - -CSSM_RETURN CSSMAPI -CSSM_KR_SetEnterpriseRecoveryPolicy (const CSSM_DATA *RecoveryPolicyFileName, - const CSSM_ACCESS_CREDENTIALS *OldPassPhrase, - const CSSM_ACCESS_CREDENTIALS *NewPassPhrase) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - - -/* Key Recovery Context Operations */ - -CSSM_RETURN CSSMAPI -CSSM_KR_CreateRecoveryRegistrationContext (CSSM_KRSP_HANDLE KRSPHandle, - CSSM_CC_HANDLE *NewContext) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -CSSM_RETURN CSSMAPI -CSSM_KR_CreateRecoveryEnablementContext (CSSM_KRSP_HANDLE KRSPHandle, - const CSSM_KR_PROFILE *LocalProfile, - const CSSM_KR_PROFILE *RemoteProfile, - CSSM_CC_HANDLE *NewContext) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -CSSM_RETURN CSSMAPI -CSSM_KR_CreateRecoveryRequestContext (CSSM_KRSP_HANDLE KRSPHandle, - const CSSM_KR_PROFILE *LocalProfile, - CSSM_CC_HANDLE *NewContext) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -CSSM_RETURN CSSMAPI -CSSM_KR_GetPolicyInfo (CSSM_CC_HANDLE CCHandle, - CSSM_KR_POLICY_FLAGS *EncryptionProhibited, - uint32 *WorkFactor) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - - -/* Key Recovery Registration Operations */ - -CSSM_RETURN CSSMAPI -CSSM_KR_RegistrationRequest (CSSM_CC_HANDLE RecoveryRegistrationContext, - const CSSM_DATA *KRInData, - const CSSM_ACCESS_CREDENTIALS *AccessCredentials, - CSSM_KR_POLICY_FLAGS KRFlags, - sint32 *EstimatedTime, - CSSM_HANDLE_PTR ReferenceHandle) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -CSSM_RETURN CSSMAPI -CSSM_KR_RegistrationRetrieve (CSSM_KRSP_HANDLE KRSPHandle, - CSSM_HANDLE ReferenceHandle, - const CSSM_ACCESS_CREDENTIALS *AccessCredentials, - sint32 *EstimatedTime, - CSSM_KR_PROFILE_PTR KRProfile) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - - -/* Key Recovery Enablement Operations */ - -CSSM_RETURN CSSMAPI -CSSM_KR_GenerateRecoveryFields (CSSM_CC_HANDLE KeyRecoveryContext, - CSSM_CC_HANDLE CCHandle, - const CSSM_DATA *KRSPOptions, - CSSM_KR_POLICY_FLAGS KRFlags, - CSSM_DATA_PTR KRFields, - CSSM_CC_HANDLE *NewCCHandle) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -CSSM_RETURN CSSMAPI -CSSM_KR_ProcessRecoveryFields (CSSM_CC_HANDLE KeyRecoveryContext, - CSSM_CC_HANDLE CryptoContext, - const CSSM_DATA *KRSPOptions, - CSSM_KR_POLICY_FLAGS KRFlags, - const CSSM_DATA *KRFields, - CSSM_CC_HANDLE *NewCryptoContext) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - - -/* Key Recovery Request Operations */ - -CSSM_RETURN CSSMAPI -CSSM_KR_RecoveryRequest (CSSM_CC_HANDLE RecoveryRequestContext, - const CSSM_DATA *KRInData, - const CSSM_ACCESS_CREDENTIALS *AccessCredentials, - sint32 *EstimatedTime, - CSSM_HANDLE_PTR ReferenceHandle) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -CSSM_RETURN CSSMAPI -CSSM_KR_RecoveryRetrieve (CSSM_KRSP_HANDLE KRSPHandle, - CSSM_HANDLE ReferenceHandle, - const CSSM_ACCESS_CREDENTIALS *AccessCredentials, - sint32 *EstimatedTime, - CSSM_HANDLE_PTR CacheHandle, - uint32 *NumberOfRecoveredKeys) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -CSSM_RETURN CSSMAPI -CSSM_KR_GetRecoveredObject (CSSM_KRSP_HANDLE KRSPHandle, - CSSM_HANDLE CacheHandle, - uint32 IndexInResults, - CSSM_CSP_HANDLE CSPHandle, - const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, - uint32 Flags, - CSSM_KEY_PTR RecoveredKey, - CSSM_DATA_PTR OtherInfo) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -CSSM_RETURN CSSMAPI -CSSM_KR_RecoveryRequestAbort (CSSM_KRSP_HANDLE KRSPHandle, - CSSM_HANDLE CacheHandle) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -CSSM_RETURN CSSMAPI -CSSM_KR_QueryPolicyInfo (CSSM_KRSP_HANDLE KRSPHandle, - CSSM_ALGORITHMS AlgorithmID, - CSSM_ENCRYPT_MODE Mode, - CSSM_CONTEXT_TYPE Class, - CSSM_KR_POLICY_INFO_PTR *PolicyInfoData) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - - -/* Extensibility Functions */ - -CSSM_RETURN CSSMAPI -CSSM_KR_PassThrough (CSSM_KRSP_HANDLE KRSPHandle, - CSSM_CC_HANDLE KeyRecoveryContext, - CSSM_CC_HANDLE CryptoContext, - uint32 PassThroughId, - const void *InputParams, - void **OutputParams) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - #pragma clang diagnostic pop #ifdef __cplusplus diff --git a/OSX/libsecurity_cssm/lib/cssmkrspi.h b/OSX/libsecurity_cssm/lib/cssmkrspi.h index 741d5578a..00eea5e45 100644 --- a/OSX/libsecurity_cssm/lib/cssmkrspi.h +++ b/OSX/libsecurity_cssm/lib/cssmkrspi.h @@ -38,7 +38,7 @@ extern "C" { /* Data types for Key Recovery SPI */ -typedef struct cssm_spi_kr_funcs { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_spi_kr_funcs { CSSM_RETURN (CSSMKRI *RegistrationRequest) (CSSM_KRSP_HANDLE KRSPHandle, CSSM_CC_HANDLE KRRegistrationContextHandle, diff --git a/OSX/libsecurity_cssm/lib/cssmspi.h b/OSX/libsecurity_cssm/lib/cssmspi.h index e91e553e7..f1fd4bab8 100644 --- a/OSX/libsecurity_cssm/lib/cssmspi.h +++ b/OSX/libsecurity_cssm/lib/cssmspi.h @@ -41,7 +41,7 @@ typedef CSSM_RETURN (CSSMAPI *CSSM_SPI_ModuleEventHandler) void *CssmNotifyCallbackCtx, uint32 SubserviceId, CSSM_SERVICE_TYPE ServiceType, - CSSM_MODULE_EVENT EventType); + CSSM_MODULE_EVENT EventType) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; typedef uint32 CSSM_CONTEXT_EVENT; enum { @@ -50,7 +50,7 @@ enum { CSSM_CONTEXT_EVENT_UPDATE = 3 }; -typedef struct cssm_module_funcs { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_module_funcs { CSSM_SERVICE_TYPE ServiceType; uint32 NumberOfServiceFuncs; const CSSM_PROC_ADDR *ServiceFuncs; @@ -74,7 +74,7 @@ typedef void *(CSSMAPI *CSSM_UPCALLS_CALLOC) size_t num, size_t size) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_upcalls { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_upcalls { CSSM_UPCALLS_MALLOC malloc_func; CSSM_UPCALLS_FREE free_func; CSSM_UPCALLS_REALLOC realloc_func; @@ -95,39 +95,6 @@ typedef struct cssm_upcalls { uint32 NumFunctions); } CSSM_UPCALLS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_UPCALLS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -CSSM_RETURN CSSMSPI -CSSM_SPI_ModuleLoad (const CSSM_GUID *CssmGuid, - const CSSM_GUID *ModuleGuid, - CSSM_SPI_ModuleEventHandler CssmNotifyCallback, - void *CssmNotifyCallbackCtx) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -CSSM_RETURN CSSMSPI -CSSM_SPI_ModuleUnload (const CSSM_GUID *CssmGuid, - const CSSM_GUID *ModuleGuid, - CSSM_SPI_ModuleEventHandler CssmNotifyCallback, - void *CssmNotifyCallbackCtx) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -CSSM_RETURN CSSMSPI -CSSM_SPI_ModuleAttach (const CSSM_GUID *ModuleGuid, - const CSSM_VERSION *Version, - uint32 SubserviceID, - CSSM_SERVICE_TYPE SubServiceType, - CSSM_ATTACH_FLAGS AttachFlags, - CSSM_MODULE_HANDLE ModuleHandle, - CSSM_KEY_HIERARCHY KeyHierarchy, - const CSSM_GUID *CssmGuid, - const CSSM_GUID *ModuleManagerGuid, - const CSSM_GUID *CallerGuid, - const CSSM_UPCALLS *Upcalls, - CSSM_MODULE_FUNCS_PTR *FuncTbl) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - -CSSM_RETURN CSSMSPI -CSSM_SPI_ModuleDetach (CSSM_MODULE_HANDLE ModuleHandle) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - #pragma clang diagnostic pop #ifdef __cplusplus diff --git a/OSX/libsecurity_cssm/lib/cssmtpi.h b/OSX/libsecurity_cssm/lib/cssmtpi.h index ad92b1120..352d4391f 100644 --- a/OSX/libsecurity_cssm/lib/cssmtpi.h +++ b/OSX/libsecurity_cssm/lib/cssmtpi.h @@ -35,7 +35,7 @@ extern "C" { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" -typedef struct cssm_spi_tp_funcs { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_spi_tp_funcs { CSSM_RETURN (CSSMTPI *SubmitCredRequest) (CSSM_TP_HANDLE TPHandle, const CSSM_TP_AUTHORITY_ID *PreferredAuthority, diff --git a/OSX/libsecurity_cssm/lib/cssmtype.h b/OSX/libsecurity_cssm/lib/cssmtype.h index 1cddc3e41..246a16c90 100644 --- a/OSX/libsecurity_cssm/lib/cssmtype.h +++ b/OSX/libsecurity_cssm/lib/cssmtype.h @@ -27,6 +27,7 @@ #define _CSSMTYPE_H_ 1 #include +#include /* ========================================================================== W A R N I N G : CDSA has been deprecated starting with 10.7. While the @@ -89,10 +90,8 @@ enum { }; typedef char CSSM_STRING [CSSM_MODULE_STRING_SIZE + 4]; -typedef struct cssm_data { - CSSM_SIZE Length; /* in bytes */ - uint8 *Data; -} CSSM_DATA DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DATA_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; +#define CSSM_DATA SecAsn1Item +typedef SecAsn1Item *CSSM_DATA_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; typedef struct cssm_guid { uint32 Data1; @@ -141,7 +140,7 @@ enum { typedef CSSM_SERVICE_MASK CSSM_SERVICE_TYPE; -typedef struct cssm_subservice_uid { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_subservice_uid { CSSM_GUID Guid; CSSM_VERSION Version; uint32 SubserviceId; @@ -160,7 +159,7 @@ typedef CSSM_RETURN (CSSMAPI *CSSM_API_ModuleEventHandler) void* AppNotifyCallbackCtx, uint32 SubserviceId, CSSM_SERVICE_TYPE ServiceType, - CSSM_MODULE_EVENT EventType); + CSSM_MODULE_EVENT EventType) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; typedef uint32 CSSM_ATTACH_FLAGS; enum { @@ -195,7 +194,7 @@ enum { CSSM_ADDR_NAME = 4 /* char* - qualified by access method */ }; -typedef struct cssm_net_address { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_net_address { CSSM_NET_ADDRESS_TYPE AddressType; CSSM_DATA Address; } CSSM_NET_ADDRESS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_NET_ADDRESS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; @@ -217,9 +216,9 @@ enum { }; typedef CSSM_RETURN (CSSMAPI *CSSM_CALLBACK) - (CSSM_DATA_PTR OutData, void *CallerCtx); + (CSSM_DATA_PTR OutData, void *CallerCtx) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_crypto_data { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_crypto_data { CSSM_DATA Param; CSSM_CALLBACK Callback; void *CallerCtx; @@ -386,7 +385,7 @@ typedef struct cssm_list { CSSM_LIST_ELEMENT_PTR Tail; /* tail of the list */ } CSSM_LIST DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_LIST_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_list_element { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_list_element { struct cssm_list_element *NextElement; /* next list element */ CSSM_WORDID_TYPE WordID; /* integer identifier associated */ /* with a Word value */ @@ -395,9 +394,9 @@ typedef struct cssm_list_element { CSSM_LIST Sublist; /* sublist */ CSSM_DATA Word; /* a byte-string */ } Element; -} CSSM_LIST_ELEMENT; +} CSSM_LIST_ELEMENT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct { /* 5-tuple definition */ +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER { /* 5-tuple definition */ CSSM_LIST Issuer; /* issuer, or empty if ACL */ CSSM_LIST Subject; /* subject */ CSSM_BOOL Delegate; /* permission to delegate */ @@ -405,7 +404,7 @@ typedef struct { /* 5-tuple definition */ CSSM_LIST ValidityPeriod; /* validity information (dates) */ } CSSM_TUPLE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TUPLE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_tuplegroup { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_tuplegroup { uint32 NumberOfTuples; CSSM_TUPLE_PTR Tuples; } CSSM_TUPLEGROUP DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TUPLEGROUP_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; @@ -424,12 +423,12 @@ enum { CSSM_SAMPLE_TYPE_THRESHOLD = CSSM_WORDID_THRESHOLD }; -typedef struct cssm_sample { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_sample { CSSM_LIST TypedSample; const CSSM_SUBSERVICE_UID *Verifier; } CSSM_SAMPLE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_SAMPLE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_samplegroup { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_samplegroup { uint32 NumberOfSamples; const CSSM_SAMPLE *Samples; } CSSM_SAMPLEGROUP DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_SAMPLEGROUP_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; @@ -460,14 +459,14 @@ typedef struct cssm_memory_funcs { void *AllocRef; } CSSM_MEMORY_FUNCS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_MEMORY_FUNCS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef CSSM_MEMORY_FUNCS CSSM_API_MEMORY_FUNCS; -typedef CSSM_API_MEMORY_FUNCS *CSSM_API_MEMORY_FUNCS_PTR; +typedef CSSM_MEMORY_FUNCS CSSM_API_MEMORY_FUNCS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; +typedef CSSM_API_MEMORY_FUNCS *CSSM_API_MEMORY_FUNCS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; typedef CSSM_RETURN (CSSMAPI * CSSM_CHALLENGE_CALLBACK) (const CSSM_LIST *Challenge, CSSM_SAMPLEGROUP_PTR Response, void *CallerCtx, - const CSSM_MEMORY_FUNCS *MemFuncs); + const CSSM_MEMORY_FUNCS *MemFuncs) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; typedef uint32 CSSM_CERT_TYPE, *CSSM_CERT_TYPE_PTR; enum { @@ -508,7 +507,7 @@ enum { CSSM_CL_CUSTOM_CERT_ENCODING = 0x8000 }; -typedef struct cssm_encoded_cert { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_encoded_cert { CSSM_CERT_TYPE CertType; /* type of certificate */ CSSM_CERT_ENCODING CertEncoding; /* encoding for this packed cert */ CSSM_DATA CertBlob; /* packed cert */ @@ -540,7 +539,7 @@ typedef struct cssm_parsed_cert { void *ParsedCert; /* parsed cert (to be typecast) */ } CSSM_PARSED_CERT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_PARSED_CERT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_cert_pair { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_cert_pair { CSSM_ENCODED_CERT EncodedCert; /* an encoded certificate blob */ CSSM_PARSED_CERT ParsedCert; /* equivalent parsed certificate */ } CSSM_CERT_PAIR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_CERT_PAIR_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; @@ -553,7 +552,7 @@ enum { CSSM_CERTGROUP_CERT_PAIR = 0x03 }; -typedef struct cssm_certgroup { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_certgroup { CSSM_CERT_TYPE CertType; CSSM_CERT_ENCODING CertEncoding; uint32 NumCerts; /* # of certificates in this list */ @@ -569,15 +568,15 @@ typedef struct cssm_certgroup { CSSM_CERTGROUP_TYPE CertGroupType; /* type of structure in the GroupList */ void *Reserved; /* reserved for implementation dependent use */ -} CSSM_CERTGROUP, *CSSM_CERTGROUP_PTR; +} CSSM_CERTGROUP DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_CERTGROUP_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_base_certs { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_base_certs { CSSM_TP_HANDLE TPHandle; CSSM_CL_HANDLE CLHandle; CSSM_CERTGROUP Certs; } CSSM_BASE_CERTS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_BASE_CERTS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_access_credentials { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_access_credentials { CSSM_STRING EntryTag; CSSM_BASE_CERTS BaseCerts; CSSM_SAMPLEGROUP Samples; @@ -637,12 +636,12 @@ typedef struct cssm_authorizationgroup { CSSM_ACL_AUTHORIZATION_TAG *AuthTags; } CSSM_AUTHORIZATIONGROUP DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_AUTHORIZATIONGROUP_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_acl_validity_period { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_acl_validity_period { CSSM_DATA StartDate; CSSM_DATA EndDate; } CSSM_ACL_VALIDITY_PERIOD DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_ACL_VALIDITY_PERIOD_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_acl_entry_prototype { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_acl_entry_prototype { CSSM_LIST TypedSubject; CSSM_BOOL Delegate; CSSM_AUTHORIZATIONGROUP Authorization; @@ -650,7 +649,7 @@ typedef struct cssm_acl_entry_prototype { CSSM_STRING EntryTag; } CSSM_ACL_ENTRY_PROTOTYPE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_ACL_ENTRY_PROTOTYPE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_acl_owner_prototype { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_acl_owner_prototype { CSSM_LIST TypedSubject; CSSM_BOOL Delegate; } CSSM_ACL_OWNER_PROTOTYPE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_ACL_OWNER_PROTOTYPE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; @@ -659,22 +658,22 @@ typedef CSSM_RETURN (CSSMAPI * CSSM_ACL_SUBJECT_CALLBACK) (const CSSM_LIST *SubjectRequest, CSSM_LIST_PTR SubjectResponse, void *CallerContext, - const CSSM_MEMORY_FUNCS *MemFuncs); + const CSSM_MEMORY_FUNCS *MemFuncs) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_acl_entry_input { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_acl_entry_input { CSSM_ACL_ENTRY_PROTOTYPE Prototype; CSSM_ACL_SUBJECT_CALLBACK Callback; void *CallerContext; } CSSM_ACL_ENTRY_INPUT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_ACL_ENTRY_INPUT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_resource_control_context { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_resource_control_context { CSSM_ACCESS_CREDENTIALS_PTR AccessCred; CSSM_ACL_ENTRY_INPUT InitialAclEntry; } CSSM_RESOURCE_CONTROL_CONTEXT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_RESOURCE_CONTROL_CONTEXT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; typedef CSSM_HANDLE CSSM_ACL_HANDLE; -typedef struct cssm_acl_entry_info { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_acl_entry_info { CSSM_ACL_ENTRY_PROTOTYPE EntryPublicInfo; CSSM_ACL_HANDLE EntryHandle; } CSSM_ACL_ENTRY_INFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_ACL_ENTRY_INFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; @@ -686,7 +685,7 @@ enum { CSSM_ACL_EDIT_MODE_REPLACE = 3 }; -typedef struct cssm_acl_edit { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_acl_edit { CSSM_ACL_EDIT_MODE EditMode; CSSM_ACL_HANDLE OldEntryHandle; const CSSM_ACL_ENTRY_INPUT *NewEntry; @@ -695,7 +694,7 @@ typedef struct cssm_acl_edit { #if defined(WIN32) typedef FARPROC CSSM_PROC_ADDR; #else -typedef void (CSSMAPI *CSSM_PROC_ADDR) (); +typedef void (CSSMAPI *CSSM_PROC_ADDR) (void); #endif typedef CSSM_PROC_ADDR *CSSM_PROC_ADDR_PTR; @@ -985,7 +984,7 @@ enum { CSSM_ALGMODE_VENDOR_DEFINED = CSSM_ALGMODE_NONE + 0x80000000 }; -typedef struct cssm_keyheader { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_keyheader { CSSM_HEADERVERSION HeaderVersion; /* Key header version */ CSSM_GUID CspId; /* GUID of CSP generating the key */ CSSM_KEYBLOB_TYPE BlobType; /* See BlobType enum */ @@ -1002,12 +1001,12 @@ typedef struct cssm_keyheader { uint32 Reserved; } CSSM_KEYHEADER DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_KEYHEADER_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_key { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_key { CSSM_KEYHEADER KeyHeader; /* Fixed length key header */ CSSM_DATA KeyData; /* Variable length key data */ } CSSM_KEY DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_KEY_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef CSSM_KEY CSSM_WRAP_KEY, *CSSM_WRAP_KEY_PTR; +typedef CSSM_KEY CSSM_WRAP_KEY DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_WRAP_KEY_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; typedef uint32 CSSM_CSPTYPE; enum { @@ -1121,10 +1120,10 @@ enum { typedef CSSM_ALGORITHMS CSSM_KEY_TYPE; -typedef struct cssm_context_attribute { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_context_attribute { CSSM_ATTRIBUTE_TYPE AttributeType; uint32 AttributeLength; - union cssm_context_attribute_value { + union DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_context_attribute_value { char *String; uint32 Uint32; CSSM_ACCESS_CREDENTIALS_PTR AccessCredentials; @@ -1138,9 +1137,9 @@ typedef struct cssm_context_attribute { CSSM_DL_DB_HANDLE_PTR DLDBHandle; struct cssm_kr_profile *KRProfile; } Attribute; -} CSSM_CONTEXT_ATTRIBUTE, *CSSM_CONTEXT_ATTRIBUTE_PTR; +} CSSM_CONTEXT_ATTRIBUTE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_CONTEXT_ATTRIBUTE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_context { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_context { CSSM_CONTEXT_TYPE ContextType; CSSM_ALGORITHMS AlgorithmType; uint32 NumberOfAttributes; @@ -1198,7 +1197,7 @@ enum { CSSM_PKCS_OAEP_PSOURCE_Pspecified = CSSM_PKCS_OAEP_PSOURCE_NONE + 1 }; -typedef struct cssm_pkcs1_oaep_params { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_pkcs1_oaep_params { uint32 HashAlgorithm; CSSM_DATA HashParams; CSSM_PKCS_OAEP_MGF MGF; @@ -1227,7 +1226,7 @@ enum { CSSM_VALUE_NOT_AVAILABLE = -1 }; -typedef struct cssm_pkcs5_pbkdf1_params { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_pkcs5_pbkdf1_params { CSSM_DATA Passphrase; CSSM_DATA InitVector; } CSSM_PKCS5_PBKDF1_PARAMS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_PKCS5_PBKDF1_PARAMS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; @@ -1237,12 +1236,12 @@ enum { CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1 = 0 }; -typedef struct cssm_pkcs5_pbkdf2_params { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_pkcs5_pbkdf2_params { CSSM_DATA Passphrase; CSSM_PKCS5_PBKDF2_PRF PseudoRandomFunction; } CSSM_PKCS5_PBKDF2_PARAMS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_PKCS5_PBKDF2_PARAMS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_kea_derive_params { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_kea_derive_params { CSSM_DATA Rb; CSSM_DATA Yb; } CSSM_KEA_DERIVE_PARAMS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_KEA_DERIVE_PARAMS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; @@ -1250,7 +1249,7 @@ typedef struct cssm_kea_derive_params { /* Data Types for Trust Policy Services */ -typedef struct cssm_tp_authority_id { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_tp_authority_id { CSSM_DATA *AuthorityCert; CSSM_NET_ADDRESS_PTR AuthorityLocation; } CSSM_TP_AUTHORITY_ID DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_AUTHORITY_ID_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; @@ -1270,18 +1269,19 @@ enum { typedef CSSM_RETURN (CSSMAPI * CSSM_TP_VERIFICATION_RESULTS_CALLBACK) (CSSM_MODULE_HANDLE ModuleHandle, void *CallerCtx, - CSSM_DATA_PTR VerifiedCert); + CSSM_DATA_PTR VerifiedCert) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; /* From CL */ -typedef CSSM_DATA CSSM_OID, *CSSM_OID_PTR; +#define CSSM_OID SecAsn1Oid +typedef SecAsn1Oid *CSSM_OID_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_field { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_field { CSSM_OID FieldOid; CSSM_DATA FieldValue; } CSSM_FIELD DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_FIELD_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; /* TP Again. */ -typedef struct cssm_tp_policyinfo { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_tp_policyinfo { uint32 NumberOfPolicyIds; CSSM_FIELD_PTR PolicyIds; void *PolicyControl; @@ -1313,13 +1313,13 @@ enum { typedef char *CSSM_TIMESTRING; /* From DL. */ -typedef struct cssm_dl_db_list { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_dl_db_list { uint32 NumHandles; CSSM_DL_DB_HANDLE_PTR DLDBHandle; } CSSM_DL_DB_LIST DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DL_DB_LIST_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; /* TP Again. */ -typedef struct cssm_tp_callerauth_context { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_tp_callerauth_context { CSSM_TP_POLICYINFO Policy; CSSM_TIMESTRING VerifyTime; CSSM_TP_STOP_ON VerificationAbortOn; @@ -1367,7 +1367,7 @@ enum { CSSM_CRL_ENCODING_MULTIPLE = 0x7FFE }; -typedef struct cssm_encoded_crl { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_encoded_crl { CSSM_CRL_TYPE CrlType; /* type of CRL */ CSSM_CRL_ENCODING CrlEncoding; /* encoding for this packed CRL */ CSSM_DATA CrlBlob; /* packed CRL */ @@ -1381,7 +1381,7 @@ typedef struct cssm_parsed_crl { void *ParsedCrl; /* parsed CRL (to be typecast) */ } CSSM_PARSED_CRL DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_PARSED_CRL_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_crl_pair { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_crl_pair { CSSM_ENCODED_CRL EncodedCrl; /* an encoded CRL blob */ CSSM_PARSED_CRL ParsedCrl; /* equivalent parsed CRL */ } CSSM_CRL_PAIR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_CRL_PAIR_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; @@ -1394,7 +1394,7 @@ enum { CSSM_CRLGROUP_CRL_PAIR = 0x03 }; -typedef struct cssm_crlgroup { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_crlgroup { CSSM_CRL_TYPE CrlType; CSSM_CRL_ENCODING CrlEncoding; uint32 NumberOfCrls; @@ -1405,9 +1405,9 @@ typedef struct cssm_crlgroup { CSSM_CRL_PAIR_PTR PairCrlList; } GroupCrlList; CSSM_CRLGROUP_TYPE CrlGroupType; -} CSSM_CRLGROUP, *CSSM_CRLGROUP_PTR; +} CSSM_CRLGROUP DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_CRLGROUP_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_fieldgroup { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_fieldgroup { int NumberOfFields; /* number of fields in the array */ CSSM_FIELD_PTR Fields; /* array of fields */ } CSSM_FIELDGROUP DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_FIELDGROUP_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; @@ -1426,24 +1426,24 @@ enum { CSSM_EVIDENCE_FORM_TUPLEGROUP = 0x9 }; -typedef struct cssm_evidence { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_evidence { CSSM_EVIDENCE_FORM EvidenceForm; void *Evidence; /* Evidence content */ } CSSM_EVIDENCE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_EVIDENCE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_tp_verify_context { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_tp_verify_context { CSSM_TP_ACTION Action; CSSM_DATA ActionData; CSSM_CRLGROUP Crls; CSSM_TP_CALLERAUTH_CONTEXT_PTR Cred; } CSSM_TP_VERIFY_CONTEXT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_VERIFY_CONTEXT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_tp_verify_context_result { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_tp_verify_context_result { uint32 NumberOfEvidences; CSSM_EVIDENCE_PTR Evidence; } CSSM_TP_VERIFY_CONTEXT_RESULT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_VERIFY_CONTEXT_RESULT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_tp_request_set { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_tp_request_set { uint32 NumberOfRequests; void *Requests; } CSSM_TP_REQUEST_SET DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_REQUEST_SET_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; @@ -1465,7 +1465,7 @@ enum { submit-retrieve function pair */ }; -typedef struct cssm_tp_confirm_response { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_tp_confirm_response { uint32 NumberOfResponses; CSSM_TP_CONFIRM_STATUS_PTR Responses; } CSSM_TP_CONFIRM_RESPONSE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_CONFIRM_RESPONSE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; @@ -1479,7 +1479,7 @@ enum { CSSM_ELAPSED_TIME_COMPLETE = -2 }; -typedef struct cssm_tp_certissue_input { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_tp_certissue_input { CSSM_SUBSERVICE_UID CSPSubserviceUid; CSSM_CL_HANDLE CLHandle; uint32 NumberOfTemplateFields; @@ -1514,7 +1514,7 @@ enum { a revocation of the certificate */ }; -typedef struct cssm_tp_certissue_output { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_tp_certissue_output { CSSM_TP_CERTISSUE_STATUS IssueStatus; CSSM_CERTGROUP_PTR CertGroup; CSSM_TP_SERVICES PerformedServiceRequests; @@ -1571,7 +1571,7 @@ enum { jurisdiction of this certificate */ }; -typedef struct cssm_tp_certchange_input { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_tp_certchange_input { CSSM_TP_CERTCHANGE_ACTION Action; CSSM_TP_CERTCHANGE_REASON Reason; CSSM_CL_HANDLE CLHandle; @@ -1604,12 +1604,12 @@ enum { the cert state */ }; -typedef struct cssm_tp_certchange_output { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_tp_certchange_output { CSSM_TP_CERTCHANGE_STATUS ActionStatus; CSSM_FIELD RevokeInfo; } CSSM_TP_CERTCHANGE_OUTPUT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_CERTCHANGE_OUTPUT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_tp_certverify_input { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_tp_certverify_input { CSSM_CL_HANDLE CLHandle; CSSM_DATA_PTR Cert; CSSM_TP_VERIFY_CONTEXT_PTR VerifyContext; @@ -1636,13 +1636,13 @@ enum { CSSM_TP_CERTVERIFY_UNKNOWN_CRITICAL_EXT = 0x10 }; -typedef struct cssm_tp_certverify_output { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_tp_certverify_output { CSSM_TP_CERTVERIFY_STATUS VerifyStatus; uint32 NumberOfEvidence; CSSM_EVIDENCE_PTR Evidence; } CSSM_TP_CERTVERIFY_OUTPUT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_CERTVERIFY_OUTPUT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_tp_certnotarize_input { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_tp_certnotarize_input { CSSM_CL_HANDLE CLHandle; uint32 NumberOfFields; CSSM_FIELD_PTR MoreFields; @@ -1678,13 +1678,13 @@ enum { not authorized */ }; -typedef struct cssm_tp_certnotarize_output { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_tp_certnotarize_output { CSSM_TP_CERTNOTARIZE_STATUS NotarizeStatus; CSSM_CERTGROUP_PTR NotarizedCertGroup; CSSM_TP_SERVICES PerformedServiceRequests; } CSSM_TP_CERTNOTARIZE_OUTPUT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_CERTNOTARIZE_OUTPUT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_tp_certreclaim_input { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_tp_certreclaim_input { CSSM_CL_HANDLE CLHandle; uint32 NumberOfSelectionFields; CSSM_FIELD_PTR SelectionFields; @@ -1712,13 +1712,13 @@ enum { authorized */ }; -typedef struct cssm_tp_certreclaim_output { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_tp_certreclaim_output { CSSM_TP_CERTRECLAIM_STATUS ReclaimStatus; CSSM_CERTGROUP_PTR ReclaimedCertGroup; CSSM_LONG_HANDLE KeyCacheHandle; } CSSM_TP_CERTRECLAIM_OUTPUT DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_TP_CERTRECLAIM_OUTPUT_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_tp_crlissue_input { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_tp_crlissue_input { CSSM_CL_HANDLE CLHandle; uint32 CrlIdentifier; CSSM_TIMESTRING CrlThisTime; @@ -1760,7 +1760,7 @@ enum { next CRL has been returned. */ }; -typedef struct cssm_tp_crlissue_output { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_tp_crlissue_output { CSSM_TP_CRLISSUE_STATUS IssueStatus; CSSM_ENCODED_CRL_PTR Crl; CSSM_TIMESTRING CrlNextTime; @@ -1810,12 +1810,12 @@ enum { CSSM_CERT_BUNDLE_ENCODING_PGP = 0x05 }; -typedef struct cssm_cert_bundle_header { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_cert_bundle_header { CSSM_CERT_BUNDLE_TYPE BundleType; CSSM_CERT_BUNDLE_ENCODING BundleEncoding; } CSSM_CERT_BUNDLE_HEADER DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_CERT_BUNDLE_HEADER_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_cert_bundle { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_cert_bundle { CSSM_CERT_BUNDLE_HEADER BundleHeader; CSSM_DATA Bundle; } CSSM_CERT_BUNDLE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_CERT_BUNDLE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; @@ -1846,17 +1846,17 @@ enum { CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX = 8 }; -typedef struct cssm_db_attribute_info { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_db_attribute_info { CSSM_DB_ATTRIBUTE_NAME_FORMAT AttributeNameFormat; - union cssm_db_attribute_label { + union DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_db_attribute_label { char *AttributeName; /* e.g., "record label" */ CSSM_OID AttributeOID; /* e.g., CSSMOID_RECORDLABEL */ uint32 AttributeID; /* e.g., FOUR_CHAR_CODE('recl') */ } Label; CSSM_DB_ATTRIBUTE_FORMAT AttributeFormat; -} CSSM_DB_ATTRIBUTE_INFO, *CSSM_DB_ATTRIBUTE_INFO_PTR; +} CSSM_DB_ATTRIBUTE_INFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DB_ATTRIBUTE_INFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_db_attribute_data { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_db_attribute_data { CSSM_DB_ATTRIBUTE_INFO Info; uint32 NumberOfValues; CSSM_DATA_PTR Value; @@ -1899,20 +1899,20 @@ enum { CSSM_DB_CERT_USE_PRIVACY = 0x00000020 /* use cert for confidentiality only */ }; -typedef struct cssm_db_record_attribute_info { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_db_record_attribute_info { CSSM_DB_RECORDTYPE DataRecordType; uint32 NumberOfAttributes; CSSM_DB_ATTRIBUTE_INFO_PTR AttributeInfo; } CSSM_DB_RECORD_ATTRIBUTE_INFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DB_RECORD_ATTRIBUTE_INFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_db_record_attribute_data { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_db_record_attribute_data { CSSM_DB_RECORDTYPE DataRecordType; uint32 SemanticInformation; uint32 NumberOfAttributes; CSSM_DB_ATTRIBUTE_DATA_PTR AttributeData; } CSSM_DB_RECORD_ATTRIBUTE_DATA DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_db_parsing_module_info { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_db_parsing_module_info { CSSM_DB_RECORDTYPE RecordType; CSSM_SUBSERVICE_UID ModuleSubserviceUid; } CSSM_DB_PARSING_MODULE_INFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DB_PARSING_MODULE_INFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; @@ -1930,18 +1930,18 @@ enum { CSSM_DB_INDEX_ON_RECORD = 2 }; -typedef struct cssm_db_index_info { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_db_index_info { CSSM_DB_INDEX_TYPE IndexType; CSSM_DB_INDEXED_DATA_LOCATION IndexedDataLocation; CSSM_DB_ATTRIBUTE_INFO Info; } CSSM_DB_INDEX_INFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DB_INDEX_INFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_db_unique_record { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_db_unique_record { CSSM_DB_INDEX_INFO RecordLocator; CSSM_DATA RecordIdentifier; } CSSM_DB_UNIQUE_RECORD DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DB_UNIQUE_RECORD_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_db_record_index_info { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_db_record_index_info { CSSM_DB_RECORDTYPE DataRecordType; uint32 NumberOfIndexes; CSSM_DB_INDEX_INFO_PTR IndexInfo; @@ -1962,7 +1962,7 @@ enum { CSSM_DB_MODIFY_ATTRIBUTE_REPLACE = CSSM_DB_MODIFY_ATTRIBUTE_NONE + 3 }; -typedef struct cssm_dbinfo { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_dbinfo { /* meta information about each record type stored in this data store including meta information about record attributes and indexes */ @@ -1994,7 +1994,7 @@ enum { CSSM_DB_OR = 2 }; -typedef struct cssm_selection_predicate { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_selection_predicate { CSSM_DB_OPERATOR DbOperator; CSSM_DB_ATTRIBUTE_DATA Attribute; } CSSM_SELECTION_PREDICATE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_SELECTION_PREDICATE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; @@ -2007,7 +2007,7 @@ enum { CSSM_QUERY_SIZELIMIT_NONE = 0 }; -typedef struct cssm_query_limits { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_query_limits { uint32 TimeLimit; /* in seconds */ uint32 SizeLimit; /* max. number of records to return */ } CSSM_QUERY_LIMITS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_QUERY_LIMITS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; @@ -2017,7 +2017,7 @@ enum { CSSM_QUERY_RETURN_DATA = 0x01 }; -typedef struct cssm_query { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_query { CSSM_DB_RECORDTYPE RecordType; CSSM_DB_CONJUNCTIVE Conjunctive; uint32 NumSelectionPredicates; @@ -2062,7 +2062,7 @@ enum { CSSM_DB_FILESYSTEMSCAN_MODE = 1 }; -typedef struct cssm_db_schema_attribute_info { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_db_schema_attribute_info { uint32 AttributeId; char *AttributeName; CSSM_OID AttributeNameID; diff --git a/OSX/libsecurity_cssm/lib/eisl.h b/OSX/libsecurity_cssm/lib/eisl.h index 7c8fa9417..83f02f46c 100644 --- a/OSX/libsecurity_cssm/lib/eisl.h +++ b/OSX/libsecurity_cssm/lib/eisl.h @@ -32,293 +32,6 @@ extern "C" { #endif -/* Data Types for Embedded Integrity Services Library */ - -typedef const void *ISL_ITERATOR_PTR; - -typedef const void *ISL_VERIFIED_SIGNATURE_ROOT_PTR; - -typedef const void *ISL_VERIFIED_CERTIFICATE_CHAIN_PTR; - -typedef const void *ISL_VERIFIED_CERTIFICATE_PTR; - -typedef const void *ISL_MANIFEST_SECTION_PTR; - -typedef const void *ISL_VERIFIED_MODULE_PTR; - -typedef void (*ISL_FUNCTION_PTR)(void); - -typedef struct isl_data { - CSSM_SIZE Length; /* in bytes */ - uint8 *Data; -} ISL_DATA, *ISL_DATA_PTR; - -typedef struct isl_const_data { - CSSM_SIZE Length; /* in bytes */ - const uint8 *Data; -} ISL_CONST_DATA, *ISL_CONST_DATA_PTR; - -typedef enum isl_status { - ISL_OK = 0, - ISL_FAIL = -1 -} ISL_STATUS; - - -/* Embedded Integrity Services Library Functions */ - -ISL_VERIFIED_MODULE_PTR -EISL_SelfCheck (); - -ISL_VERIFIED_MODULE_PTR -EISL_VerifyAndLoadModuleAndCredentialData (const ISL_CONST_DATA CredentialsImage, - const ISL_CONST_DATA ModuleSearchPath, - const ISL_CONST_DATA Name, - const ISL_CONST_DATA Signer, - const ISL_CONST_DATA PublicKey); - -ISL_VERIFIED_MODULE_PTR -EISL_VerifyAndLoadModuleAndCredentialDataWithCertificate (const ISL_CONST_DATA CredentialsImage, - const ISL_CONST_DATA ModuleSearchPath, - const ISL_CONST_DATA Name, - const ISL_CONST_DATA Signer, - const ISL_CONST_DATA Certificate); - -ISL_VERIFIED_MODULE_PTR -EISL_VerifyAndLoadModuleAndCredentials (ISL_CONST_DATA Credentials, - ISL_CONST_DATA Name, - ISL_CONST_DATA Signer, - ISL_CONST_DATA PublicKey); - -ISL_VERIFIED_MODULE_PTR -EISL_VerifyAndLoadModuleAndCredentialsWithCertificate (const ISL_CONST_DATA Credentials, - const ISL_CONST_DATA Name, - const ISL_CONST_DATA Signer, - const ISL_CONST_DATA Certificate); - -ISL_VERIFIED_MODULE_PTR -EISL_VerifyLoadedModuleAndCredentialData (const ISL_CONST_DATA CredentialsImage, - const ISL_CONST_DATA ModuleSearchPath, - const ISL_CONST_DATA Name, - const ISL_CONST_DATA Signer, - const ISL_CONST_DATA PublicKey); - -ISL_VERIFIED_MODULE_PTR -EISL_VerifyLoadedModuleAndCredentialDataWithCertificate (const ISL_CONST_DATA CredentialsImage, - const ISL_CONST_DATA ModuleSearchPath, - const ISL_CONST_DATA Name, - const ISL_CONST_DATA Signer, - const ISL_CONST_DATA Certificate); - -ISL_VERIFIED_MODULE_PTR -EISL_VerifyLoadedModuleAndCredentials (ISL_CONST_DATA Credentials, - ISL_CONST_DATA Name, - ISL_CONST_DATA Signer, - ISL_CONST_DATA PublicKey); - -ISL_VERIFIED_MODULE_PTR -EISL_VerifyLoadedModuleAndCredentialsWithCertificate (const ISL_CONST_DATA Credentials, - const ISL_CONST_DATA Name, - const ISL_CONST_DATA Signer, - const ISL_CONST_DATA Certificate); - -ISL_VERIFIED_CERTIFICATE_CHAIN_PTR -EISL_GetCertificateChain (ISL_VERIFIED_MODULE_PTR Module); - -uint32 -EISL_ContinueVerification (ISL_VERIFIED_MODULE_PTR Module, - uint32 WorkFactor); - -ISL_VERIFIED_MODULE_PTR -EISL_DuplicateVerifiedModulePtr (ISL_VERIFIED_MODULE_PTR Module); - -ISL_STATUS -EISL_RecycleVerifiedModuleCredentials (ISL_VERIFIED_MODULE_PTR Verification); - - -/* Signature Root Methods */ - -ISL_VERIFIED_SIGNATURE_ROOT_PTR -EISL_CreateVerifiedSignatureRootWithCredentialData (const ISL_CONST_DATA CredentialsImage, - const ISL_CONST_DATA ModuleSearchPath, - const ISL_CONST_DATA Signer, - const ISL_CONST_DATA PublicKey); - -ISL_VERIFIED_SIGNATURE_ROOT_PTR -EISL_CreateVerifiedSignatureRootWithCredentialDataAndCertificate (const ISL_CONST_DATA CredentialsImage, - const ISL_CONST_DATA ModuleSearchPath, - ISL_VERIFIED_CERTIFICATE_PTR Cert); - -ISL_VERIFIED_SIGNATURE_ROOT_PTR -EISL_CreateVerfiedSignatureRoot (ISL_CONST_DATA Credentials, - ISL_CONST_DATA Signer, - ISL_CONST_DATA PublicKey); - -ISL_VERIFIED_SIGNATURE_ROOT_PTR -EISL_CreateVerfiedSignatureRootWithCertificate (ISL_CONST_DATA Credentials, - ISL_VERIFIED_CERTIFICATE_PTR Cert); - -ISL_MANIFEST_SECTION_PTR -EISL_FindManifestSection (ISL_VERIFIED_SIGNATURE_ROOT_PTR Root, - ISL_CONST_DATA Name); - -ISL_ITERATOR_PTR -EISL_CreateManifestSectionEnumerator (ISL_VERIFIED_SIGNATURE_ROOT_PTR Root); - -ISL_MANIFEST_SECTION_PTR -EISL_GetNextManifestSection (ISL_ITERATOR_PTR Iterator); - -ISL_STATUS -EISL_RecycleManifestSectionEnumerator (ISL_ITERATOR_PTR Iterator); - -ISL_STATUS -EISL_FindManifestAttribute (ISL_VERIFIED_SIGNATURE_ROOT_PTR Context, - ISL_CONST_DATA Name, - ISL_CONST_DATA_PTR Value); - -ISL_ITERATOR_PTR -EISL_CreateManifestAttributeEnumerator (ISL_VERIFIED_SIGNATURE_ROOT_PTR Context); - -ISL_STATUS -EISL_FindSignerInfoAttribute (ISL_VERIFIED_SIGNATURE_ROOT_PTR Context, - ISL_CONST_DATA Name, - ISL_CONST_DATA_PTR Value); - -ISL_ITERATOR_PTR -EISL_CreateSignerInfoAttributeEnumerator (ISL_VERIFIED_SIGNATURE_ROOT_PTR Context); - -ISL_STATUS -EISL_GetNextAttribute (ISL_ITERATOR_PTR Iterator, - ISL_CONST_DATA_PTR Name, - ISL_CONST_DATA_PTR Value); - -ISL_STATUS -EISL_RecycleAttributeEnumerator (ISL_ITERATOR_PTR Iterator); - -ISL_STATUS -EISL_FindSignatureAttribute (ISL_VERIFIED_SIGNATURE_ROOT_PTR Root, - ISL_CONST_DATA Name, - ISL_CONST_DATA_PTR Value); - -ISL_ITERATOR_PTR -EISL_CreateSignatureAttributeEnumerator (ISL_VERIFIED_SIGNATURE_ROOT_PTR Root); - -ISL_STATUS -EISL_GetNextSignatureAttribute (ISL_ITERATOR_PTR Iterator, - ISL_CONST_DATA_PTR Name, - ISL_CONST_DATA_PTR Value); - -ISL_STATUS -EISL_RecycleSignatureAttributeEnumerator (ISL_ITERATOR_PTR Iterator); - -ISL_STATUS -EISL_RecycleVerifiedSignatureRoot (ISL_VERIFIED_SIGNATURE_ROOT_PTR Root); - - -/* Certificate Chain Methods */ - -ISL_VERIFIED_CERTIFICATE_CHAIN_PTR -EISL_CreateCertificateChainWithCredentialData (const ISL_CONST_DATA RootIssuer, - const ISL_CONST_DATA PublicKey, - const ISL_CONST_DATA CredentialsImage, - const ISL_CONST_DATA ModuleSearchPath); - -ISL_VERIFIED_CERTIFICATE_CHAIN_PTR -EISL_CreateCertificateChainWithCredentialDataAndCertificate (const ISL_CONST_DATA Certificate, - const ISL_CONST_DATA CredentialsImage, - const ISL_CONST_DATA ModuleSearchPath); - -ISL_VERIFIED_CERTIFICATE_CHAIN_PTR -EISL_CreateCertificateChain (ISL_CONST_DATA RootIssuer, - ISL_CONST_DATA PublicKey, - ISL_CONST_DATA Credential); - -ISL_VERIFIED_CERTIFICATE_CHAIN_PTR -EISL_CreateCertificateChainWithCertificate (const ISL_CONST_DATA Certificate, - const ISL_CONST_DATA Credential); - -uint32 -EISL_CopyCertificateChain (ISL_VERIFIED_CERTIFICATE_CHAIN_PTR Verification, - ISL_VERIFIED_CERTIFICATE_PTR Certs[], - uint32 MaxCertificates); - -ISL_STATUS -EISL_RecycleVerifiedCertificateChain (ISL_VERIFIED_CERTIFICATE_CHAIN_PTR Chain); - - -/* Certificate Attribute Methods */ - -ISL_STATUS -EISL_FindCertificateAttribute (ISL_VERIFIED_CERTIFICATE_PTR Cert, - ISL_CONST_DATA Name, - ISL_CONST_DATA_PTR Value); - -ISL_ITERATOR_PTR -EISL_CreateCertificateAttributeEnumerator (ISL_VERIFIED_CERTIFICATE_PTR Cert); - -ISL_STATUS -EISL_GetNextCertificateAttribute (ISL_ITERATOR_PTR CertIterator, - ISL_CONST_DATA_PTR Name, - ISL_CONST_DATA_PTR Value); - -ISL_STATUS -EISL_RecycleCertificateAttributeEnumerator (ISL_ITERATOR_PTR CertIterator); - - -/* Manifest Section Object Methods */ - -ISL_VERIFIED_SIGNATURE_ROOT_PTR -EISL_GetManifestSignatureRoot (ISL_MANIFEST_SECTION_PTR Section); - -ISL_VERIFIED_MODULE_PTR -EISL_VerifyAndLoadModule (ISL_MANIFEST_SECTION_PTR Section); - -ISL_VERIFIED_MODULE_PTR -EISL_VerifyLoadedModule (ISL_MANIFEST_SECTION_PTR Section); - -ISL_STATUS -EISL_FindManifestSectionAttribute (ISL_MANIFEST_SECTION_PTR Section, - ISL_CONST_DATA Name, - ISL_CONST_DATA_PTR Value); - -ISL_ITERATOR_PTR -EISL_CreateManifestSectionAttributeEnumerator (ISL_MANIFEST_SECTION_PTR Section); - -ISL_STATUS -EISL_GetNextManifestSectionAttribute (ISL_ITERATOR_PTR Iterator, - ISL_CONST_DATA_PTR Name, - ISL_CONST_DATA_PTR Value); - -ISL_STATUS -EISL_RecycleManifestSectionAttributeEnumerator (ISL_ITERATOR_PTR Iterator); - -ISL_MANIFEST_SECTION_PTR -EISL_GetModuleManifestSection (ISL_VERIFIED_MODULE_PTR Module); - - -/* Secure Linkage Services */ - -ISL_FUNCTION_PTR -EISL_LocateProcedureAddress (ISL_VERIFIED_MODULE_PTR Module, - ISL_CONST_DATA Name); - -#ifdef MACOSX -#define EISL_GetReturnAddress(Address) \ -{\ - /* Platform specific code in here */ \ -} -#endif - -ISL_STATUS -EISL_CheckAddressWithinModule (ISL_VERIFIED_MODULE_PTR Verification, - ISL_FUNCTION_PTR Address); - -ISL_STATUS -EISL_CheckDataAddressWithinModule (ISL_VERIFIED_MODULE_PTR Verification, - const void *Address); - -void * -EISL_GetLibHandle (ISL_VERIFIED_MODULE_PTR Verification); - #ifdef __cplusplus } #endif diff --git a/OSX/libsecurity_cssm/lib/emmspi.h b/OSX/libsecurity_cssm/lib/emmspi.h index a618be9ef..29e5ba2f4 100644 --- a/OSX/libsecurity_cssm/lib/emmspi.h +++ b/OSX/libsecurity_cssm/lib/emmspi.h @@ -37,7 +37,7 @@ extern "C" { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" -typedef struct cssm_state_funcs { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_state_funcs { CSSM_RETURN (CSSMAPI *cssm_GetAttachFunctions) (CSSM_MODULE_HANDLE hAddIn, CSSM_SERVICE_MASK AddinType, @@ -63,7 +63,7 @@ typedef struct cssm_state_funcs { (const CSSM_MANAGER_EVENT_NOTIFICATION *EventDescription); } CSSM_STATE_FUNCS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_STATE_FUNCS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_manager_registration_info { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_manager_registration_info { /* loading, unloading, dispatch table, and event notification */ CSSM_RETURN (CSSMAPI *Initialize) (uint32 VerMajor, @@ -85,13 +85,6 @@ enum { CSSM_HINT_ADDRESS_SP = 1 << 1 }; -CSSM_RETURN CSSMAPI -ModuleManagerAuthenticate (CSSM_KEY_HIERARCHY KeyHierarchy, - const CSSM_GUID *CssmGuid, - const CSSM_GUID *AppGuid, - CSSM_MANAGER_REGISTRATION_INFO_PTR FunctionTable) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - #pragma clang diagnostic pop #ifdef __cplusplus diff --git a/OSX/libsecurity_cssm/lib/emmtype.h b/OSX/libsecurity_cssm/lib/emmtype.h index 1f3c18f18..d61b7caf3 100644 --- a/OSX/libsecurity_cssm/lib/emmtype.h +++ b/OSX/libsecurity_cssm/lib/emmtype.h @@ -41,7 +41,7 @@ typedef uint32 CSSM_MANAGER_EVENT_TYPES; #define CSSM_MANAGER_SERVICE_REQUEST 1 #define CSSM_MANAGER_REPLY 2 -typedef struct cssm_manager_event_notification { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_manager_event_notification { CSSM_SERVICE_MASK DestinationModuleManagerType; CSSM_SERVICE_MASK SourceModuleManagerType; CSSM_MANAGER_EVENT_TYPES Event; diff --git a/OSX/libsecurity_cssm/lib/generator.pl b/OSX/libsecurity_cssm/lib/generator.pl index e4792ac94..c3d6802f6 100644 --- a/OSX/libsecurity_cssm/lib/generator.pl +++ b/OSX/libsecurity_cssm/lib/generator.pl @@ -192,7 +192,7 @@ sub ignored { "; while (($name, $_) = each %spi) { print "extern const char *const ${name}NameTable[] = {"; - s/^.*struct cssm_spi.*{(.*)} CSSM_SPI.*$/$1/s + s/^.*struct(?: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER)? cssm_spi.*{(.*)} CSSM_SPI.*$/$1/s or die "bad format in $SPI_H{$name}"; s/CSSM_RETURN \(CSSM[A-Z]*I \*([A-Za-z_]+)\)\s+\([^)]+\)[^;]*;/\t"$1",/g; print; diff --git a/OSX/libsecurity_cssm/lib/x509defs.h b/OSX/libsecurity_cssm/lib/x509defs.h index 1affad445..5a5f31e49 100644 --- a/OSX/libsecurity_cssm/lib/x509defs.h +++ b/OSX/libsecurity_cssm/lib/x509defs.h @@ -69,43 +69,38 @@ typedef uint8 CSSM_BER_TAG; /* Data Structures for X.509 Certificates */ - -typedef struct cssm_x509_algorithm_identifier { - CSSM_OID algorithm; - CSSM_DATA parameters; -} CSSM_X509_ALGORITHM_IDENTIFIER DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_ALGORITHM_IDENTIFIER_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; +#define CSSM_X509_ALGORITHM_IDENTIFIER SecAsn1AlgId +typedef SecAsn1AlgId *CSSM_X509_ALGORITHM_IDENTIFIER_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; /* X509 Distinguished name structure */ -typedef struct cssm_x509_type_value_pair { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_x509_type_value_pair { CSSM_OID type; CSSM_BER_TAG valueType; /* The Tag to be used when */ /*this value is BER encoded */ CSSM_DATA value; } CSSM_X509_TYPE_VALUE_PAIR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_TYPE_VALUE_PAIR_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_x509_rdn { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_x509_rdn { uint32 numberOfPairs; CSSM_X509_TYPE_VALUE_PAIR_PTR AttributeTypeAndValue; } CSSM_X509_RDN DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_RDN_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_x509_name { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_x509_name { uint32 numberOfRDNs; CSSM_X509_RDN_PTR RelativeDistinguishedName; } CSSM_X509_NAME DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_NAME_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; /* Public key info struct */ -typedef struct cssm_x509_subject_public_key_info { - CSSM_X509_ALGORITHM_IDENTIFIER algorithm; - CSSM_DATA subjectPublicKey; -} CSSM_X509_SUBJECT_PUBLIC_KEY_INFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_SUBJECT_PUBLIC_KEY_INFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; +#define CSSM_X509_SUBJECT_PUBLIC_KEY_INFO SecAsn1PubKeyInfo +typedef SecAsn1PubKeyInfo *CSSM_X509_SUBJECT_PUBLIC_KEY_INFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_x509_time { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_x509_time { CSSM_BER_TAG timeType; CSSM_DATA time; } CSSM_X509_TIME DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_TIME_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; /* Validity struct */ -typedef struct x509_validity { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER x509_validity { CSSM_X509_TIME notBefore; CSSM_X509_TIME notAfter; } CSSM_X509_VALIDITY DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_VALIDITY_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; @@ -114,7 +109,7 @@ typedef struct x509_validity { #define CSSM_X509_OPTION_NOT_PRESENT CSSM_FALSE typedef CSSM_BOOL CSSM_X509_OPTION; -typedef struct cssm_x509ext_basicConstraints { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_x509ext_basicConstraints { CSSM_BOOL cA; CSSM_X509_OPTION pathLenConstraintPresent; uint32 pathLenConstraint; @@ -126,22 +121,22 @@ typedef enum extension_data_format { CSSM_X509_DATAFORMAT_PAIR } CSSM_X509EXT_DATA_FORMAT; -typedef struct cssm_x509_extensionTagAndValue { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_x509_extensionTagAndValue { CSSM_BER_TAG type; CSSM_DATA value; } CSSM_X509EXT_TAGandVALUE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509EXT_TAGandVALUE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_x509ext_pair { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_x509ext_pair { CSSM_X509EXT_TAGandVALUE tagAndValue; void *parsedValue; } CSSM_X509EXT_PAIR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509EXT_PAIR_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; /* Extension structure */ -typedef struct cssm_x509_extension { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_x509_extension { CSSM_OID extnId; CSSM_BOOL critical; CSSM_X509EXT_DATA_FORMAT format; - union cssm_x509ext_value { + union DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_x509ext_value { CSSM_X509EXT_TAGandVALUE *tagAndValue; void *parsedValue; CSSM_X509EXT_PAIR *valuePair; @@ -149,13 +144,13 @@ typedef struct cssm_x509_extension { CSSM_DATA BERvalue; } CSSM_X509_EXTENSION DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_EXTENSION_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_x509_extensions { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_x509_extensions { uint32 numberOfExtensions; CSSM_X509_EXTENSION_PTR extensions; } CSSM_X509_EXTENSIONS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_EXTENSIONS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; /* X509V3 certificate structure */ -typedef struct cssm_x509_tbs_certificate { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_x509_tbs_certificate { CSSM_DATA version; CSSM_DATA serialNumber; CSSM_X509_ALGORITHM_IDENTIFIER signature; @@ -169,28 +164,28 @@ typedef struct cssm_x509_tbs_certificate { } CSSM_X509_TBS_CERTIFICATE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_TBS_CERTIFICATE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; /* Signature structure */ -typedef struct cssm_x509_signature { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_x509_signature { CSSM_X509_ALGORITHM_IDENTIFIER algorithmIdentifier; CSSM_DATA encrypted; } CSSM_X509_SIGNATURE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_SIGNATURE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; /* Signed certificate structure */ -typedef struct cssm_x509_signed_certificate { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_x509_signed_certificate { CSSM_X509_TBS_CERTIFICATE certificate; CSSM_X509_SIGNATURE signature; } CSSM_X509_SIGNED_CERTIFICATE DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_SIGNED_CERTIFICATE_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_x509ext_policyQualifierInfo { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_x509ext_policyQualifierInfo { CSSM_OID policyQualifierId; CSSM_DATA value; } CSSM_X509EXT_POLICYQUALIFIERINFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509EXT_POLICYQUALIFIERINFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_x509ext_policyQualifiers { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_x509ext_policyQualifiers { uint32 numberOfPolicyQualifiers; CSSM_X509EXT_POLICYQUALIFIERINFO *policyQualifier; } CSSM_X509EXT_POLICYQUALIFIERS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509EXT_POLICYQUALIFIERS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_x509ext_policyInfo { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_x509ext_policyInfo { CSSM_OID policyIdentifier; CSSM_X509EXT_POLICYQUALIFIERS policyQualifiers; } CSSM_X509EXT_POLICYINFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509EXT_POLICYINFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; @@ -199,19 +194,19 @@ typedef struct cssm_x509ext_policyInfo { /* Data Structures for X.509 Certificate Revocations Lists */ /* x509V2 entry in the CRL revokedCertificates sequence */ -typedef struct cssm_x509_revoked_cert_entry { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_x509_revoked_cert_entry { CSSM_DATA certificateSerialNumber; CSSM_X509_TIME revocationDate; CSSM_X509_EXTENSIONS extensions; } CSSM_X509_REVOKED_CERT_ENTRY DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_REVOKED_CERT_ENTRY_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_x509_revoked_cert_list { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_x509_revoked_cert_list { uint32 numberOfRevokedCertEntries; CSSM_X509_REVOKED_CERT_ENTRY_PTR revokedCertEntry; } CSSM_X509_REVOKED_CERT_LIST DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_REVOKED_CERT_LIST_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; /* x509v2 Certificate Revocation List (CRL) (unsigned) structure */ -typedef struct cssm_x509_tbs_certlist { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_x509_tbs_certlist { CSSM_DATA version; CSSM_X509_ALGORITHM_IDENTIFIER signature; CSSM_X509_NAME issuer; @@ -221,7 +216,7 @@ typedef struct cssm_x509_tbs_certlist { CSSM_X509_EXTENSIONS extensions; } CSSM_X509_TBS_CERTLIST DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_TBS_CERTLIST_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; -typedef struct cssm_x509_signed_crl { +typedef struct DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER cssm_x509_signed_crl { CSSM_X509_TBS_CERTLIST tbsCertList; CSSM_X509_SIGNATURE signature; } CSSM_X509_SIGNED_CRL DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_SIGNED_CRL_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; diff --git a/OSX/libsecurity_filedb/lib/AtomicFile.cpp b/OSX/libsecurity_filedb/lib/AtomicFile.cpp index 9dd9bbfdc..6c21d12d2 100644 --- a/OSX/libsecurity_filedb/lib/AtomicFile.cpp +++ b/OSX/libsecurity_filedb/lib/AtomicFile.cpp @@ -18,10 +18,10 @@ #include -#include #include #include #include +#include #include #include #include @@ -962,7 +962,6 @@ std::string NetworkFileLocker::unique(mode_t mode) { static const int randomPart = 16; - DevRandomGenerator randomGen; std::string::size_type dirSize = mDir.size(); std::string fullname(dirSize + randomPart + 2, '\0'); fullname.replace(0, dirSize, mDir); @@ -974,7 +973,7 @@ NetworkFileLocker::unique(mode_t mode) for (int retries = 0; retries < 10; ++retries) { /* Make a random filename. */ - randomGen.random(buf, randomPart); + MacOSError::check(SecRandomCopyBytes(kSecRandomDefault, randomPart, buf)); for (int ix = 0; ix < randomPart; ++ix) { char ch = buf[ix] & 0x3f; diff --git a/OSX/libsecurity_keychain/lib/ACL.cpp b/OSX/libsecurity_keychain/lib/ACL.cpp index 3c328bf4b..77beb3ada 100644 --- a/OSX/libsecurity_keychain/lib/ACL.cpp +++ b/OSX/libsecurity_keychain/lib/ACL.cpp @@ -31,8 +31,7 @@ #include #include #include -#include -#include +#include #include @@ -108,7 +107,7 @@ ACL::ACL(Allocator &alloc) mPromptSelector = defaultSelector; // randomize the CSSM handle - UniformRandomBlobs().random(mCssmHandle); + MacOSError::check(SecRandomCopyBytes(kSecRandomDefault, sizeof(mCssmHandle), (void *)mCssmHandle)); } @@ -129,7 +128,7 @@ ACL::ACL(string description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR &promptSele mPromptSelector = promptSelector; // randomize the CSSM handle - UniformRandomBlobs().random(mCssmHandle); + MacOSError::check(SecRandomCopyBytes(kSecRandomDefault, sizeof(mCssmHandle), &mCssmHandle)); } @@ -149,7 +148,7 @@ ACL::ACL(const CssmData &digest, Allocator &alloc) //mPromptSelector stays empty // randomize the CSSM handle - UniformRandomBlobs().random(mCssmHandle); + MacOSError::check(SecRandomCopyBytes(kSecRandomDefault, sizeof(mCssmHandle), &mCssmHandle)); } diff --git a/OSX/libsecurity_keychain/lib/Access.cpp b/OSX/libsecurity_keychain/lib/Access.cpp index 64da867e9..032bbb6eb 100644 --- a/OSX/libsecurity_keychain/lib/Access.cpp +++ b/OSX/libsecurity_keychain/lib/Access.cpp @@ -27,11 +27,10 @@ #include #include #include "SecBridge.h" -#include -#include +#include #include #include -#include +#include using namespace KeychainCore; using namespace CssmClient; @@ -364,8 +363,9 @@ Access::Maker::Maker(Allocator &alloc, MakerType makerType) { // generate random key mKey.malloc(keySize); - UniformRandomBlobs().random(mKey.get()); - + CssmData data = mKey.get(); + MacOSError::check(SecRandomCopyBytes(kSecRandomDefault, data.length(), data.data())); + // create entry info for resource creation mInput = AclEntryPrototype(TypedList(allocator, CSSM_ACL_SUBJECT_TYPE_PASSWORD, new(allocator) ListElement(mKey.get()))); diff --git a/OSX/libsecurity_keychain/lib/CCallbackMgr.cp b/OSX/libsecurity_keychain/lib/CCallbackMgr.cp index 6fac59b63..96da5d8e0 100644 --- a/OSX/libsecurity_keychain/lib/CCallbackMgr.cp +++ b/OSX/libsecurity_keychain/lib/CCallbackMgr.cp @@ -310,7 +310,23 @@ void CCallbackMgr::consume (SecurityServer::NotificationDomain domain, SecurityS Keychain thisKeychain; Item thisItem; - list eventCallbacks; + list eventCallbacks = CCallbackMgr::Instance().mEventCallbacks; + + // First, does this process care about this notification? If not, just exit early. + bool careAboutEventType = thisEvent == kSecDeleteEvent || thisEvent == kSecKeychainListChangedEvent; + bool registeredCallbacksForEventType = false; + for (ConstCallbackInfoListIterator ix = eventCallbacks.begin(); ix != eventCallbacks.end(); ++ix) + { + if ((ix->mEventMask & (1U << thisEvent))) { + registeredCallbacksForEventType = true; + break; + } + } + if(!careAboutEventType && !registeredCallbacksForEventType) { + secinfo("kcnotify", "not processing uninteresting event (%d)", (unsigned int)thisEvent); + return; + } + { // Lock the global API lock before doing stuff with StorageManager. // make sure we have a database identifier @@ -342,7 +358,6 @@ void CCallbackMgr::consume (SecurityServer::NotificationDomain domain, SecurityS else if (thisEvent == kSecKeychainListChangedEvent) globals().storageManager.forceUserSearchListReread(); - eventCallbacks = CCallbackMgr::Instance().mEventCallbacks; // We can safely release the global API lock now since thisKeychain and thisItem // are CFRetained and will be until they go out of scope. } diff --git a/OSX/libsecurity_keychain/lib/Certificate.cpp b/OSX/libsecurity_keychain/lib/Certificate.cpp index 81dc86996..2ee5cbc2a 100644 --- a/OSX/libsecurity_keychain/lib/Certificate.cpp +++ b/OSX/libsecurity_keychain/lib/Certificate.cpp @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include diff --git a/OSX/libsecurity_keychain/lib/CertificateValues.cpp b/OSX/libsecurity_keychain/lib/CertificateValues.cpp index 7fd526d1e..a2f1ec1b8 100644 --- a/OSX/libsecurity_keychain/lib/CertificateValues.cpp +++ b/OSX/libsecurity_keychain/lib/CertificateValues.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-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, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -31,17 +31,14 @@ #include #include "SecCertificateOIDs.h" #include "CertificateValues.h" -#include "SecCertificateP.h" -#include "SecCertificatePrivP.h" #include -#include "SecCertificateP.h" -/* FIXME including SecCertificateInternalP.h here produces errors; investigate */ -extern "C" CFDataRef SecCertificateCopyIssuerSequenceP(SecCertificateRefP certificate); -extern "C" CFDataRef SecCertificateCopySubjectSequenceP(SecCertificateRefP certificate); -extern "C" CFDictionaryRef SecCertificateCopyAttributeDictionaryP(SecCertificateRefP certificate); - -extern "C" void appendPropertyP(CFMutableArrayRef properties, CFStringRef propertyType, CFStringRef label, CFTypeRef value); +// SecCertificateInternal.h cannot be included in this file, due to its +// use of types which are not resolved in our macOS-only library. +// +extern "C" CFArrayRef SecCertificateCopyLegacyProperties(SecCertificateRef certificate); +extern "C" void appendProperty(CFMutableArrayRef properties, CFStringRef propertyType, + CFStringRef label, CFStringRef localizedLabel, CFTypeRef value); extern const CFStringRef __nonnull kSecPropertyKeyType; extern const CFStringRef __nonnull kSecPropertyKeyLabel; @@ -52,9 +49,8 @@ extern const CFStringRef __nonnull kSecPropertyTypeData; extern const CFStringRef __nonnull kSecPropertyTypeString; extern const CFStringRef __nonnull kSecPropertyTypeURL; extern const CFStringRef __nonnull kSecPropertyTypeDate; - -CFStringRef kSecPropertyTypeArray = CFSTR("array"); -CFStringRef kSecPropertyTypeNumber = CFSTR("number"); +extern const CFStringRef __nonnull kSecPropertyTypeArray; +extern const CFStringRef __nonnull kSecPropertyTypeNumber; #pragma mark ---------- CertificateValues Implementation ---------- @@ -75,7 +71,8 @@ typedef struct FieldValueFilterContext } FieldValueFilterContext; CertificateValues::CertificateValues(SecCertificateRef certificateRef) : mCertificateRef(certificateRef), - mCertificateData(NULL) + mCertificateData(NULL), + mCertificateProperties(NULL) { if (mCertificateRef) CFRetain(mCertificateRef); @@ -83,12 +80,29 @@ CertificateValues::CertificateValues(SecCertificateRef certificateRef) : mCertif CertificateValues::~CertificateValues() throw() { + if (mCertificateProperties) + CFRelease(mCertificateProperties); if (mCertificateData) CFRelease(mCertificateData); if (mCertificateRef) CFRelease(mCertificateRef); } +CFArrayRef CertificateValues::copyPropertyValues(CFErrorRef *error) +{ + if (!mCertificateProperties) { + mCertificateProperties = SecCertificateCopyLegacyProperties(mCertificateRef); + } + if (mCertificateProperties) { + CFRetain(mCertificateProperties); + } + else if (error) { + *error = CFErrorCreate(NULL, + kCFErrorDomainOSStatus, errSecInvalidCertificateRef, NULL); + } + return mCertificateProperties; +} + CFDictionaryRef CertificateValues::copyFieldValues(CFArrayRef keys, CFErrorRef *error) { if (keys) @@ -119,8 +133,8 @@ CFDictionaryRef CertificateValues::copyFieldValues(CFArrayRef keys, CFErrorRef * } } - SecCertificateRefP certificateP = SecCertificateCreateWithDataP(kCFAllocatorDefault, mCertificateData); - if (!certificateP) + SecCertificateRef certificate = SecCertificateCreateWithData(kCFAllocatorDefault, mCertificateData); + if (!certificate) { if (error) *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInvalidCertificateGroup, NULL); @@ -131,93 +145,93 @@ CFDictionaryRef CertificateValues::copyFieldValues(CFArrayRef keys, CFErrorRef * &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); // Return an array of CFStringRefs representing the common names in the certificates subject if any - CFArrayRef commonNames=SecCertificateCopyCommonNamesP(certificateP); + CFArrayRef commonNames=SecCertificateCopyCommonNames(certificate); if (commonNames) { CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - appendPropertyP(additionalValues, kSecPropertyTypeArray, CFSTR("CN"), commonNames); + appendProperty(additionalValues, kSecPropertyTypeArray, CFSTR("CN"), NULL, commonNames); CFDictionaryAddValue(fieldValues, kSecOIDCommonName, (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); CFRelease(commonNames); CFRelease(additionalValues); } // These can exist in the subject alt name or in the subject - CFArrayRef dnsNames=SecCertificateCopyDNSNamesP(certificateP); + CFArrayRef dnsNames=SecCertificateCopyDNSNames(certificate); if (dnsNames) { CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - appendPropertyP(additionalValues, kSecPropertyTypeArray, CFSTR("DNS"), dnsNames); + appendProperty(additionalValues, kSecPropertyTypeArray, CFSTR("DNS"), NULL, dnsNames); CFDictionaryAddValue(fieldValues, CFSTR("DNSNAMES"), (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); CFRelease(dnsNames); CFRelease(additionalValues); } - CFArrayRef ipAddresses=SecCertificateCopyIPAddressesP(certificateP); + CFArrayRef ipAddresses=SecCertificateCopyIPAddresses(certificate); if (ipAddresses) { CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - appendPropertyP(additionalValues, kSecPropertyTypeArray, CFSTR("IP"), dnsNames); + appendProperty(additionalValues, kSecPropertyTypeArray, CFSTR("IP"), NULL, dnsNames); CFDictionaryAddValue(fieldValues, CFSTR("IPADDRESSES"), (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); CFRelease(ipAddresses); CFRelease(additionalValues); } // These can exist in the subject alt name or in the subject - CFArrayRef emailAddrs=SecCertificateCopyRFC822NamesP(certificateP); + CFArrayRef emailAddrs=SecCertificateCopyRFC822Names(certificate); if (emailAddrs) { CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - appendPropertyP(additionalValues, kSecPropertyTypeArray, CFSTR("DNS"), dnsNames); + appendProperty(additionalValues, kSecPropertyTypeArray, CFSTR("DNS"), NULL, dnsNames); CFDictionaryAddValue(fieldValues, kSecOIDEmailAddress, (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); CFRelease(emailAddrs); CFRelease(additionalValues); } - CFAbsoluteTime notBefore = SecCertificateNotValidBeforeP(certificateP); + CFAbsoluteTime notBefore = SecCertificateNotValidBefore(certificate); CFNumberRef notBeforeRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, ¬Before); if (notBeforeRef) { CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - appendPropertyP(additionalValues, kSecPropertyTypeNumber, CFSTR("Not Valid Before"), notBeforeRef); + appendProperty(additionalValues, kSecPropertyTypeNumber, CFSTR("Not Valid Before"), NULL, notBeforeRef); CFDictionaryAddValue(fieldValues, kSecOIDX509V1ValidityNotBefore, (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); CFRelease(notBeforeRef); CFRelease(additionalValues); } - CFAbsoluteTime notAfter = SecCertificateNotValidAfterP(certificateP); + CFAbsoluteTime notAfter = SecCertificateNotValidAfter(certificate); CFNumberRef notAfterRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, ¬After); if (notAfterRef) { CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - appendPropertyP(additionalValues, kSecPropertyTypeNumber, CFSTR("Not Valid After"), notAfterRef); + appendProperty(additionalValues, kSecPropertyTypeNumber, CFSTR("Not Valid After"), NULL, notAfterRef); CFDictionaryAddValue(fieldValues, kSecOIDX509V1ValidityNotAfter, (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); CFRelease(notAfterRef); CFRelease(additionalValues); } - SecKeyUsage keyUsage=SecCertificateGetKeyUsageP(certificateP); + SecKeyUsage keyUsage=SecCertificateGetKeyUsage(certificate); CFNumberRef ku = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &keyUsage); if (ku) { CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - appendPropertyP(additionalValues, kSecPropertyTypeNumber, CFSTR("Key Usage"), ku); + appendProperty(additionalValues, kSecPropertyTypeNumber, CFSTR("Key Usage"), NULL, ku); CFDictionaryAddValue(fieldValues, kSecOIDKeyUsage, (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); CFRelease(ku); CFRelease(additionalValues); } - CFArrayRef ekus = SecCertificateCopyExtendedKeyUsageP(certificateP); + CFArrayRef ekus = SecCertificateCopyExtendedKeyUsage(certificate); if (ekus) { CFMutableArrayRef additionalValues = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - appendPropertyP(additionalValues, kSecPropertyTypeArray, CFSTR("Extended Key Usage"), ekus); + appendProperty(additionalValues, kSecPropertyTypeArray, CFSTR("Extended Key Usage"), NULL, ekus); CFDictionaryAddValue(fieldValues, kSecOIDExtendedKeyUsage, (CFTypeRef)CFArrayGetValueAtIndex(additionalValues, 0)); CFRelease(ekus); CFRelease(additionalValues); } // Add all values from properties dictionary - CFArrayRef properties = SecCertificateCopyPropertiesP(certificateP); + CFArrayRef properties = copyPropertyValues(NULL); if (properties) { CFRange range = CFRangeMake(0, CFArrayGetCount((CFArrayRef)properties)); @@ -228,7 +242,7 @@ CFDictionaryRef CertificateValues::copyFieldValues(CFArrayRef keys, CFErrorRef * CFAbsoluteTime verifyTime = CFAbsoluteTimeGetCurrent(); CFMutableArrayRef summaryProperties = - SecCertificateCopySummaryPropertiesP(certificateP, verifyTime); + SecCertificateCopySummaryProperties(certificate, verifyTime); if (summaryProperties) { CFRange range = CFRangeMake(0, CFArrayGetCount((CFArrayRef)summaryProperties)); @@ -238,8 +252,8 @@ CFDictionaryRef CertificateValues::copyFieldValues(CFArrayRef keys, CFErrorRef * CFRelease(summaryProperties); } - if (certificateP) - CFRelease(certificateP); + if (certificate) + CFRelease(certificate); if (keys==NULL) return (CFDictionaryRef)fieldValues; @@ -362,12 +376,12 @@ CFStringRef CertificateValues::remapLabelToKey(CFStringRef label) CFDataRef CertificateValues::copySerialNumber(CFErrorRef *error) { CFDataRef result = NULL; - SecCertificateRefP certificateP = getSecCertificateRefP(error); + SecCertificateRef certificate = copySecCertificateRef(error); - if (certificateP) + if (certificate) { - result = SecCertificateCopySerialNumberP(certificateP); - CFRelease(certificateP); + result = SecCertificateCopySerialNumberData(certificate, error); + CFRelease(certificate); } return result; } @@ -375,11 +389,14 @@ CFDataRef CertificateValues::copySerialNumber(CFErrorRef *error) CFDataRef CertificateValues::copyNormalizedIssuerContent(CFErrorRef *error) { CFDataRef result = NULL; - SecCertificateRefP certificateP = getSecCertificateRefP(error); - if (certificateP) + SecCertificateRef certificate = copySecCertificateRef(error); + if (certificate) { - result = SecCertificateCopyNormalizedIssuerSequenceP(certificateP); - CFRelease(certificateP); + // this matches the behavior on OS X prior to 10.12, where + // normalized content was actually returned as a sequence. + + result = SecCertificateCopyNormalizedIssuerSequence(certificate); + CFRelease(certificate); } return result; } @@ -387,11 +404,14 @@ CFDataRef CertificateValues::copyNormalizedIssuerContent(CFErrorRef *error) CFDataRef CertificateValues::copyNormalizedSubjectContent(CFErrorRef *error) { CFDataRef result = NULL; - SecCertificateRefP certificateP = getSecCertificateRefP(error); - if (certificateP) + SecCertificateRef certificate = copySecCertificateRef(error); + if (certificate) { - result = SecCertificateCopyNormalizedSubjectSequenceP(certificateP); - CFRelease(certificateP); + // this matches the behavior on OS X prior to 10.12, where + // normalized content was actually returned as a sequence. + + result = SecCertificateCopyNormalizedSubjectSequence(certificate); + CFRelease(certificate); } return result; } @@ -399,11 +419,11 @@ CFDataRef CertificateValues::copyNormalizedSubjectContent(CFErrorRef *error) CFDataRef CertificateValues::copyIssuerSequence(CFErrorRef *error) { CFDataRef result = NULL; - SecCertificateRefP certificateP = getSecCertificateRefP(error); - if (certificateP) + SecCertificateRef certificate = copySecCertificateRef(error); + if (certificate) { - result = SecCertificateCopyIssuerSequenceP(certificateP); - CFRelease(certificateP); + result = SecCertificateCopyIssuerSequence(certificate); + CFRelease(certificate); } return result; } @@ -411,35 +431,59 @@ CFDataRef CertificateValues::copyIssuerSequence(CFErrorRef *error) CFDataRef CertificateValues::copySubjectSequence(CFErrorRef *error) { CFDataRef result = NULL; - SecCertificateRefP certificateP = getSecCertificateRefP(error); - if (certificateP) + SecCertificateRef certificate = copySecCertificateRef(error); + if (certificate) { - result = SecCertificateCopySubjectSequenceP(certificateP); - CFRelease(certificateP); + result = SecCertificateCopySubjectSequence(certificate); + CFRelease(certificate); + } + return result; +} + +CFStringRef CertificateValues::copyIssuerSummary(CFErrorRef *error) +{ + CFStringRef result = NULL; + SecCertificateRef certificate = copySecCertificateRef(error); + if (certificate) + { + result = SecCertificateCopyIssuerSummary(certificate); + CFRelease(certificate); + } + return result; +} + +CFStringRef CertificateValues::copySubjectSummary(CFErrorRef *error) +{ + CFStringRef result = NULL; + SecCertificateRef certificate = copySecCertificateRef(error); + if (certificate) + { + result = SecCertificateCopySubjectSummary(certificate); + CFRelease(certificate); } return result; } CFDictionaryRef CertificateValues::copyAttributeDictionary(CFErrorRef *error) { - CFDictionaryRef result = NULL; - SecCertificateRefP certificateP = getSecCertificateRefP(error); - if (certificateP) - { - result = SecCertificateCopyAttributeDictionaryP(certificateP); - CFRelease(certificateP); - } - return result; + CFDictionaryRef result = NULL; + SecCertificateRef certificate = copySecCertificateRef(error); + if (certificate) + { + result = SecCertificateCopyAttributeDictionary(certificate); + CFRelease(certificate); + } + return result; } bool CertificateValues::isValid(CFAbsoluteTime verifyTime, CFErrorRef *error) { bool result = NULL; - SecCertificateRefP certificateP = getSecCertificateRefP(error); - if (certificateP) + SecCertificateRef certificate = copySecCertificateRef(error); + if (certificate) { - result = SecCertificateIsValidP(certificateP, verifyTime); - CFRelease(certificateP); + result = SecCertificateIsValid(certificate, verifyTime); + CFRelease(certificate); } return result; } @@ -447,11 +491,11 @@ bool CertificateValues::isValid(CFAbsoluteTime verifyTime, CFErrorRef *error) CFAbsoluteTime CertificateValues::notValidBefore(CFErrorRef *error) { CFAbsoluteTime result = 0; - SecCertificateRefP certificateP = getSecCertificateRefP(error); - if (certificateP) + SecCertificateRef certificate = copySecCertificateRef(error); + if (certificate) { - result = SecCertificateNotValidBeforeP(certificateP); - CFRelease(certificateP); + result = SecCertificateNotValidBefore(certificate); + CFRelease(certificate); } return result; } @@ -459,16 +503,16 @@ CFAbsoluteTime CertificateValues::notValidBefore(CFErrorRef *error) CFAbsoluteTime CertificateValues::notValidAfter(CFErrorRef *error) { CFAbsoluteTime result = 0; - SecCertificateRefP certificateP = getSecCertificateRefP(error); - if (certificateP) + SecCertificateRef certificate = copySecCertificateRef(error); + if (certificate) { - result = SecCertificateNotValidAfterP(certificateP); - CFRelease(certificateP); + result = SecCertificateNotValidAfter(certificate); + CFRelease(certificate); } return result; } -SecCertificateRefP CertificateValues::getSecCertificateRefP(CFErrorRef *error) +SecCertificateRef CertificateValues::copySecCertificateRef(CFErrorRef *error) { // SecCertificateCopyData returns an object created with CFDataCreate, so we // own it and must release it @@ -480,20 +524,26 @@ SecCertificateRefP CertificateValues::getSecCertificateRefP(CFErrorRef *error) } mCertificateData = SecCertificateCopyData(mCertificateRef); // OK to call, no big lock - if (!mCertificateData && error) + if (!mCertificateData) { - *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInvalidCertificateRef, NULL); + if (error) + { + *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInvalidCertificateRef, NULL); + } return NULL; } - SecCertificateRefP certificateP = SecCertificateCreateWithDataP(kCFAllocatorDefault, mCertificateData); - if (!certificateP && error) + SecCertificateRef certificate = SecCertificateCreateWithData(kCFAllocatorDefault, mCertificateData); + if (!certificate) { - *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInvalidCertificateGroup, NULL); + if (error) + { + *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecInvalidCertificateGroup, NULL); + } return NULL; } - return certificateP; + return certificate; } #pragma mark ---------- OID Constants ---------- diff --git a/OSX/libsecurity_keychain/lib/CertificateValues.h b/OSX/libsecurity_keychain/lib/CertificateValues.h index 37de693fc..41d17c3fe 100644 --- a/OSX/libsecurity_keychain/lib/CertificateValues.h +++ b/OSX/libsecurity_keychain/lib/CertificateValues.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-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, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -27,9 +27,8 @@ #ifndef _SECURITY_CERTIFICATEVALUES_H_ #define _SECURITY_CERTIFICATEVALUES_H_ -#include -#include "SecBaseP.h" -//#include +#include + namespace Security { @@ -37,33 +36,37 @@ namespace Security namespace KeychainCore { -class CertificateValues// : public SecCFObject +class CertificateValues { NOCOPY(CertificateValues) public: CertificateValues(SecCertificateRef certificateRef); - virtual ~CertificateValues() throw(); + virtual ~CertificateValues() throw(); static CFStringRef remapLabelToKey(CFStringRef label); + CFArrayRef copyPropertyValues(CFErrorRef *error); CFDictionaryRef copyFieldValues(CFArrayRef keys, CFErrorRef *error); CFDataRef copySerialNumber(CFErrorRef *error); CFDataRef copyNormalizedIssuerContent(CFErrorRef *error); CFDataRef copyNormalizedSubjectContent(CFErrorRef *error); CFDataRef copyIssuerSequence(CFErrorRef *error); CFDataRef copySubjectSequence(CFErrorRef *error); - CFDictionaryRef copyAttributeDictionary(CFErrorRef *error); + CFStringRef copyIssuerSummary(CFErrorRef *error); + CFStringRef copySubjectSummary(CFErrorRef *error); + CFDictionaryRef copyAttributeDictionary(CFErrorRef *error); bool isValid(CFAbsoluteTime verifyTime, CFErrorRef *error); CFAbsoluteTime notValidBefore(CFErrorRef *error); CFAbsoluteTime notValidAfter(CFErrorRef *error); private: - SecCertificateRefP getSecCertificateRefP(CFErrorRef *error); + SecCertificateRef copySecCertificateRef(CFErrorRef *error); SecCertificateRef mCertificateRef; CFDataRef mCertificateData; + CFArrayRef mCertificateProperties; static CFDictionaryRef mOIDRemap; }; diff --git a/OSX/libsecurity_keychain/lib/DLDBListCFPref.cpp b/OSX/libsecurity_keychain/lib/DLDBListCFPref.cpp index 3cd84cc4e..aa168bd8b 100644 --- a/OSX/libsecurity_keychain/lib/DLDBListCFPref.cpp +++ b/OSX/libsecurity_keychain/lib/DLDBListCFPref.cpp @@ -1034,6 +1034,12 @@ DLDbListCFPref::defaultDLDbIdentifier() if (mDefaultDLDbIdentifier.mImpl != NULL && actualIdentifier.mImpl != NULL) { st_result = stat(actualIdentifier.dbName(), &st); + + // Always claim that the system keychain exists for purposes of the search list + if (st_result && 0 == strncmp(actualIdentifier.dbName(), kSystemKeychainPath, strlen(kSystemKeychainPath))) { + secnotice("secpref", "System keychain (%s) does not exist. Continuing as if it does...", actualIdentifier.dbName()); + st_result = 0; + } } if (st_result) diff --git a/OSX/libsecurity_keychain/lib/Identity.cpp b/OSX/libsecurity_keychain/lib/Identity.cpp index 52be5fece..85b0636de 100644 --- a/OSX/libsecurity_keychain/lib/Identity.cpp +++ b/OSX/libsecurity_keychain/lib/Identity.cpp @@ -61,7 +61,7 @@ Identity::Identity(const StorageManager::KeychainList &keychains, const SecPoint kCFAllocatorNull); // First, try the new iOS keychain. { - const void *keys[] = { kSecClass, kSecAttrKeyClass, kSecAttrApplicationLabel, kSecReturnRef, kSecAttrNoLegacy }; + const void *keys[] = { kSecClass, kSecAttrKeyClass, kSecAttrApplicationLabel, kSecReturnRef, kSecUseDataProtectionKeychain }; const void *values[] = { kSecClassKey, kSecAttrKeyClassPrivate, keyHash, kCFBooleanTrue, kCFBooleanTrue }; CFRef query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, sizeof(keys) / sizeof(*keys), diff --git a/OSX/libsecurity_keychain/lib/IdentityCursor.cpp b/OSX/libsecurity_keychain/lib/IdentityCursor.cpp index 7a19a2cac..519b47c25 100644 --- a/OSX/libsecurity_keychain/lib/IdentityCursor.cpp +++ b/OSX/libsecurity_keychain/lib/IdentityCursor.cpp @@ -275,7 +275,7 @@ IdentityCursor::~IdentityCursor() throw() { } -CFDataRef +CFDataRef CF_RETURNS_RETAINED IdentityCursor::pubKeyHashForSystemIdentity(CFStringRef domain) { StLock_(mMutex); diff --git a/OSX/libsecurity_keychain/lib/Item.cpp b/OSX/libsecurity_keychain/lib/Item.cpp index ff064c1a0..474aba73a 100644 --- a/OSX/libsecurity_keychain/lib/Item.cpp +++ b/OSX/libsecurity_keychain/lib/Item.cpp @@ -46,9 +46,7 @@ #include #include -#include - -#define SENDACCESSNOTIFICATIONS 1 +#include //%%% schema indexes should be defined in Schema.h #define _kSecAppleSharePasswordItemClass 'ashp' @@ -196,14 +194,22 @@ ItemImpl::ItemImpl(ItemImpl &item) : } ItemImpl::~ItemImpl() -{ +try { if (secd_PersistentRef) { CFRelease(secd_PersistentRef); } +} catch (...) { +#ifndef NDEBUG + /* if we get an exception in destructor, presumably the mutex, lets throw if we + * are in a debug build (ie reach end of block) */ +#else + return; +#endif } + Mutex* ItemImpl::getMutexForObject() const { @@ -632,7 +638,7 @@ bool ItemImpl::checkIntegrityFromDictionary(AclBearer& aclBearer, DbAttributes* return false; // No MAC, no integrity. } - throw cssme; + throw; } secnotice("integrity", "***** INVALID ITEM"); @@ -1407,23 +1413,12 @@ ItemImpl::getContent(SecItemClass *itemClass, SecKeychainAttributeList *attrList { getLocalContent(attrList, length, outData); } - - // Inform anyone interested that we are doing this -#if SENDACCESSNOTIFICATIONS - if (outData) - { - secinfo("kcnotify", "ItemImpl::getContent(%p, %p, %p, %p) retrieved content", - itemClass, attrList, length, outData); - - KCEventNotifier::PostKeychainEvent(kSecDataAccessEvent, mKeychain, this); - } -#endif } void ItemImpl::freeContent(SecKeychainAttributeList *attrList, void *data) { - Allocator &allocator = Allocator::standard(); // @@@ This might not match the one used originally + Allocator &allocator = Allocator::standard(Allocator::sensitive); // @@@ This might not match the one used originally if (data) allocator.free(data); @@ -1565,13 +1560,6 @@ ItemImpl::getAttributesAndData(SecKeychainAttributeInfo *info, SecItemClass *ite if (length) *length=(UInt32)itemData.length(); itemData.Length=0; - -#if SENDACCESSNOTIFICATIONS - secinfo("kcnotify", "ItemImpl::getAttributesAndData(%p, %p, %p, %p, %p) retrieved data", - info, itemClass, attrList, length, outData); - - KCEventNotifier::PostKeychainEvent(kSecDataAccessEvent, mKeychain, this); -#endif } } @@ -1579,7 +1567,7 @@ ItemImpl::getAttributesAndData(SecKeychainAttributeInfo *info, SecItemClass *ite void ItemImpl::freeAttributesAndData(SecKeychainAttributeList *attrList, void *data) { - Allocator &allocator = Allocator::standard(); // @@@ This might not match the one used originally + Allocator &allocator = Allocator::standard(Allocator::sensitive); // @@@ This might not match the one used originally if (data) allocator.free(data); @@ -1732,13 +1720,6 @@ ItemImpl::getData(CssmDataContainer& outData) } getContent(NULL, &outData); - -#if SENDACCESSNOTIFICATIONS - secinfo("kcnotify", "ItemImpl::getData retrieved data"); - - //%%% be done elsewhere, but here is good for now - KCEventNotifier::PostKeychainEvent(kSecDataAccessEvent, mKeychain, this); -#endif } SSGroup @@ -1825,7 +1806,7 @@ ItemImpl::getContent(DbAttributes *dbAttributes, CssmDataContainer *itemData) } } catch(CssmError cssme) { secnotice("integrity", "error while checking integrity, denying access: %s", cssme.what()); - throw cssme; + throw; } SSDbUniqueRecordImpl* impl = dynamic_cast(&(*dbUniqueRecord())); diff --git a/OSX/libsecurity_keychain/lib/KCCursor.cpp b/OSX/libsecurity_keychain/lib/KCCursor.cpp index a5d25d961..ad7039cf3 100644 --- a/OSX/libsecurity_keychain/lib/KCCursor.cpp +++ b/OSX/libsecurity_keychain/lib/KCCursor.cpp @@ -35,7 +35,7 @@ #include "Globals.h" #include "StorageManager.h" #include -#include +#include #include #include diff --git a/OSX/libsecurity_keychain/lib/KCExceptions.h b/OSX/libsecurity_keychain/lib/KCExceptions.h index 4f1fb8199..69cf84354 100644 --- a/OSX/libsecurity_keychain/lib/KCExceptions.h +++ b/OSX/libsecurity_keychain/lib/KCExceptions.h @@ -29,7 +29,7 @@ #define _SECURITY_KCEXCEPTIONS_H_ #include -#include +#include #ifdef lock #undef lock #endif diff --git a/OSX/libsecurity_keychain/lib/KCUtilities.h b/OSX/libsecurity_keychain/lib/KCUtilities.h index b0174e5bf..b6c0a01d0 100644 --- a/OSX/libsecurity_keychain/lib/KCUtilities.h +++ b/OSX/libsecurity_keychain/lib/KCUtilities.h @@ -25,7 +25,7 @@ #define _SECURITY_KCUTILITIES_H_ #include -#include +#include namespace Security { diff --git a/OSX/libsecurity_keychain/lib/KeyItem.cpp b/OSX/libsecurity_keychain/lib/KeyItem.cpp index 12f7113fa..6bec5672a 100644 --- a/OSX/libsecurity_keychain/lib/KeyItem.cpp +++ b/OSX/libsecurity_keychain/lib/KeyItem.cpp @@ -38,8 +38,8 @@ #include #include "KCEventNotifier.h" #include -#include -#include +#include +#include #include // @@@ This needs to be shared. @@ -81,6 +81,7 @@ KeyItem::operator CFTypeRef() const throw() if (mWeakSecKeyRef != NULL) { if (_CFTryRetain(mWeakSecKeyRef) == NULL) { + StMaybeLock secKeyCDSAMutex(static_cast(mWeakSecKeyRef)->cdsaKeyMutex); // mWeakSecKeyRef is not really valid, pointing to SecKeyRef which going to die - it is somewhere between last CFRelease and entering into mutex-protected section of SecCDSAKeyDestroy. Avoid using it, pretend that no enveloping SecKeyRef exists. But make sure that this KeyImpl is disconnected from this about-to-die SecKeyRef, because we do not want KeyImpl connected to it to be really destroyed, it will be connected to newly created SecKeyRef (see below). mWeakSecKeyRef->key = NULL; mWeakSecKeyRef = NULL; @@ -488,7 +489,7 @@ KeyItem::key() } catch(CssmError cssme) { mKey.release(); secnotice("integrity", "error while checking integrity, denying access: %s", cssme.what()); - throw cssme; + throw; } } diff --git a/OSX/libsecurity_keychain/lib/KeyItem.h b/OSX/libsecurity_keychain/lib/KeyItem.h index 54691919b..8f048f5ce 100644 --- a/OSX/libsecurity_keychain/lib/KeyItem.h +++ b/OSX/libsecurity_keychain/lib/KeyItem.h @@ -164,12 +164,14 @@ class KeyItem : public ItemImpl } // end namespace Security -struct OpaqueSecKeyRef { - CFRuntimeBase _base; - const SecKeyDescriptor *key_class; - SecKeyRef cdsaKey; - Security::KeychainCore::KeyItem *key; +class CDSASecKey : public __SecKey { +public: + static Security::KeychainCore::KeyItem *keyItem(SecKeyRef key) { + CDSASecKey *cdsaKey = static_cast(key); + return static_cast(cdsaKey->key); + } SecCredentialType credentialType; + Mutex *cdsaKeyMutex; }; #endif // !_SECURITY_KEYITEM_H_ diff --git a/OSX/libsecurity_keychain/lib/Keychains.cpp b/OSX/libsecurity_keychain/lib/Keychains.cpp index e3ce4cb06..2b125fa8e 100644 --- a/OSX/libsecurity_keychain/lib/Keychains.cpp +++ b/OSX/libsecurity_keychain/lib/Keychains.cpp @@ -656,11 +656,14 @@ KeychainImpl::changePassphrase(UInt32 oldPasswordLength, const void *oldPassword UInt32 newPasswordLength, const void *newPassword) { StLock_(mMutex); - + + secnotice("KCspi", "Attempting to change passphrase for %s", mDb->name()); + bool isSmartcard = (mDb->dl()->guid() == gGuidAppleSdCSPDL); TrackingAllocator allocator(Allocator::standard()); AutoCredentials cred = AutoCredentials(allocator); + if (oldPassword) { const CssmData &oldPass = *new(allocator) CssmData(const_cast(oldPassword), oldPasswordLength); diff --git a/OSX/libsecurity_keychain/lib/MacOSErrorStrings.h b/OSX/libsecurity_keychain/lib/MacOSErrorStrings.h index 02e6195b9..fb9ef2fdf 100644 --- a/OSX/libsecurity_keychain/lib/MacOSErrorStrings.h +++ b/OSX/libsecurity_keychain/lib/MacOSErrorStrings.h @@ -56,6 +56,6 @@ enum errSecMisc_cantGetFlavorErr = -1854, /* The location (URL) of this item is missing or improperly formatted. */ errSecMisc_afpAccessDenied = -5000, /* Access to this item was denied. */ errSecMisc_afpUserNotAuth = -5023, /* Authentication failed. The password for this server may have changed since the item was added to the keychain. */ - errSecMisc_afpPwdPolicyErr = -5046 /* This AppleShare IP server is configured to not allow users to save passwords for automatic login. Contact the server administrator for more information. */ + errSecMisc_afpPwdPolicyErr = -5046, /* This AppleShare IP server is configured to not allow users to save passwords for automatic login. Contact the server administrator for more information. */ }; diff --git a/OSX/libsecurity_keychain/lib/PolicyCursor.cpp b/OSX/libsecurity_keychain/lib/PolicyCursor.cpp index aa12338ff..d8db218b8 100644 --- a/OSX/libsecurity_keychain/lib/PolicyCursor.cpp +++ b/OSX/libsecurity_keychain/lib/PolicyCursor.cpp @@ -42,26 +42,29 @@ struct TheOneTP : public TP { }; static ModuleNexus theOneTP; -static const CssmOid *theOidList[] = { - static_cast(&CSSMOID_APPLE_ISIGN), - static_cast(&CSSMOID_APPLE_X509_BASIC), - static_cast(&CSSMOID_APPLE_TP_SSL), - static_cast(&CSSMOID_APPLE_TP_SMIME), - static_cast(&CSSMOID_APPLE_TP_EAP), - static_cast(&CSSMOID_APPLE_TP_SW_UPDATE_SIGNING), - static_cast(&CSSMOID_APPLE_TP_IP_SEC), - static_cast(&CSSMOID_APPLE_TP_ICHAT), - static_cast(&CSSMOID_APPLE_TP_RESOURCE_SIGN), - static_cast(&CSSMOID_APPLE_TP_PKINIT_CLIENT), - static_cast(&CSSMOID_APPLE_TP_PKINIT_SERVER), - static_cast(&CSSMOID_APPLE_TP_CODE_SIGNING), - static_cast(&CSSMOID_APPLE_TP_PACKAGE_SIGNING), - static_cast(&CSSMOID_APPLE_TP_REVOCATION_CRL), - static_cast(&CSSMOID_APPLE_TP_REVOCATION_OCSP), - static_cast(&CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT), - static_cast(&CSSMOID_APPLE_TP_APPLEID_SHARING), - static_cast(&CSSMOID_APPLE_TP_TIMESTAMPING), - NULL // sentinel +static const CssmOid** theOidList() { + static const CssmOid* list[] = { + static_cast(&CSSMOID_APPLE_ISIGN), + static_cast(&CSSMOID_APPLE_X509_BASIC), + static_cast(&CSSMOID_APPLE_TP_SSL), + static_cast(&CSSMOID_APPLE_TP_SMIME), + static_cast(&CSSMOID_APPLE_TP_EAP), + static_cast(&CSSMOID_APPLE_TP_SW_UPDATE_SIGNING), + static_cast(&CSSMOID_APPLE_TP_IP_SEC), + static_cast(&CSSMOID_APPLE_TP_ICHAT), + static_cast(&CSSMOID_APPLE_TP_RESOURCE_SIGN), + static_cast(&CSSMOID_APPLE_TP_PKINIT_CLIENT), + static_cast(&CSSMOID_APPLE_TP_PKINIT_SERVER), + static_cast(&CSSMOID_APPLE_TP_CODE_SIGNING), + static_cast(&CSSMOID_APPLE_TP_PACKAGE_SIGNING), + static_cast(&CSSMOID_APPLE_TP_REVOCATION_CRL), + static_cast(&CSSMOID_APPLE_TP_REVOCATION_OCSP), + static_cast(&CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT), + static_cast(&CSSMOID_APPLE_TP_APPLEID_SHARING), + static_cast(&CSSMOID_APPLE_TP_TIMESTAMPING), + NULL // sentinel + }; + return list; }; @@ -94,13 +97,13 @@ bool PolicyCursor::next(SecPointer &policy) { StLock_(mMutex); - while (theOidList[mSearchPos]) { - if (mOidGiven && mOid != *theOidList[mSearchPos]) { + while (theOidList()[mSearchPos]) { + if (mOidGiven && mOid != *(theOidList()[mSearchPos])) { mSearchPos++; continue; // no oid match } // ignoring mValue - not used by current TP - policy = new Policy(theOneTP(), *theOidList[mSearchPos]); + policy = new Policy(theOneTP(), *(theOidList()[mSearchPos])); mSearchPos++; // advance cursor return true; // return next match } diff --git a/OSX/libsecurity_keychain/lib/SecACL.cpp b/OSX/libsecurity_keychain/lib/SecACL.cpp index d91458b3c..5e5dbb7b3 100644 --- a/OSX/libsecurity_keychain/lib/SecACL.cpp +++ b/OSX/libsecurity_keychain/lib/SecACL.cpp @@ -50,9 +50,6 @@ CFTypeID SecACLGetTypeID(void) { BEGIN_SECAPI - os_activity_t activity = os_activity_create("SecACLGetTypeID", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); - os_activity_scope(activity); - os_release(activity); return gTypes().ACL.typeID; diff --git a/OSX/libsecurity_keychain/lib/SecACL.h b/OSX/libsecurity_keychain/lib/SecACL.h index abc9f8146..1bb1101d0 100644 --- a/OSX/libsecurity_keychain/lib/SecACL.h +++ b/OSX/libsecurity_keychain/lib/SecACL.h @@ -81,7 +81,7 @@ CF_IMPLICIT_BRIDGING_ENABLED CFStringRef description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector, SecACLRef * __nonnull CF_RETURNS_RETAINED newAcl) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + CSSM_DEPRECATED; /*! @function SecACLCreateWithSimpleContents @@ -124,7 +124,7 @@ CF_IMPLICIT_BRIDGING_ENABLED CFArrayRef * __nonnull CF_RETURNS_RETAINED applicationList, CFStringRef * __nonnull CF_RETURNS_RETAINED description, CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + CSSM_DEPRECATED; /*! @function SecACLCopyContents @@ -155,7 +155,7 @@ CF_IMPLICIT_BRIDGING_ENABLED CFArrayRef __nullable applicationList, CFStringRef description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + CSSM_DEPRECATED; /*! @function SecACLSetContents @@ -186,7 +186,7 @@ CF_IMPLICIT_BRIDGING_ENABLED */ OSStatus SecACLGetAuthorizations(SecACLRef acl, CSSM_ACL_AUTHORIZATION_TAG *tags, uint32 *tagCount) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + CSSM_DEPRECATED; /*! @function SecACLCopyAuthorizations @@ -209,7 +209,7 @@ CF_IMPLICIT_BRIDGING_ENABLED */ OSStatus SecACLSetAuthorizations(SecACLRef acl, CSSM_ACL_AUTHORIZATION_TAG *tags, uint32 tagCount) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + CSSM_DEPRECATED; /*! diff --git a/OSX/libsecurity_keychain/lib/SecAccess.cpp b/OSX/libsecurity_keychain/lib/SecAccess.cpp index bb3adfc67..91680d824 100644 --- a/OSX/libsecurity_keychain/lib/SecAccess.cpp +++ b/OSX/libsecurity_keychain/lib/SecAccess.cpp @@ -21,7 +21,7 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include +#include #include #include #include @@ -321,10 +321,7 @@ SecAccessRef SecAccessCreateWithOwnerAndACL(uid_t userId, gid_t groupId, SecAcce CFRelease(debugStr); #endif - CFIndex rightsSize = numAcls > 0 ? numAcls : 1; - - CSSM_ACL_AUTHORIZATION_TAG rights[rightsSize]; - memset(rights, 0, sizeof(rights)); + std::vector rights(numAcls); for (CFIndex iCnt = 0; iCnt < numAcls; iCnt++) { @@ -384,7 +381,7 @@ SecAccessRef SecAccessCreateWithOwnerAndACL(uid_t userId, gid_t groupId, SecAcce { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 }, false, // Delegate // rights for this entry - { (uint32)numAcls, rights }, + { (uint32)numAcls, rights.data() }, // rest is defaulted } } diff --git a/OSX/libsecurity_keychain/lib/SecAccess.h b/OSX/libsecurity_keychain/lib/SecAccess.h index 2ba660807..d9e151ce6 100644 --- a/OSX/libsecurity_keychain/lib/SecAccess.h +++ b/OSX/libsecurity_keychain/lib/SecAccess.h @@ -1,15 +1,15 @@ /* * 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, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -97,11 +97,11 @@ extern const CFStringRef kSecACLAuthorizationKeychainItemModify __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); extern const CFStringRef kSecACLAuthorizationKeychainItemDelete __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); - -extern const CFStringRef kSecACLAuthorizationChangeACL - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + +extern const CFStringRef kSecACLAuthorizationChangeACL + __OSX_AVAILABLE_STARTING(__MAC_10_13_4, __IPHONE_NA); extern const CFStringRef kSecACLAuthorizationChangeOwner - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + __OSX_AVAILABLE_STARTING(__MAC_10_13_4, __IPHONE_NA); extern const CFStringRef kSecACLAuthorizationPartitionID __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_NA); extern const CFStringRef kSecACLAuthorizationIntegrity @@ -127,7 +127,7 @@ CFTypeID SecAccessGetTypeID(void); @param accessRef On return, a pointer to the new access reference. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecAccessCreate(CFStringRef descriptor, CFArrayRef __nullable trustedlist, SecAccessRef * __nonnull CF_RETURNS_RETAINED accessRef); +OSStatus SecAccessCreate(CFStringRef descriptor, CFArrayRef __nullable trustedlist, SecAccessRef * __nonnull CF_RETURNS_RETAINED accessRef) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); /*! @function SecAccessCreateFromOwnerAndACL @@ -140,8 +140,8 @@ OSStatus SecAccessCreate(CFStringRef descriptor, CFArrayRef __nullable trustedli @discussion For 10.7 and later please use the SecAccessCreateWithOwnerAndACL API */ OSStatus SecAccessCreateFromOwnerAndACL(const CSSM_ACL_OWNER_PROTOTYPE *owner, uint32 aclCount, const CSSM_ACL_ENTRY_INFO *acls, SecAccessRef * __nonnull CF_RETURNS_RETAINED accessRef) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - + CSSM_DEPRECATED; + /*! @function SecAccessCreateWithOwnerAndACL @abstract Creates a new SecAccessRef using either for a user or a group with a list of ACLs @@ -167,8 +167,8 @@ SecAccessRef SecAccessCreateWithOwnerAndACL(uid_t userId, gid_t groupId, SecAcce @discussion For 10.7 and later please use the SecAccessCopyOwnerAndACL API */ OSStatus SecAccessGetOwnerAndACL(SecAccessRef accessRef, CSSM_ACL_OWNER_PROTOTYPE_PTR __nullable * __nonnull owner, uint32 *aclCount, CSSM_ACL_ENTRY_INFO_PTR __nullable * __nonnull acls) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; - + CSSM_DEPRECATED; + /*! @function SecAccessCopyOwnerAndACL @abstract Retrieves the owner and the access control list of a given access. @@ -178,7 +178,7 @@ OSStatus SecAccessGetOwnerAndACL(SecAccessRef accessRef, CSSM_ACL_OWNER_PROTOTYP @param ownerType On return, the type of owner for this AccessRef @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 SecAccessCopyOwnerAndACL(SecAccessRef accessRef, uid_t * __nullable userId, gid_t * __nullable groupId, SecAccessOwnerType * __nullable ownerType, CFArrayRef * __nullable CF_RETURNS_RETAINED aclList) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); @@ -189,7 +189,7 @@ OSStatus SecAccessCopyOwnerAndACL(SecAccessRef accessRef, uid_t * __nullable use @param aclList On return, a pointer to a new created CFArray of SecACL instances. The caller is responsible for calling CFRelease on this array. @result A result code. See "Security Error Codes" (SecBase.h). */ -OSStatus SecAccessCopyACLList(SecAccessRef accessRef, CFArrayRef * __nonnull CF_RETURNS_RETAINED aclList); +OSStatus SecAccessCopyACLList(SecAccessRef accessRef, CFArrayRef * __nonnull CF_RETURNS_RETAINED aclList) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); /*! @function SecAccessCopySelectedACLList @@ -201,7 +201,7 @@ OSStatus SecAccessCopyACLList(SecAccessRef accessRef, CFArrayRef * __nonnull CF_ @discussion For 10.7 and later please use the SecAccessCopyMatchingACLList API */ OSStatus SecAccessCopySelectedACLList(SecAccessRef accessRef, CSSM_ACL_AUTHORIZATION_TAG action, CFArrayRef * __nonnull CF_RETURNS_RETAINED aclList) - DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; + CSSM_DEPRECATED; /*! diff --git a/OSX/libsecurity_keychain/lib/SecAccessPriv.h b/OSX/libsecurity_keychain/lib/SecAccessPriv.h index 4e61067e5..9596f4fc8 100644 --- a/OSX/libsecurity_keychain/lib/SecAccessPriv.h +++ b/OSX/libsecurity_keychain/lib/SecAccessPriv.h @@ -1,15 +1,15 @@ /* * 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, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -40,7 +40,7 @@ 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"); + UInt32 passwordLength, const void *passwordData, SecKeychainItemRef *itemRef) __deprecated_msg("iTools is no longer supported") API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); /*! @function SecAccessCreateWithTrustedApplications @@ -50,12 +50,12 @@ OSStatus SecKeychainAddIToolsPassword(SecKeychainRef keychain, UInt32 accountNam @param allowAny Flag that determines allow access to any application. @param returnedAccess On return, a new SecAccessRef. @result A result code. See "Security Error Codes" (SecBase.h). - @discussion The SecAccessCreateWithPList creates a SecAccess with the provided list of 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); +OSStatus SecAccessCreateWithTrustedApplications(CFStringRef trustedApplicationsPListPath, CFStringRef accessLabel, Boolean allowAny, SecAccessRef* returnedAccess) API_UNAVAILABLE(ios, watchos, tvos, bridgeos, iosmac); + - #if defined(__cplusplus) } #endif diff --git a/OSX/libsecurity_keychain/lib/SecAsn1TypesP.h b/OSX/libsecurity_keychain/lib/SecAsn1TypesP.h deleted file mode 100644 index 2a027acbe..000000000 --- a/OSX/libsecurity_keychain/lib/SecAsn1TypesP.h +++ /dev/null @@ -1,241 +0,0 @@ -/* - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1994-2000 Netscape Communications Corporation. All - * Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your - * version of this file only under the terms of the GPL and not to - * allow others to use your version of this file under the MPL, - * indicate your decision by deleting the provisions above and - * replace them with the notice and other provisions required by - * the GPL. If you do not delete the provisions above, a recipient - * may use your version of this file under either the MPL or the - * GPL. - */ - -/* - * Types for encoding/decoding of ASN.1 using BER/DER (Basic/Distinguished - * Encoding Rules). - */ - -#ifndef _SEC_ASN1_TYPES_H_ -#define _SEC_ASN1_TYPES_H_ - -#include /* Boolean */ -#include -#include - -#include -#if 1 /* TARGET_OS_EMBEDDED */ -/* @@@ We need something that tells us which platform we are building - for that let's us distinguish if we are doing an emulator build. */ - -typedef struct { - size_t Length; - uint8_t *Data; -} SecAsn1Item, SecAsn1Oid; - -typedef struct { - SecAsn1Oid algorithm; - SecAsn1Item parameters; -} SecAsn1AlgId; - -typedef struct { - SecAsn1AlgId algorithm; - SecAsn1Item subjectPublicKey; -} SecAsn1PubKeyInfo; - -#else -#include -#include - -typedef CSSM_DATA SecAsn1Item; -typedef CSSM_OID SecAsn1Oid; -typedef CSSM_X509_ALGORITHM_IDENTIFIER SecAsn1AlgId; -typedef CSSM_X509_SUBJECT_PUBLIC_KEY_INFO SecAsn1PubKeyInfo; - -#endif - -/* - * An array of these structures defines a BER/DER encoding for an object. - * - * The array usually starts with a dummy entry whose kind is SEC_ASN1_SEQUENCE; - * such an array is terminated with an entry where kind == 0. (An array - * which consists of a single component does not require a second dummy - * entry -- the array is only searched as long as previous component(s) - * instruct it.) - */ -typedef struct SecAsn1Template_struct { - /* - * Kind of item being decoded/encoded, including tags and modifiers. - */ - uint32_t kind; - - /* - * This value is the offset from the base of the structure (i.e., the - * (void *) passed as 'src' to SecAsn1EncodeItem, or the 'dst' argument - * passed to SecAsn1CoderRef()) to the field that holds the value being - * decoded/encoded. - */ - uint32_t offset; - - /* - * When kind suggests it (e.g., SEC_ASN1_POINTER, SEC_ASN1_GROUP, - * SEC_ASN1_INLINE, or a component that is *not* a SEC_ASN1_UNIVERSAL), - * this points to a sub-template for nested encoding/decoding. - * OR, iff SEC_ASN1_DYNAMIC is set, then this is a pointer to a pointer - * to a function which will return the appropriate template when called - * at runtime. NOTE! that explicit level of indirection, which is - * necessary because ANSI does not allow you to store a function - * pointer directly as a "void *" so we must store it separately and - * dereference it to get at the function pointer itself. - */ - const void *sub; - - /* - * In the first element of a template array, the value is the size - * of the structure to allocate when this template is being referenced - * by another template via SEC_ASN1_POINTER or SEC_ASN1_GROUP. - * In all other cases, the value is ignored. - */ - uint32_t size; -} SecAsn1Template; - - -/* - * BER/DER values for ASN.1 identifier octets. - */ -#define SEC_ASN1_TAG_MASK 0xff - -/* - * BER/DER universal type tag numbers. - */ -#define SEC_ASN1_TAGNUM_MASK 0x1f -#define SEC_ASN1_BOOLEAN 0x01 -#define SEC_ASN1_INTEGER 0x02 -#define SEC_ASN1_BIT_STRING 0x03 -#define SEC_ASN1_OCTET_STRING 0x04 -#define SEC_ASN1_NULL 0x05 -#define SEC_ASN1_OBJECT_ID 0x06 -#define SEC_ASN1_OBJECT_DESCRIPTOR 0x07 -/* External type and instance-of type 0x08 */ -#define SEC_ASN1_REAL 0x09 -#define SEC_ASN1_ENUMERATED 0x0a -#define SEC_ASN1_EMBEDDED_PDV 0x0b -#define SEC_ASN1_UTF8_STRING 0x0c -/* not used 0x0d */ -/* not used 0x0e */ -/* not used 0x0f */ -#define SEC_ASN1_SEQUENCE 0x10 -#define SEC_ASN1_SET 0x11 -#define SEC_ASN1_NUMERIC_STRING 0x12 -#define SEC_ASN1_PRINTABLE_STRING 0x13 -#define SEC_ASN1_T61_STRING 0x14 -#define SEC_ASN1_VIDEOTEX_STRING 0x15 -#define SEC_ASN1_IA5_STRING 0x16 -#define SEC_ASN1_UTC_TIME 0x17 -#define SEC_ASN1_GENERALIZED_TIME 0x18 -#define SEC_ASN1_GRAPHIC_STRING 0x19 -#define SEC_ASN1_VISIBLE_STRING 0x1a -#define SEC_ASN1_GENERAL_STRING 0x1b -#define SEC_ASN1_UNIVERSAL_STRING 0x1c -/* not used 0x1d */ -#define SEC_ASN1_BMP_STRING 0x1e -#define SEC_ASN1_HIGH_TAG_NUMBER 0x1f -#define SEC_ASN1_TELETEX_STRING SEC_ASN1_T61_STRING - -/* - * Modifiers to type tags. These are also specified by a/the - * standard, and must not be changed. - */ -#define SEC_ASN1_METHOD_MASK 0x20 -#define SEC_ASN1_PRIMITIVE 0x00 -#define SEC_ASN1_CONSTRUCTED 0x20 - -#define SEC_ASN1_CLASS_MASK 0xc0 -#define SEC_ASN1_UNIVERSAL 0x00 -#define SEC_ASN1_APPLICATION 0x40 -#define SEC_ASN1_CONTEXT_SPECIFIC 0x80 -#define SEC_ASN1_PRIVATE 0xc0 - -/* - * Our additions, used for templates. - * These are not defined by any standard; the values are used internally only. - * Just be careful to keep them out of the low 8 bits. - */ -#define SEC_ASN1_OPTIONAL 0x00100 -#define SEC_ASN1_EXPLICIT 0x00200 -#define SEC_ASN1_ANY 0x00400 -#define SEC_ASN1_INLINE 0x00800 -#define SEC_ASN1_POINTER 0x01000 -#define SEC_ASN1_GROUP 0x02000 /* with SET or SEQUENCE means - * SET OF or SEQUENCE OF */ -#define SEC_ASN1_DYNAMIC 0x04000 /* subtemplate is found by calling - * a function at runtime */ -#define SEC_ASN1_SKIP 0x08000 /* skip a field; only for decoding */ -#define SEC_ASN1_INNER 0x10000 /* with ANY means capture the - * contents only (not the id, len, - * or eoc); only for decoding */ -#define SEC_ASN1_SAVE 0x20000 /* stash away the encoded bytes first; - * only for decoding */ -#define SEC_ASN1_SKIP_REST 0x80000 /* skip all following fields; - * only for decoding */ -#define SEC_ASN1_CHOICE 0x100000 /* pick one from a template */ - -/* - * Indicate that a type SEC_ASN1_INTEGER is actually signed. - * The default is unsigned, which causes a leading zero to be - * encoded if the MS bit of the source data is 1. - */ -#define SEC_ASN1_SIGNED_INT 0X800000 - -/* Shorthand/Aliases */ -#define SEC_ASN1_SEQUENCE_OF (SEC_ASN1_GROUP | SEC_ASN1_SEQUENCE) -#define SEC_ASN1_SET_OF (SEC_ASN1_GROUP | SEC_ASN1_SET) -#define SEC_ASN1_ANY_CONTENTS (SEC_ASN1_ANY | SEC_ASN1_INNER) - -/* - * Function used for SEC_ASN1_DYNAMIC. - * "arg" is a pointer to the top-level structure being encoded or - * decoded. - * - * "enc" when true, means that we are encoding (false means decoding) - * - * "buf" For decode only; points to the start of the decoded data for - * the current template. Callee can use the tag at this location - * to infer the returned template. Not used on encode. - * - * "Dest" points to the template-specific item being decoded to - * or encoded from. (This is as opposed to arg, which - * points to the start of the struct associated with the - * current array of templates). - */ - -typedef const SecAsn1Template * SecAsn1TemplateChooser( - void *arg, - Boolean enc, - const char *buf, - void *dest); - -typedef SecAsn1TemplateChooser * SecAsn1TemplateChooserPtr; - - -#endif /* _SEC_ASN1_TYPES_H_ */ diff --git a/OSX/libsecurity_keychain/lib/SecBase.cpp b/OSX/libsecurity_keychain/lib/SecBase.cpp index 096349ed4..2d82dd360 100644 --- a/OSX/libsecurity_keychain/lib/SecBase.cpp +++ b/OSX/libsecurity_keychain/lib/SecBase.cpp @@ -27,6 +27,7 @@ #include #include #include "SecBridge.h" +#include static CFStringRef copyErrorMessageFromBundle(OSStatus status,CFStringRef tableName); @@ -98,7 +99,7 @@ cssmErrorString(CSSM_RETURN error) CFStringRef result = copyErrorMessageFromBundle(error,CFSTR("SecErrorMessages")); if (result == NULL) result = copyErrorMessageFromBundle(error,CFSTR("SecDebugErrorMessages")); - err = cfString(result, true); + err = cfString(result, errSecErrorStringNotAvailable); CFReleaseSafe(result); } @@ -299,7 +300,7 @@ OSStatus SecKeychainErrFromOSStatus(OSStatus osStatus) case CSSMERR_DL_DATASTORE_ALREADY_EXISTS: return errSecDuplicateKeychain; case CSSMERR_APPLEDL_DISK_FULL: - return errSecDskFull; + return errSecDiskFull; case CSSMERR_DL_INVALID_OPEN_PARAMETERS: case CSSMERR_APPLEDL_INVALID_OPEN_PARAMETERS: case CSSMERR_APPLE_DOTMAC_REQ_SERVER_PARAM: diff --git a/OSX/libsecurity_keychain/lib/SecBase64P.c b/OSX/libsecurity_keychain/lib/SecBase64P.c deleted file mode 100644 index c043906cd..000000000 --- a/OSX/libsecurity_keychain/lib/SecBase64P.c +++ /dev/null @@ -1,489 +0,0 @@ -/* ///////////////////////////////////////////////////////////////////////////// - * File: b64.c - * - * Purpose: Implementation file for the b64 library - * - * Created: 18th October 2004 - * Updated: 2nd August 2006 - * - * Home: http://synesis.com.au/software/ - * - * Copyright (c) 2004-2006, Matthew Wilson and Synesis Software - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of - * any contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * ////////////////////////////////////////////////////////////////////////// */ - - -/** \file b64.c Implementation file for the b64 library - */ - -#include "SecBase64P.h" - -#include -#include - -/* ///////////////////////////////////////////////////////////////////////////// - * Constants and definitions - */ - -#ifndef B64_DOCUMENTATION_SKIP_SECTION -# define NUM_PLAIN_DATA_BYTES (3) -# define NUM_ENCODED_DATA_BYTES (4) -#endif /* !B64_DOCUMENTATION_SKIP_SECTION */ - -/* ///////////////////////////////////////////////////////////////////////////// - * Warnings - */ - -#if defined(_MSC_VER) && \ - _MSC_VER < 1000 -# pragma warning(disable : 4705) -#endif /* _MSC_VER < 1000 */ - -/* ///////////////////////////////////////////////////////////////////////////// - * Data - */ - -static const char b64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -static const signed char b64_indexes[] = -{ - /* 0 - 31 / 0x00 - 0x1f */ - -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1 - /* 32 - 63 / 0x20 - 0x3f */ - , -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, 62, -1, -1, -1, 63 /* ... , '+', ... '/' */ - , 52, 53, 54, 55, 56, 57, 58, 59 /* '0' - '7' */ - , 60, 61, -1, -1, -1, -1, -1, -1 /* '8', '9', ... */ - /* 64 - 95 / 0x40 - 0x5f */ - , -1, 0, 1, 2, 3, 4, 5, 6 /* ..., 'A' - 'G' */ - , 7, 8, 9, 10, 11, 12, 13, 14 /* 'H' - 'O' */ - , 15, 16, 17, 18, 19, 20, 21, 22 /* 'P' - 'W' */ - , 23, 24, 25, -1, -1, -1, -1, -1 /* 'X', 'Y', 'Z', ... */ - /* 96 - 127 / 0x60 - 0x7f */ - , -1, 26, 27, 28, 29, 30, 31, 32 /* ..., 'a' - 'g' */ - , 33, 34, 35, 36, 37, 38, 39, 40 /* 'h' - 'o' */ - , 41, 42, 43, 44, 45, 46, 47, 48 /* 'p' - 'w' */ - , 49, 50, 51, -1, -1, -1, -1, -1 /* 'x', 'y', 'z', ... */ - - , -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1 - - , -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1 - - , -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1 - - , -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1 - , -1, -1, -1, -1, -1, -1, -1, -1 -}; - -/* ///////////////////////////////////////////////////////////////////////////// - * Helper functions - */ - -/** This function reads in 3 bytes at a time, and translates them into 4 - * characters. - */ -static size_t SecBase64Encode_( unsigned char const *src - , size_t srcSize - , char *const dest - , size_t destLen - , unsigned lineLen - , SecBase64Result *rc) -{ - size_t total = ((srcSize + (NUM_PLAIN_DATA_BYTES - 1)) / NUM_PLAIN_DATA_BYTES) * NUM_ENCODED_DATA_BYTES; - - assert(NULL != rc); - *rc = kSecB64_R_OK; - - if(lineLen > 0) - { - size_t numLines = (total + (lineLen - 1)) / lineLen; - - total += 2 * (numLines - 1); - } - - if(NULL == dest) - { - return total; - } - else if(destLen < total) - { - *rc = kSecB64_R_INSUFFICIENT_BUFFER; - - return 0; - } - else - { - char *p = dest; - char *end = dest + destLen; - size_t len = 0; - - for(; NUM_PLAIN_DATA_BYTES <= srcSize; srcSize -= NUM_PLAIN_DATA_BYTES) - { - char characters[NUM_ENCODED_DATA_BYTES]; - - /* - * - * | 0 | 1 | 2 | - * - * | | | | - * | | | | | | | - * | | | | | | | | | | | | | - * | | | | | | | | | | | | | | | | | | | | | | | | | - * - * | 0 | 1 | 2 | 3 | - * - */ - - /* characters[0] is the 6 left-most bits of src[0] */ - characters[0] = (char)((src[0] & 0xfc) >> 2); - /* characters[0] is the right-most 2 bits of src[0] and the left-most 4 bits of src[1] */ - characters[1] = (char)(((src[0] & 0x03) << 4) + ((src[1] & 0xf0) >> 4)); - /* characters[0] is the right-most 4 bits of src[1] and the 2 left-most bits of src[2] */ - characters[2] = (char)(((src[1] & 0x0f) << 2) + ((src[2] & 0xc0) >> 6)); - /* characters[3] is the right-most 6 bits of src[2] */ - characters[3] = (char)(src[2] & 0x3f); - -#ifndef __WATCOMC__ - assert(characters[0] >= 0 && characters[0] < 64); - assert(characters[1] >= 0 && characters[1] < 64); - assert(characters[2] >= 0 && characters[2] < 64); - assert(characters[3] >= 0 && characters[3] < 64); -#endif /* __WATCOMC__ */ - - src += NUM_PLAIN_DATA_BYTES; - *p++ = b64_chars[(unsigned char)characters[0]]; - assert(NULL != strchr(b64_chars, *(p-1))); - ++len; - assert(len != lineLen); - - *p++ = b64_chars[(unsigned char)characters[1]]; - assert(NULL != strchr(b64_chars, *(p-1))); - ++len; - assert(len != lineLen); - - *p++ = b64_chars[(unsigned char)characters[2]]; - assert(NULL != strchr(b64_chars, *(p-1))); - ++len; - assert(len != lineLen); - - *p++ = b64_chars[(unsigned char)characters[3]]; - assert(NULL != strchr(b64_chars, *(p-1))); - - if( ++len == lineLen && - p != end) - { - *p++ = '\r'; - *p++ = '\n'; - len = 0; - } - } - - if(0 != srcSize) - { - /* Deal with the overspill, by boosting it up to three bytes (using 0s) - * and then appending '=' for any missing characters. - * - * This is done into a temporary buffer, so we can call ourselves and - * have the output continue to be written direct to the destination. - */ - - unsigned char dummy[NUM_PLAIN_DATA_BYTES]; - size_t i; - - for(i = 0; i < srcSize; ++i) - { - dummy[i] = *src++; - } - - for(; i < NUM_PLAIN_DATA_BYTES; ++i) - { - dummy[i] = '\0'; - } - - SecBase64Encode_(&dummy[0], NUM_PLAIN_DATA_BYTES, p, NUM_ENCODED_DATA_BYTES * (1 + 2), 0, rc); - - for(p += 1 + srcSize; srcSize++ < NUM_PLAIN_DATA_BYTES; ) - { - *p++ = '='; - } - } - - return total; - } -} - -/** This function reads in a character string in 4-character chunks, and writes - * out the converted form in 3-byte chunks to the destination. - */ -static size_t SecBase64Decode_( char const *src - , size_t srcLen - , unsigned char *dest - , size_t destSize - , unsigned flags - , char const **badChar - , SecBase64Result *rc) -{ - const size_t wholeChunks = (srcLen / NUM_ENCODED_DATA_BYTES); - const size_t remainderBytes = (srcLen % NUM_ENCODED_DATA_BYTES); - size_t maxTotal = (wholeChunks + (0 != remainderBytes)) * NUM_PLAIN_DATA_BYTES; - unsigned char *dest_ = dest; - - ((void)remainderBytes); - - assert(NULL != badChar); - assert(NULL != rc); - - *badChar = NULL; - *rc = kSecB64_R_OK; - - if(NULL == dest) - { - return maxTotal; - } - else if(destSize < maxTotal) - { - *rc = kSecB64_R_INSUFFICIENT_BUFFER; - - return 0; - } - else - { - /* Now we iterate through the src, collecting together four characters - * at a time from the Base-64 alphabet, until the end-point is reached. - * - * - */ - - char const *begin = src; - char const *const end = begin + srcLen; - size_t currIndex = 0; - size_t numPads = 0; - signed char indexes[NUM_ENCODED_DATA_BYTES]; /* 4 */ - - for(; begin != end; ++begin) - { - const char ch = *begin; - - if('=' == ch) - { - assert(currIndex < NUM_ENCODED_DATA_BYTES); - - indexes[currIndex++] = '\0'; - - ++numPads; - } - else - { - signed char ix = b64_indexes[(unsigned char)ch]; - - if(-1 == ix) - { - switch(ch) - { - case ' ': - case '\t': - case '\b': - case '\v': - if(kSecB64_F_STOP_ON_UNEXPECTED_WS & flags) - { - *rc = kSecB64_R_DATA_ERROR; - *badChar = begin; - return 0; - } - else - { - /* Fall through */ - } - case '\r': - case '\n': - continue; - default: - if(kSecB64_F_STOP_ON_UNKNOWN_CHAR & flags) - { - *rc = kSecB64_R_DATA_ERROR; - *badChar = begin; - return 0; - } - else - { - continue; - } - } - } - else - { - numPads = 0; - - assert(currIndex < NUM_ENCODED_DATA_BYTES); - - indexes[currIndex++] = ix; - } - } - - if(NUM_ENCODED_DATA_BYTES == currIndex) - { - unsigned char bytes[NUM_PLAIN_DATA_BYTES]; /* 3 */ - - bytes[0] = (unsigned char)((indexes[0] << 2) + ((indexes[1] & 0x30) >> 4)); - - currIndex = 0; - - *dest++ = bytes[0]; - if(2 != numPads) - { - bytes[1] = (unsigned char)(((indexes[1] & 0xf) << 4) + ((indexes[2] & 0x3c) >> 2)); - - *dest++ = bytes[1]; - - if(1 != numPads) - { - bytes[2] = (unsigned char)(((indexes[2] & 0x3) << 6) + indexes[3]); - - *dest++ = bytes[2]; - } - } - if(0 != numPads) - { - break; - } - } - } - - return (size_t)(dest - dest_); - } -} - -/* ///////////////////////////////////////////////////////////////////////////// - * API functions - */ - -size_t SecBase64Encode(void const *src, size_t srcSize, char *dest, size_t destLen) -{ - /* Use Null Object (Variable) here for rc, so do not need to check - * elsewhere. - */ - SecBase64Result rc_; - - return SecBase64Encode_((unsigned char const*)src, srcSize, dest, destLen, 0, &rc_); -} - -size_t SecBase64Encode2( void const *src - , size_t srcSize - , char *dest - , size_t destLen - , unsigned flags - , int lineLen /* = -1 */ - , SecBase64Result *rc /* = NULL */) -{ - /* Use Null Object (Variable) here for rc, so do not need to check - * elsewhere - */ - SecBase64Result rc_; - if(NULL == rc) - { - rc = &rc_; - } - - switch(kSecB64_F_LINE_LEN_MASK & flags) - { - case kSecB64_F_LINE_LEN_USE_PARAM: - if(lineLen >= 0) - { - break; - } - /* Fall through to 64 */ - case kSecB64_F_LINE_LEN_64: - lineLen = 64; - break; - case kSecB64_F_LINE_LEN_76: - lineLen = 76; - break; - default: - assert(!"Bad line length flag specified to SecBase64Encode2()"); - case kSecB64_F_LINE_LEN_INFINITE: - lineLen = 0; - break; - } - - assert(0 == (lineLen % 4)); - - return SecBase64Encode_((unsigned char const*)src, srcSize, dest, destLen, (unsigned)lineLen, rc); -} - -size_t SecBase64Decode(char const *src, size_t srcLen, void *dest, size_t destSize) -{ - /* Use Null Object (Variable) here for rc and badChar, so do not need to - * check elsewhere. - */ - char const *badChar_; - SecBase64Result rc_; - - return SecBase64Decode_(src, srcLen, (unsigned char*)dest, destSize, kSecB64_F_STOP_ON_NOTHING, &badChar_, &rc_); -} - -size_t SecBase64Decode2( char const *src - , size_t srcLen - , void *dest - , size_t destSize - , unsigned flags - , char const **badChar /* = NULL */ - , SecBase64Result *rc /* = NULL */) -{ - char const *badChar_; - SecBase64Result rc_; - - /* Use Null Object (Variable) here for rc and badChar, so do not need to - * check elsewhere. - */ - if(NULL == badChar) - { - badChar = &badChar_; - } - if(NULL == rc) - { - rc = &rc_; - } - - return SecBase64Decode_(src, srcLen, (unsigned char*)dest, destSize, flags, badChar, rc); -} - -/* ////////////////////////////////////////////////////////////////////////// */ diff --git a/OSX/libsecurity_keychain/lib/SecBaseP.h b/OSX/libsecurity_keychain/lib/SecBaseP.h deleted file mode 100644 index dc4f9cd18..000000000 --- a/OSX/libsecurity_keychain/lib/SecBaseP.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2000-2009,2011 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 SecBase - SecBase contains common declarations for the Security functions. -*/ - -#ifndef _SECURITY_SECBASEP_H_ -#define _SECURITY_SECBASEP_H_ - -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -/*! - @typedef SecCertificateRef - @abstract CFType representing a X.509 certificate, see - SecCertificate.h for details. -*/ -typedef struct __SecCertificate *SecCertificateRefP; - -/*! - @typedef SecIdentityRef - @abstract CFType representing an identity, which contains - a SecKeyRef and an ascociated SecCertificateRef, see - SecIdentity.h for details. -*/ -typedef struct __SecIdentity *SecIdentityRefP; - -/*! - @typedef SecKeyRef - @abstract CFType representing an asymetric key, see - SecKey.h for details. -*/ -typedef struct __SecKey *SecKeyRefP; - -/*********************************************** - *** OSStatus values unique to Security APIs *** - ***********************************************/ - -/* - Note: the comments that appear after these errors are used to create - SecErrorMessages.strings. The comments must not be multi-line, and - should be in a form meaningful to an end user. If a different or - additional comment is needed, it can be put in the header doc format, - or on a line that does not start with errZZZ. -*/ - -#if 0 -enum -{ - errSecSuccess = 0, /* No error. */ - errSecUnimplemented = -4, /* Function or operation not implemented. */ - errSecParam = -50, /* One or more parameters passed to a function where not valid. */ - errSecAllocate = -108, /* Failed to allocate memory. */ - errSecNotAvailable = -25291, /* No keychain is available. You may need to restart your computer. */ - errSecDuplicateItem = -25299, /* The specified item already exists in the keychain. */ - errSecItemNotFound = -25300, /* The specified item could not be found in the keychain. */ - errSecInteractionNotAllowed = -25308, /* User interaction is not allowed. */ - errSecDecode = -26275, /* Unable to decode the provided data. */ -}; -#endif - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECBASEP_H_ */ diff --git a/OSX/libsecurity_keychain/lib/SecBridge.h b/OSX/libsecurity_keychain/lib/SecBridge.h index ed923939f..c52a5b296 100644 --- a/OSX/libsecurity_keychain/lib/SecBridge.h +++ b/OSX/libsecurity_keychain/lib/SecBridge.h @@ -26,7 +26,7 @@ #include #include -#include "SecBasePriv.h" +#include #include #include #include diff --git a/OSX/libsecurity_keychain/lib/SecCertificate.cpp b/OSX/libsecurity_keychain/lib/SecCertificate.cpp index a9b145d48..7c1e40b4a 100644 --- a/OSX/libsecurity_keychain/lib/SecCertificate.cpp +++ b/OSX/libsecurity_keychain/lib/SecCertificate.cpp @@ -45,8 +45,6 @@ #include #include #include "CertificateValues.h" -#include "SecCertificateP.h" -#include "SecCertificatePrivP.h" #include "AppleBaselineEscrowCertificates.h" @@ -54,11 +52,7 @@ OSStatus SecCertificateGetCLHandle_legacy(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle); extern CSSM_KEYUSE ConvertArrayToKeyUsage(CFArrayRef usage); -#define SEC_CONST_DECL(k,v) const CFStringRef k = CFSTR(v); -SEC_CONST_DECL (kSecCertificateProductionEscrowKey, "ProductionEscrowKey"); -SEC_CONST_DECL (kSecCertificateProductionPCSEscrowKey, "ProductionPCSEscrowKey"); -SEC_CONST_DECL (kSecCertificateEscrowFileName, "AppleESCertificates"); using namespace CssmClient; @@ -413,7 +407,7 @@ SecCertificateFindByIssuerAndSN(CFTypeRef keychainOrArray,const CSSM_DATA *issue CFRef query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(query, kSecClass, kSecClassCertificate); CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue); - CFDictionarySetValue(query, kSecAttrNoLegacy, kCFBooleanTrue); + CFDictionarySetValue(query, kSecUseDataProtectionKeychain, kCFBooleanTrue); CFRef issuerData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)issuer->Data, issuer->Length, kCFAllocatorNull); CFDictionarySetValue(query, kSecAttrIssuer, issuerData); @@ -452,7 +446,7 @@ SecCertificateFindBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *sub CFRef query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(query, kSecClass, kSecClassCertificate); CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue); - CFDictionarySetValue(query, kSecAttrNoLegacy, kCFBooleanTrue); + CFDictionarySetValue(query, kSecUseDataProtectionKeychain, kCFBooleanTrue); CFRef subjectKeyIDData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)subjectKeyID->Data, subjectKeyID->Length, kCFAllocatorNull); CFDictionarySetValue(query, kSecAttrSubjectKeyID, subjectKeyIDData); @@ -487,7 +481,7 @@ SecCertificateFindByEmail(CFTypeRef keychainOrArray, const char *emailAddress, S CFRef query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(query, kSecClass, kSecClassCertificate); CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue); - CFDictionarySetValue(query, kSecAttrNoLegacy, kCFBooleanTrue); + CFDictionarySetValue(query, kSecUseDataProtectionKeychain, kCFBooleanTrue); CFRef emailAddressString = CFStringCreateWithCString(kCFAllocatorDefault, emailAddress, kCFStringEncodingUTF8); CFTypeRef keys[] = { kSecPolicyName }; @@ -793,20 +787,28 @@ OSStatus SecCertificateSetPreference( const char *templateStr = "%s [key usage 0x%X]"; const int keyUsageMaxStrLen = 8; accountUTF8Len += strlen(templateStr) + keyUsageMaxStrLen; - char accountUTF8[accountUTF8Len]; + 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); - CssmData account(const_cast(accountUTF8), strlen(accountUTF8)); + CssmDataContainer account(const_cast(accountUTF8), strlen(accountUTF8)); + free(accountUTF8); CFRelease(labelStr); // service attribute (name provided by the caller) CFIndex serviceUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(name), kCFStringEncodingUTF8) + 1;; - char serviceUTF8[serviceUTF8Len]; + char *serviceUTF8 = (char *)malloc(serviceUTF8Len); + if (!serviceUTF8) { + MacOSError::throwMe(errSecMemoryError); + } if (!CFStringGetCString(name, serviceUTF8, serviceUTF8Len-1, kCFStringEncodingUTF8)) serviceUTF8[0] = (char)'\0'; - CssmData service(const_cast(serviceUTF8), strlen(serviceUTF8)); + CssmDataContainer service(const_cast(serviceUTF8), strlen(serviceUTF8)); + free(serviceUTF8); // look for existing preference item, in case this is an update StorageManager::KeychainList keychains; @@ -992,3 +994,20 @@ bool SecCertificateIsValidX(SecCertificateRef certificate, CFAbsoluteTime verify */ return SecCertificateIsValid(certificate, verifyTime); } + +/* OS X only */ +CFDataRef SecCertificateCopyPublicKeySHA1DigestFromCertificateData(CFAllocatorRef allocator, + CFDataRef der_certificate) +{ + CFDataRef result = NULL; + SecCertificateRef iosCertRef = SecCertificateCreateWithData(allocator, der_certificate); + if (NULL == iosCertRef) + { + return result; + } + + result = SecCertificateCopyPublicKeySHA1Digest(iosCertRef); + CFRelease(iosCertRef); + return result; +} + diff --git a/OSX/libsecurity_keychain/lib/SecCertificateBundle.h b/OSX/libsecurity_keychain/lib/SecCertificateBundle.h index f63160e01..d2bc3e10f 100644 --- a/OSX/libsecurity_keychain/lib/SecCertificateBundle.h +++ b/OSX/libsecurity_keychain/lib/SecCertificateBundle.h @@ -53,7 +53,7 @@ OSStatus SecCertificateBundleImport( const CSSM_CERT_BUNDLE* bundle, CSSM_CERT_BUNDLE_TYPE type, CSSM_CERT_BUNDLE_ENCODING encodingType, - CFArrayRef keychainListToSkipDuplicates); + CFArrayRef keychainListToSkipDuplicates) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; /*! @function SecCertificateBundleExport @@ -68,7 +68,7 @@ OSStatus SecCertificateBundleExport( CFArrayRef certificates, CSSM_CERT_BUNDLE_TYPE type, CSSM_CERT_BUNDLE_ENCODING encodingType, - CSSM_DATA* data); + CSSM_DATA* data) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; #if defined(__cplusplus) } diff --git a/OSX/libsecurity_keychain/lib/SecCertificateInternalP.h b/OSX/libsecurity_keychain/lib/SecCertificateInternalP.h deleted file mode 100644 index 276de2292..000000000 --- a/OSX/libsecurity_keychain/lib/SecCertificateInternalP.h +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (c) 2007-2011,2013-2015 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* - SecCertificateInternal.h -*/ - -#ifndef _SECURITY_SECCERTIFICATEINTERNAL_H_ -#define _SECURITY_SECCERTIFICATEINTERNAL_H_ - -//#include -#include "SecCertificatePrivP.h" -#include "certextensionsP.h" -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -CFDataRef SecCertificateGetAuthorityKeyIDP(SecCertificateRefP certificate); -CFDataRef SecCertificateGetSubjectKeyIDP(SecCertificateRefP certificate); - -/* Return an array of CFURLRefs each of which is an crl distribution point for - this certificate. */ -CFArrayRef SecCertificateGetCRLDistributionPointsP(SecCertificateRefP certificate); - -/* Return an array of CFURLRefs each of which is an ocspResponder for this - certificate. */ -CFArrayRef SecCertificateGetOCSPRespondersP(SecCertificateRefP certificate); - -/* Return an array of CFURLRefs each of which is an caIssuer for this - certificate. */ -CFArrayRef SecCertificateGetCAIssuersP(SecCertificateRefP certificate); - -/* Dump certificate for debugging. */ -void SecCertificateShowP(SecCertificateRefP certificate); - -/* Return the DER encoded issuer sequence for the receiving certificates issuer. */ -CFDataRef SecCertificateCopyIssuerSequenceP(SecCertificateRefP certificate); - -/* Return the DER encoded subject sequence for the receiving certificates subject. */ -CFDataRef SecCertificateCopySubjectSequenceP(SecCertificateRefP certificate); - -/* Return the content of a DER encoded X.501 name (without the tag and length - fields) for the receiving certificates issuer. */ -CFDataRef SecCertificateGetNormalizedIssuerContentP(SecCertificateRefP certificate); - -/* Return the content of a DER encoded X.501 name (without the tag and length - fields) for the receiving certificates subject. */ -CFDataRef SecCertificateGetNormalizedSubjectContentP(SecCertificateRefP certificate); - -CFDataRef SecDERItemCopySequenceP(DERItem *content); - -/* Return true iff the certificate has a subject. */ -bool SecCertificateHasSubjectP(SecCertificateRefP certificate); - -/* Return true iff the certificate has a critical subject alt name. */ -bool SecCertificateHasCriticalSubjectAltNameP(SecCertificateRefP certificate); - -/* Return true if certificate contains one or more critical extensions we - are unable to parse. */ -bool SecCertificateHasUnknownCriticalExtensionP(SecCertificateRefP certificate); - -/* Return true iff certificate is valid as of verifyTime. */ -bool SecCertificateIsValidP(SecCertificateRefP certificate, - CFAbsoluteTime verifyTime); - -/* Return an attribute dictionary used to store this item in a keychain. */ -CFDictionaryRef SecCertificateCopyAttributeDictionaryP( - SecCertificateRefP certificate); - -/* Return a certificate from the attribute dictionary that was used to store - this item in a keychain. */ -SecCertificateRefP SecCertificateCreateFromAttributeDictionaryP( - CFDictionaryRef refAttributes); - -/* Return a SecKeyRef for the public key embedded in the cert. */ -SecKeyRefP SecCertificateCopyPublicKeyP(SecCertificateRefP certificate); - -/* Return the SecCEBasicConstraints extension for this certificate if it - has one. */ -const SecCEBasicConstraints * -SecCertificateGetBasicConstraintsP(SecCertificateRefP certificate); - -/* Return the SecCEPolicyConstraints extension for this certificate if it - has one. */ -const SecCEPolicyConstraints * -SecCertificateGetPolicyConstraintsP(SecCertificateRefP certificate); - -/* Return a dictionary from CFDataRef to CFArrayRef of CFDataRef - representing the policyMapping extension of this certificate. */ -CFDictionaryRef -SecCertificateGetPolicyMappingsP(SecCertificateRefP certificate); - -/* Return the SecCECertificatePolicies extension for this certificate if it - has one. */ -const SecCECertificatePolicies * -SecCertificateGetCertificatePoliciesP(SecCertificateRefP certificate); - -/* Returns UINT32_MAX if InhibitAnyPolicy extension is not present or invalid, - returns the value of the SkipCerts field of the InhibitAnyPolicy extension - otherwise. */ -uint32_t -SecCertificateGetInhibitAnyPolicySkipCertsP(SecCertificateRefP certificate); - -/* Return the public key algorithm and parameters for certificate. */ -const DERAlgorithmId *SecCertificateGetPublicKeyAlgorithmP( - SecCertificateRefP certificate); - -/* Return the raw public key data for certificate. */ -const DERItem *SecCertificateGetPublicKeyDataP(SecCertificateRefP certificate); - -#pragma mark - -#pragma mark Certificate Operations - -OSStatus SecCertificateIsSignedByP(SecCertificateRefP certificate, - SecKeyRefP issuerKey); - -#pragma mark - -#pragma mark Certificate Creation - -#ifdef OPTIONAL_METHODS -/* Return a certificate for the PEM representation of this certificate. - Return NULL the passed in der_certificate is not a valid DER encoded X.509 - certificate, and return a CFError by reference. It is the - responsibility of the caller to release the CFError. */ -SecCertificateRefP SecCertificateCreateWithPEMP(CFAllocatorRef allocator, - CFStringRef pem_certificate); - -/* Return a CFStringRef containing the the pem representation of this - certificate. */ -CFStringRef SecCertificateGetPEMP(SecCertificateRefP der_certificate); - -#endif /* OPTIONAL_METHODS */ - -#if 0 -/* Complete the certificate chain of this certificate, setting the parent - certificate for each certificate along they way. Return 0 if the - system is able to find all the certificates to complete the certificate - chain either in the passed in other_certificates array or in the user or - the systems keychain(s). - If the certificate's issuer chain can not be completed, this function - will return an error status code. - NOTE: This function does not verify whether the certificate is trusted it's - main use is just to ensure that anyone using this certificate upstream will - have access to a complete (or as complete as possible in the case of - something going wrong) certificate chain. */ -OSStatus SecCertificateCompleteChainP(SecCertificateRefP certificate, - CFArrayRef other_certificates); -#endif - -#if 0 - -/*! - @function SecCertificateGetVersionNumberP - @abstract Retrieves the version of a given certificate as a CFNumberRef. - @param certificate A reference to the certificate from which to obtain the certificate version. - @result A CFNumberRef representing the certificate version. The following values are currently known to be returned, but more may be added in the future: - 1: X509v1 - 2: X509v2 - 3: X509v3 -*/ -CFNumberRef SecCertificateGetVersionNumberP(SecCertificateRefP certificate); - -/*! - @function SecCertificateGetSerialDERP - @abstract Retrieves the serial number of a given certificate in DER encoding. - @param certificate A reference to the certificate from which to obtain the serial number. - @result A CFDataRef containing the DER encoded serial number of the certificate, minus the tag and length fields. -*/ -CFDataRef SecCertificateGetSerialDERP(SecCertificateRefP certificate); - - -/*! - @function SecCertificateGetSerialStringP - @abstract Retrieves the serial number of a given certificate in human readable form. - @param certificate A reference to the certificate from which to obtain the serial number. - @result A CFStringRef containing the human readable serial number of the certificate in decimal form. -*/ -CFStringRef SecCertificateGetSerialStringP(SecCertificateRefP certificate); - - - -CFDataRef SecCertificateGetPublicKeyDERP(SecCertificateRefP certificate); -CFDataRef SecCertificateGetPublicKeySHA1FingerPrintP(SecCertificateRefP certificate); -CFDataRef SecCertificateGetPublicKeyMD5FingerPrintP(SecCertificateRefP certificate); -CFDataRef SecCertificateGetSignatureAlgorithmDERP(SecCertificateRefP certificate); -CFDataRef SecCertificateGetSignatureAlgorithmNameP(SecCertificateRefP certificate); -CFStringRef SecCertificateGetSignatureAlgorithmOIDP(SecCertificateRefP certificate); -CFDataRef SecCertificateGetSignatureDERP(SecCertificateRefP certificate); -CFDataRef SecCertificateGetSignatureAlgorithmParametersDERP(SecCertificateRefP certificate); - -/* plist top level array is orderd list of key/value pairs */ -CFArrayRef SecCertificateGetSignatureAlgorithmParametersArrayP(SecCertificateRefP certificate); - -#if 0 -/* This cert is signed by its parent? */ -bool SecCertificateIsSignatureValidP(SecCertificateRefP certificate); - -/* This cert is signed by its parent and so on until no parent certificate can be found? */ -bool SecCertificateIsIssuerChainValidP(SecCertificateRefP certificate, CFArrayRef additionalCertificatesToSearch); - -/* This cert is signed by its parent and so on until no parent certificate can be found? */ -bool SecCertificateIsSignatureChainValidP(SecCertificateRefP certificate); - -/* This cert is signed by its parent and so on until a certiicate in anchors can be found. */ -bool SecCertificateIssuerChainHasAnchorInP(SecCertificateRefP certificate, CFArrayRef anchors); - -/* This cert is signed by its parent and so on until a certiicate in anchors can be found. */ -bool SecCertificateSignatureChainHasAnchorInP(SecCertificateRefP certificate, CFArrayRef anchors); - -bool SecCertificateIsSelfSignedP(SecCertificateRefP certificate); -#endif - - -/* The entire certificate in DER encoding including the outer tag and length fields. */ -CFDataRef SecCertificateGetDERP(SecCertificateRefP certificate); - -/* Returns the status code of the last failed call for this certificate on this thread. */ -OSStatus SecCertificateGetStatusP(SecCertificateRefP certificate); - -CFDataRef SecCertificateGetIssuerDERP(SecCertificateRefP certificate); -CFDataRef SecCertificateGetNormalizedIssuerDERP(SecCertificateRefP certificate); - -/* Return the issuer as an X509 name encoded in an array. Each element in this array is an array. Each inner array has en even number of elements. Each pair of elements in the inner array represents a key and a value. The key is a string and the value is also a string. Elements in the outer array should be considered ordered while pairs in the inner array should not. */ -CFArrayRef SecCertificateGetIssuerArrayP(SecCertificateRefP certificate); - - -CFDataRef SecCertificateGetSubjectDERP(SecCertificateRefP certificate); -CFDataRef SecCertificateGetNormalizedSubjectDERP(SecCertificateRefP certificate); -/* See SecCertificateGetIssuerArray for a description of the returned array. */ -CFArrayRef SecCertificateGetSubjectArrayP(SecCertificateRefP certificate); - -CFDateRef SecCertificateGetNotValidBeforeDateP(SecCertificateRefP certificate); -CFDateRef SecCertificateGetNotValidDateP(SecCertificateRefP certificate); - - -#if 0 - -CFIndex SecCertificateGetExtensionCountP(SecCertificateRefP certificate, index); -CFDataRef SecCertificateGetExtensionAtIndexDERP(SecCertificateRefP certificate, CFIndex index); -bool SecCertificateIsExtensionAtIndexCriticalP(SecCertificateRefP certificate, CFIndex index); - -/* array see email example. */ -CFArrayRef SecCertificateGetExtensionAtIndexParamsArrayP(SecCertificateRefP certificate, CFIndex index); - -CFStringRef SecCertificateGetExtensionAtIndexNameP(SecCertificateRefP certificate, CFIndex index); -CFStringRef SecCertificateGetExtensionAtIndexOIDP(SecCertificateRefP certificate, CFIndex index); - -#else - -/* Return an array with all of this certificates SecCertificateExtensionRefs. */ -CFArrayRef SecCertificateGetExtensionsP(SecCertificateRefP certificate); - -/* Return the SecCertificateExtensionRef for the extension with the given oid. Return NULL if it does not exist or if an error occours call SecCertificateGetStatus() to see if an error occured or not. */ -SecCertificateExtensionRef SecCertificateGetExtensionWithOIDP(SecCertificateRefP certificate, CFDataRef oid); - -CFDataRef SecCertificateExtensionGetDERP(SecCertificateExtensionRef extension, CFDataRef oid); -CFStringRef SecCertificateExtensionNameP(SecCertificateExtensionRef extension); -CFDataRef SecCertificateExtensionGetOIDDERP(SecCertificateExtensionRef extension, CFDataRef oid); -CFStringRef SecCertificateExtensionGetOIDStringP(SecCertificateExtensionRef extension, CFDataRef oid); -bool SecCertificateExtensionIsCriticalP(SecCertificateExtensionRef extension); -CFArrayRef SecCertificateExtensionGetContentDERP(SecCertificateExtensionRef extension); - -/* Return the content of extension as an array. The array has en even number of elements. Each pair of elements in the array represents a key and a value. The key is a string and the value is either a string, or dictionary or an array of key value pairs like the outer array. */ -CFArrayRef SecCertificateExtensionGetContentArrayP(SecCertificateExtensionRef extension); - -#endif /* 0 */ - -#endif /* 0 */ - - -void appendPropertyP(CFMutableArrayRef properties, - CFStringRef propertyType, CFStringRef label, CFTypeRef value); - -#if 0 -/* Utility functions. */ -CFStringRef SecDERItemCopyOIDDecimalRepresentation(CFAllocatorRef allocator, - const DERItem *oid); -CFDataRef createNormalizedX501Name(CFAllocatorRef allocator, - const DERItem *x501name); - -/* Decode a choice of UTCTime or GeneralizedTime to a CFAbsoluteTime. Return - an absoluteTime if the date was valid and properly decoded. Return - NULL_TIME otherwise. */ -CFAbsoluteTime SecAbsoluteTimeFromDateContent(DERTag tag, const uint8_t *bytes, - size_t length); -#endif - -#if defined(__cplusplus) -} -#endif - -#endif /* !_SECURITY_SECCERTIFICATEINTERNAL_H_ */ diff --git a/OSX/libsecurity_keychain/lib/SecCertificateP.c b/OSX/libsecurity_keychain/lib/SecCertificateP.c deleted file mode 100644 index 77210b575..000000000 --- a/OSX/libsecurity_keychain/lib/SecCertificateP.c +++ /dev/null @@ -1,4762 +0,0 @@ -/* - * Copyright (c) 2006-2015 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* - * SecCertificate.c - CoreFoundation based certificate object - */ - - -#include "SecCertificateInternalP.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "SecBasePriv.h" - -#include "SecRSAKeyP.h" -#include "SecFrameworkP.h" -#include "SecItem.h" -#include "SecItemPriv.h" -#include -#include -#include -#include -#include "SecInternal.h" -#include "SecBase64P.h" - -#include - -typedef struct SecCertificateExtension { - DERItem extnID; - bool critical; - DERItem extnValue; -} SecCertificateExtension; - -#if 0 -typedef struct KnownExtension { - bool critical; - DERItem extnValue; -} KnownExtension; - -enum { - kSecSelfSignedUnknown = 0, - kSecSelfSignedFalse, - kSecSelfSignedTrue, -}; -#endif - -struct __SecCertificate { - CFRuntimeBase _base; - - DERItem _der; /* Entire certificate in DER form. */ - DERItem _tbs; /* To Be Signed cert DER bytes. */ - DERAlgorithmId _sigAlg; /* Top level signature algorithm. */ - DERItem _signature; /* The content of the sig bit string. */ - - UInt8 _version; - DERItem _serialNum; /* Integer. */ - DERAlgorithmId _tbsSigAlg; /* sig alg MUST be same as _sigAlg. */ - DERItem _issuer; /* Sequence of RDN. */ - CFAbsoluteTime _notBefore; - CFAbsoluteTime _notAfter; - DERItem _subject; /* Sequence of RDN. */ - DERAlgorithmId _algId; /* oid and params of _pubKeyDER. */ - DERItem _pubKeyDER; /* contents of bit string */ - DERItem _issuerUniqueID; /* bit string, optional */ - DERItem _subjectUniqueID; /* bit string, optional */ - -#if 0 - /* Known extensions if the certificate contains them, - extnValue.length will be > 0. */ - KnownExtension _authorityKeyID; - - /* This extension is used to uniquely identify a certificate from among - several that have the same subject name. If the extension is not - present, its value is calculated by performing a SHA-1 hash of the - certificate's DER encoded subjectPublicKeyInfo, as recommended by - PKIX. */ - KnownExtension _subjectKeyID; - KnownExtension _keyUsage; - KnownExtension _extendedKeyUsage; - KnownExtension _basicConstraints; - KnownExtension _netscapeCertType; - KnownExtension _subjectAltName; - KnownExtension _qualCertStatements; - -#endif - bool _foundUnknownCriticalExtension; - - /* Well known certificate extensions. */ - SecCEBasicConstraints _basicConstraints; - SecCEPolicyConstraints _policyConstraints; - CFDictionaryRef _policyMappings; - SecCECertificatePolicies _certificatePolicies; - - /* If InhibitAnyPolicy extension is not present or invalid UINT32_MAX, - value of the SkipCerts field of the InhibitAnyPolicy extension - otherwise. */ - uint32_t _inhibitAnyPolicySkipCerts; - - /* If KeyUsage extension is not present this is 0, otherwise it's - the value of the extension. */ - SecKeyUsage _keyUsage; - - /* OCTECTS of SubjectKeyIdentifier extensions KeyIdentifier. - Length = 0 if not present. */ - DERItem _subjectKeyIdentifier; - - /* OCTECTS of AuthorityKeyIdentifier extensions KeyIdentifier. - Length = 0 if not present. */ - DERItem _authorityKeyIdentifier; - /* AuthorityKeyIdentifier extension _authorityKeyIdentifierIssuer and - _authorityKeyIdentifierSerialNumber have non zero length if present. - Both are either present or absent together. */ - DERItem _authorityKeyIdentifierIssuer; - DERItem _authorityKeyIdentifierSerialNumber; - - /* Subject alt name extension, if present. Not malloced, it's just a - pointer to an element in the _extensions array. */ - const SecCertificateExtension *_subjectAltName; - - /* Parsed extension values. */ - - /* Array of CFURLRefs containing the URI values of crlDistributionPoints. */ - CFMutableArrayRef _crlDistributionPoints; - - /* Array of CFURLRefs containing the URI values of accessLocations of each - id-ad-ocsp AccessDescription in the Authority Information Access - extension. */ - CFMutableArrayRef _ocspResponders; - - /* Array of CFURLRefs containing the URI values of accessLocations of each - id-ad-caIssuers AccessDescription in the Authority Information Access - extension. */ - CFMutableArrayRef _caIssuers; - - /* All other (non known) extensions. The _extensions array is malloced. */ - CFIndex _extensionCount; - SecCertificateExtension *_extensions; - - /* Optional cached fields. */ - SecKeyRef _pubKey; - CFDataRef _der_data; - CFArrayRef _properties; - CFDataRef _serialNumber; - CFDataRef _normalizedIssuer; - CFDataRef _normalizedSubject; - CFDataRef _authorityKeyID; - CFDataRef _subjectKeyID; - - CFDataRef _sha1Digest; - uint8_t _isSelfSigned; - -}; - -/* Public Constants for property list keys. */ -const CFStringRef kSecPropertyKeyType = CFSTR("type"); -const CFStringRef kSecPropertyKeyLabel = CFSTR("label"); -const CFStringRef kSecPropertyKeyLocalizedLabel = CFSTR("localized label"); -const CFStringRef kSecPropertyKeyValue = CFSTR("value"); - -/* Public Constants for property list values. */ -const CFStringRef kSecPropertyTypeWarning = CFSTR("warning"); -const CFStringRef kSecPropertyTypeError = CFSTR("error"); -const CFStringRef kSecPropertyTypeSuccess = CFSTR("success"); -const CFStringRef kSecPropertyTypeTitle = CFSTR("title"); -const CFStringRef kSecPropertyTypeSection = CFSTR("section"); -const CFStringRef kSecPropertyTypeData = CFSTR("data"); -const CFStringRef kSecPropertyTypeString = CFSTR("string"); -const CFStringRef kSecPropertyTypeURL = CFSTR("url"); -const CFStringRef kSecPropertyTypeDate = CFSTR("date"); - -/* Extension parsing routine. */ -typedef void (*SecCertificateExtensionParser)(SecCertificateRefP certificate, - const SecCertificateExtension *extn); - -/* CFRuntime regsitration data. */ -static pthread_once_t kSecCertificateRegisterClass = PTHREAD_ONCE_INIT; -static CFTypeID kSecCertificateTypeID = _kCFRuntimeNotATypeID; - -/* Mapping from extension OIDs (as a DERItem *) to - SecCertificateExtensionParser extension parsing routines. */ -static CFDictionaryRef gExtensionParsers; - -/* Forward declartions of static functions. */ -static CFStringRef SecCertificateCopyDescription(CFTypeRef cf); -static void SecCertificateDestroy(CFTypeRef cf); -static bool derDateGetAbsoluteTime(const DERItem *dateChoice, - CFAbsoluteTime *absTime); - -/* Static functions. */ -static CFStringRef SecCertificateCopyDescription(CFTypeRef cf) { - SecCertificateRefP certificate = (SecCertificateRefP)cf; - CFStringRef ret = NULL; - CFStringRef subjectSummary = SecCertificateCopySubjectSummaryP(certificate); - CFStringRef issuerSummary = SecCertificateCopyIssuerSummaryP(certificate); - - ret = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, - CFSTR(""), certificate, - subjectSummary, - issuerSummary); - - CFReleaseNull(subjectSummary); - CFReleaseNull(issuerSummary); - return ret; -} - -static void SecCertificateDestroy(CFTypeRef cf) { - SecCertificateRefP certificate = (SecCertificateRefP)cf; - if (certificate->_certificatePolicies.policies) { - free(certificate->_certificatePolicies.policies); - certificate->_certificatePolicies.policies = NULL; - } - CFReleaseNull(certificate->_policyMappings); - CFReleaseNull(certificate->_crlDistributionPoints); - CFReleaseNull(certificate->_ocspResponders); - CFReleaseNull(certificate->_caIssuers); - if (certificate->_extensions) { - free(certificate->_extensions); - certificate->_extensions = NULL; - } - CFReleaseNull(certificate->_pubKey); - CFReleaseNull(certificate->_der_data); - CFReleaseNull(certificate->_properties); - CFReleaseNull(certificate->_serialNumber); - CFReleaseNull(certificate->_normalizedIssuer); - CFReleaseNull(certificate->_normalizedSubject); - CFReleaseNull(certificate->_authorityKeyID); - CFReleaseNull(certificate->_subjectKeyID); - CFReleaseNull(certificate->_sha1Digest); -} - -static Boolean SecCertificateEqual(CFTypeRef cf1, CFTypeRef cf2) { - SecCertificateRefP cert1 = (SecCertificateRefP)cf1; - SecCertificateRefP cert2 = (SecCertificateRefP)cf2; - if (cert1 == cert2) - return true; - if (!cert2 || cert1->_der.length != cert2->_der.length) - return false; - return !memcmp(cert1->_der.data, cert2->_der.data, cert1->_der.length); -} - -/* Hash of the certificate is der length + signature length + last 4 bytes - of signature. */ -static CFHashCode SecCertificateHash(CFTypeRef cf) { - SecCertificateRefP certificate = (SecCertificateRefP)cf; - DERSize der_length = certificate->_der.length; - DERSize sig_length = certificate->_signature.length; - DERSize ix = (sig_length > 4) ? sig_length - 4 : 0; - CFHashCode hashCode = 0; - for (; ix < sig_length; ++ix) - hashCode = (hashCode << 8) + certificate->_signature.data[ix]; - - return (hashCode + der_length + sig_length); -} - -#if 1 - -/************************************************************************/ -/************************* General Name Parsing *************************/ -/************************************************************************/ - -typedef OSStatus (*parseGeneralNameCallback)(void *context, - SecCEGeneralNameType type, const DERItem *value); - - -/* - 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} - - OtherName ::= SEQUENCE { - type-id OBJECT IDENTIFIER, - value [0] EXPLICIT ANY DEFINED BY type-id } - - EDIPartyName ::= SEQUENCE { - nameAssigner [0] DirectoryString OPTIONAL, - partyName [1] DirectoryString } - */ -static OSStatus parseGeneralNameContentProperty(DERTag tag, - const DERItem *generalNameContent, - void *context, parseGeneralNameCallback callback) { - switch (tag) { - case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0: - return callback(context, GNT_OtherName, generalNameContent); - case ASN1_CONTEXT_SPECIFIC | 1: - return callback(context, GNT_RFC822Name, generalNameContent); - case ASN1_CONTEXT_SPECIFIC | 2: - return callback(context, GNT_DNSName, generalNameContent); - case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3: - return callback(context, GNT_X400Address, generalNameContent); - case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 4: - return callback(context, GNT_DirectoryName, generalNameContent); - case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 5: - return callback(context, GNT_EdiPartyName, generalNameContent); - 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 uriContent; - require_noerr(DERDecodeItem(generalNameContent, &uriContent), badDER); - require(uriContent.tag == ASN1_IA5_STRING, badDER); - return callback(context, GNT_URI, &uriContent.content); - } - case ASN1_CONTEXT_SPECIFIC | 6: - return callback(context, GNT_URI, generalNameContent); - case ASN1_CONTEXT_SPECIFIC | 7: - return callback(context, GNT_IPAddress, generalNameContent); - case ASN1_CONTEXT_SPECIFIC | 8: - return callback(context, GNT_RegisteredID, generalNameContent); - default: - goto badDER; - } -badDER: - return errSecInvalidCertificate; -} - -static OSStatus parseGeneralNamesContent(const DERItem *generalNamesContent, - void *context, parseGeneralNameCallback callback) { - DERSequence gnSeq; - DERReturn drtn = DERDecodeSeqContentInit(generalNamesContent, &gnSeq); - require_noerr_quiet(drtn, badDER); - DERDecodedInfo generalNameContent; - while ((drtn = DERDecodeSeqNext(&gnSeq, &generalNameContent)) == - DR_Success) { - OSStatus status = parseGeneralNameContentProperty( - generalNameContent.tag, &generalNameContent.content, context, - callback); - if (status) - return status; - } - require_quiet(drtn == DR_EndOfSequence, badDER); - return errSecSuccess; - -badDER: - return errSecInvalidCertificate; -} - -static OSStatus parseGeneralNames(const DERItem *generalNames, void *context, - parseGeneralNameCallback callback) { - DERDecodedInfo generalNamesContent; - DERReturn drtn = DERDecodeItem(generalNames, &generalNamesContent); - require_noerr_quiet(drtn, badDER); - require_quiet(generalNamesContent.tag == ASN1_CONSTR_SEQUENCE, badDER); - 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 **************************/ -/************************************************************************/ - -typedef OSStatus (*parseX501NameCallback)(void *context, const DERItem *type, - const DERItem *value, CFIndex rdnIX); - -static OSStatus parseRDNContent(const DERItem *rdnSetContent, void *context, - parseX501NameCallback callback) { - DERSequence rdn; - DERReturn drtn = DERDecodeSeqContentInit(rdnSetContent, &rdn); - require_noerr_quiet(drtn, badDER); - DERDecodedInfo atvContent; - CFIndex rdnIX = 0; - while ((drtn = DERDecodeSeqNext(&rdn, &atvContent)) == DR_Success) { - require_quiet(atvContent.tag == ASN1_CONSTR_SEQUENCE, badDER); - DERAttributeTypeAndValue atv; - drtn = DERParseSequenceContent(&atvContent.content, - DERNumAttributeTypeAndValueItemSpecs, - DERAttributeTypeAndValueItemSpecs, - &atv, sizeof(atv)); - require_noerr_quiet(drtn, badDER); - require_quiet(atv.type.length != 0, badDER); - OSStatus status = callback(context, &atv.type, &atv.value, rdnIX++); - if (status) - return status; - } - require_quiet(drtn == DR_EndOfSequence, badDER); - - return errSecSuccess; -badDER: - return errSecInvalidCertificate; -} - -static OSStatus parseX501NameContent(const DERItem *x501NameContent, void *context, - parseX501NameCallback callback) { - 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); - if (status) - return status; - } - require_quiet(drtn == DR_EndOfSequence, badDER); - - return errSecSuccess; - -badDER: - return errSecInvalidCertificate; -} - -static OSStatus parseX501Name(const DERItem *x501Name, void *context, - parseX501NameCallback callback) { - DERDecodedInfo x501NameContent; - if (DERDecodeItem(x501Name, &x501NameContent) || - x501NameContent.tag != ASN1_CONSTR_SEQUENCE) { - return errSecInvalidCertificate; - } else { - return parseX501NameContent(&x501NameContent.content, context, - callback); - } -} - -/************************************************************************/ -/********************** Extension Parsing Routines **********************/ -/************************************************************************/ - -static void SecCEPSubjectKeyIdentifier(SecCertificateRefP certificate, - const SecCertificateExtension *extn) { - secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); - DERDecodedInfo keyIdentifier; - DERReturn drtn = DERDecodeItem(&extn->extnValue, &keyIdentifier); - require_noerr_quiet(drtn, badDER); - require_quiet(keyIdentifier.tag == ASN1_OCTET_STRING, badDER); - certificate->_subjectKeyIdentifier = keyIdentifier.content; - - return; -badDER: - secinfo("cert", "Invalid SubjectKeyIdentifier Extension"); -} - -static void SecCEPKeyUsage(SecCertificateRefP certificate, - const SecCertificateExtension *extn) { - secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); - SecKeyUsage keyUsage = extn->critical ? kSecKeyUsageCritical : 0; - DERDecodedInfo bitStringContent; - DERReturn drtn = DERDecodeItem(&extn->extnValue, &bitStringContent); - require_noerr_quiet(drtn, badDER); - require_quiet(bitStringContent.tag == ASN1_BIT_STRING, badDER); - DERSize len = bitStringContent.content.length - 1; - require_quiet(len == 1 || len == 2, badDER); - DERByte numUnusedBits = bitStringContent.content.data[0]; - require_quiet(numUnusedBits < 8, badDER); - /* Flip the bits in the bit string so the first bit in the lsb. */ - uint_fast16_t bits = 8 * len - numUnusedBits; - uint_fast16_t value = bitStringContent.content.data[1]; - uint_fast16_t mask; - if (len > 1) { - value = (value << 8) + bitStringContent.content.data[2]; - mask = 0x8000; - } else { - mask = 0x80; - } - uint_fast16_t ix; - for (ix = 0; ix < bits; ++ix) { - if (value & mask) { - keyUsage |= 1 << ix; - } - mask >>= 1; - } - certificate->_keyUsage = keyUsage; - return; -badDER: - certificate->_keyUsage = kSecKeyUsageUnspecified; -} - -static void SecCEPPrivateKeyUsagePeriod(SecCertificateRefP certificate, - const SecCertificateExtension *extn) { - secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); -} - -static void SecCEPSubjectAltName(SecCertificateRefP certificate, - const SecCertificateExtension *extn) { - secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); - certificate->_subjectAltName = extn; -} - -static void SecCEPIssuerAltName(SecCertificateRefP certificate, - const SecCertificateExtension *extn) { - secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); -} - -static void SecCEPBasicConstraints(SecCertificateRefP certificate, - const SecCertificateExtension *extn) { - secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); - DERBasicConstraints basicConstraints; - require_noerr_quiet(DERParseSequence(&extn->extnValue, - DERNumBasicConstraintsItemSpecs, DERBasicConstraintsItemSpecs, - &basicConstraints, sizeof(basicConstraints)), badDER); - require_noerr_quiet(DERParseBooleanWithDefault(&basicConstraints.cA, false, - &certificate->_basicConstraints.isCA), badDER); - if (basicConstraints.pathLenConstraint.length != 0) { - require_noerr_quiet(DERParseInteger( - &basicConstraints.pathLenConstraint, - &certificate->_basicConstraints.pathLenConstraint), badDER); - certificate->_basicConstraints.pathLenConstraintPresent = true; - } - certificate->_basicConstraints.present = true; - certificate->_basicConstraints.critical = extn->critical; - return; -badDER: - certificate->_basicConstraints.present = false; - secinfo("cert", "Invalid BasicConstraints Extension"); -} - -static void SecCEPCrlDistributionPoints(SecCertificateRefP certificate, - const SecCertificateExtension *extn) { - secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); -} - -/* - certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation - - PolicyInformation ::= SEQUENCE { - policyIdentifier CertPolicyId, - policyQualifiers SEQUENCE SIZE (1..MAX) OF - PolicyQualifierInfo OPTIONAL } - - CertPolicyId ::= OBJECT IDENTIFIER - - PolicyQualifierInfo ::= SEQUENCE { - policyQualifierId PolicyQualifierId, - qualifier ANY DEFINED BY policyQualifierId } -*/ -/* maximum number of policies of 8192 seems more than adequate */ -#define MAX_CERTIFICATE_POLICIES 8192 -static void SecCEPCertificatePolicies(SecCertificateRefP certificate, - const SecCertificateExtension *extn) { - secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); - DERTag tag; - DERSequence piSeq; - SecCEPolicyInformation *policies = NULL; - DERReturn drtn = DERDecodeSeqInit(&extn->extnValue, &tag, &piSeq); - require_noerr_quiet(drtn, badDER); - require_quiet(tag == ASN1_CONSTR_SEQUENCE, badDER); - DERDecodedInfo piContent; - DERSize policy_count = 0; - while ((policy_count < MAX_CERTIFICATE_POLICIES) && - (drtn = DERDecodeSeqNext(&piSeq, &piContent)) == DR_Success) { - require_quiet(piContent.tag == ASN1_CONSTR_SEQUENCE, badDER); - policy_count++; - } - require_quiet(drtn == DR_EndOfSequence, badDER); - DERSize malloc_policies = policy_count > 0 ? policy_count : 1; - require_quiet(policies = (SecCEPolicyInformation *)malloc(sizeof(SecCEPolicyInformation) - * malloc_policies), 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) { - DERPolicyInformation pi; - drtn = DERParseSequenceContent(&piContent.content, - DERNumPolicyInformationItemSpecs, - DERPolicyInformationItemSpecs, - &pi, sizeof(pi)); - require_noerr_quiet(drtn, badDER); - policies[policy_ix].policyIdentifier = pi.policyIdentifier; - policies[policy_ix++].policyQualifiers = pi.policyQualifiers; - } - certificate->_certificatePolicies.present = true; - certificate->_certificatePolicies.critical = extn->critical; - certificate->_certificatePolicies.numPolicies = (uint32_t)policy_count; - certificate->_certificatePolicies.policies = policies; - return; -badDER: - if (policies) - free(policies); - certificate->_certificatePolicies.present = false; - secinfo("cert", "Invalid CertificatePolicies Extension"); -} - -/* - id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } - - PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE { - issuerDomainPolicy CertPolicyId, - subjectDomainPolicy CertPolicyId } -*/ -#if 0 -static void SecCEPPolicyMappings(SecCertificateRefP certificate, - const SecCertificateExtension *extn) { - secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); - DERTag tag; - DERSequence pmSeq; - SecCEPolicyMapping *mappings = NULL; - DERReturn drtn = DERDecodeSeqInit(&extn->extnValue, &tag, &pmSeq); - require_noerr_quiet(drtn, badDER); - require_quiet(tag == ASN1_CONSTR_SEQUENCE, badDER); - DERDecodedInfo pmContent; - DERSize mapping_count = 0; - while ((drtn = DERDecodeSeqNext(&pmSeq, &pmContent)) == DR_Success) { - require_quiet(pmContent.tag == ASN1_CONSTR_SEQUENCE, badDER); - mapping_count++; - } - mappings = (SecCEPolicyMapping *)malloc(sizeof(SecCEPolicyMapping) - * mapping_count); - drtn = DERDecodeSeqInit(&extn->extnValue, &tag, &pmSeq); - require_noerr_quiet(drtn, badDER); - DERSize mapping_ix = 0; - while ((drtn = DERDecodeSeqNext(&pmSeq, &pmContent)) == DR_Success) { - DERPolicyMapping pm; - drtn = DERParseSequenceContent(&pmContent.content, - DERNumPolicyMappingItemSpecs, - DERPolicyMappingItemSpecs, - &pm, sizeof(pm)); - require_noerr_quiet(drtn, badDER); - mappings[mapping_ix].issuerDomainPolicy = pm.issuerDomainPolicy; - mappings[mapping_ix++].subjectDomainPolicy = pm.subjectDomainPolicy; - } - require_quiet(drtn == DR_EndOfSequence, badDER); - certificate->_policyMappings.present = true; - certificate->_policyMappings.critical = extn->critical; - certificate->_policyMappings.numMappings = mapping_count; - certificate->_policyMappings.mappings = mappings; - return; -badDER: - if (mappings) - free(mappings); - CFReleaseSafe(mappings); - certificate->_policyMappings.present = false; - secinfo("cert", "Invalid CertificatePolicies Extension"); -} -#else -static void SecCEPPolicyMappings(SecCertificateRefP certificate, - const SecCertificateExtension *extn) { - secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); - DERTag tag; - DERSequence pmSeq; - CFMutableDictionaryRef mappings = NULL; - CFDataRef idp = NULL, sdp = NULL; - DERReturn drtn = DERDecodeSeqInit(&extn->extnValue, &tag, &pmSeq); - require_noerr_quiet(drtn, badDER); - require_quiet(tag == ASN1_CONSTR_SEQUENCE, badDER); - DERDecodedInfo pmContent; - require_quiet(mappings = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), - badDER);; - while ((drtn = DERDecodeSeqNext(&pmSeq, &pmContent)) == DR_Success) { - require_quiet(pmContent.tag == ASN1_CONSTR_SEQUENCE, badDER); - DERPolicyMapping pm; - drtn = DERParseSequenceContent(&pmContent.content, - DERNumPolicyMappingItemSpecs, - DERPolicyMappingItemSpecs, - &pm, sizeof(pm)); - require_noerr_quiet(drtn, badDER); - - require_quiet(idp = CFDataCreate(kCFAllocatorDefault, - pm.issuerDomainPolicy.data, pm.issuerDomainPolicy.length), badDER); - require_quiet(sdp = CFDataCreate(kCFAllocatorDefault, - pm.subjectDomainPolicy.data, pm.subjectDomainPolicy.length), badDER); - CFMutableArrayRef sdps = - (CFMutableArrayRef)CFDictionaryGetValue(mappings, idp); - if (sdps) { - CFArrayAppendValue(sdps, sdp); - } else { - require_quiet(sdps = CFArrayCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeArrayCallBacks), badDER); - CFDictionarySetValue(mappings, idp, sdps); - CFRelease(sdps); - } - CFReleaseNull(idp); - CFReleaseNull(sdp); - } - require_quiet(drtn == DR_EndOfSequence, badDER); - certificate->_policyMappings = mappings; - return; -badDER: - CFReleaseNull(idp); - CFReleaseNull(sdp); - CFReleaseSafe(mappings); - certificate->_policyMappings = NULL; - secinfo("cert", "Invalid CertificatePolicies Extension"); -} -#endif - -/* -AuthorityKeyIdentifier ::= SEQUENCE { - keyIdentifier [0] KeyIdentifier OPTIONAL, - authorityCertIssuer [1] GeneralNames OPTIONAL, - authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } - -- authorityCertIssuer and authorityCertSerialNumber MUST both - -- be present or both be absent - -KeyIdentifier ::= OCTET STRING -*/ -static void SecCEPAuthorityKeyIdentifier(SecCertificateRefP certificate, - const SecCertificateExtension *extn) { - secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); - DERAuthorityKeyIdentifier akid; - DERReturn drtn; - drtn = DERParseSequence(&extn->extnValue, - DERNumAuthorityKeyIdentifierItemSpecs, - DERAuthorityKeyIdentifierItemSpecs, - &akid, sizeof(akid)); - require_noerr_quiet(drtn, badDER); - if (akid.keyIdentifier.length) { - certificate->_authorityKeyIdentifier = akid.keyIdentifier; - } - if (akid.authorityCertIssuer.length || - akid.authorityCertSerialNumber.length) { - require_quiet(akid.authorityCertIssuer.length && - akid.authorityCertSerialNumber.length, badDER); - /* Perhaps put in a subsection called Authority Certificate Issuer. */ - certificate->_authorityKeyIdentifierIssuer = akid.authorityCertIssuer; - certificate->_authorityKeyIdentifierSerialNumber = akid.authorityCertSerialNumber; - } - - return; -badDER: - secinfo("cert", "Invalid AuthorityKeyIdentifier Extension"); -} - -static void SecCEPPolicyConstraints(SecCertificateRefP certificate, - const SecCertificateExtension *extn) { - secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); - DERPolicyConstraints pc; - DERReturn drtn; - drtn = DERParseSequence(&extn->extnValue, - DERNumPolicyConstraintsItemSpecs, - DERPolicyConstraintsItemSpecs, - &pc, sizeof(pc)); - require_noerr_quiet(drtn, badDER); - if (pc.requireExplicitPolicy.length) { - require_noerr_quiet(DERParseInteger( - &pc.requireExplicitPolicy, - &certificate->_policyConstraints.requireExplicitPolicy), badDER); - certificate->_policyConstraints.requireExplicitPolicyPresent = true; - } - if (pc.inhibitPolicyMapping.length) { - require_noerr_quiet(DERParseInteger( - &pc.inhibitPolicyMapping, - &certificate->_policyConstraints.inhibitPolicyMapping), badDER); - certificate->_policyConstraints.inhibitPolicyMappingPresent = true; - } - - certificate->_policyConstraints.present = true; - certificate->_policyConstraints.critical = extn->critical; - - return; -badDER: - certificate->_policyConstraints.present = false; - secinfo("cert", "Invalid PolicyConstraints Extension"); -} - -static void SecCEPExtendedKeyUsage(SecCertificateRefP certificate, - const SecCertificateExtension *extn) { - secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); -} - -/* - InhibitAnyPolicy ::= SkipCerts - - SkipCerts ::= INTEGER (0..MAX) -*/ -static void SecCEPInhibitAnyPolicy(SecCertificateRefP certificate, - const SecCertificateExtension *extn) { - secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); - require_noerr_quiet(DERParseInteger( - &extn->extnValue, - &certificate->_inhibitAnyPolicySkipCerts), badDER); - return; -badDER: - certificate->_inhibitAnyPolicySkipCerts = UINT32_MAX; - secinfo("cert", "Invalid InhibitAnyPolicy Extension"); -} - -/* - id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 } - - AuthorityInfoAccessSyntax ::= - SEQUENCE SIZE (1..MAX) OF AccessDescription - - AccessDescription ::= SEQUENCE { - accessMethod OBJECT IDENTIFIER, - accessLocation GeneralName } - - id-ad OBJECT IDENTIFIER ::= { id-pkix 48 } - - id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 } - - id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 } - */ -static void SecCEPAuthorityInfoAccess(SecCertificateRefP certificate, - const SecCertificateExtension *extn) { - secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); - DERTag tag; - DERSequence adSeq; - DERReturn drtn = DERDecodeSeqInit(&extn->extnValue, &tag, &adSeq); - require_noerr_quiet(drtn, badDER); - require_quiet(tag == ASN1_CONSTR_SEQUENCE, badDER); - DERDecodedInfo adContent; - while ((drtn = DERDecodeSeqNext(&adSeq, &adContent)) == DR_Success) { - require_quiet(adContent.tag == ASN1_CONSTR_SEQUENCE, badDER); - DERAccessDescription ad; - drtn = DERParseSequenceContent(&adContent.content, - DERNumAccessDescriptionItemSpecs, - DERAccessDescriptionItemSpecs, - &ad, sizeof(ad)); - require_noerr_quiet(drtn, badDER); - CFMutableArrayRef *urls; - if (DEROidCompare(&ad.accessMethod, &oidAdOCSP)) - urls = &certificate->_ocspResponders; - else if (DEROidCompare(&ad.accessMethod, &oidAdCAIssuer)) - urls = &certificate->_caIssuers; - else - continue; - - DERDecodedInfo generalNameContent; - drtn = DERDecodeItem(&ad.accessLocation, &generalNameContent); - require_noerr_quiet(drtn, badDER); - switch (generalNameContent.tag) { -#if 0 - 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. */ -#endif - case ASN1_CONTEXT_SPECIFIC | 6: - { - CFURLRef url = CFURLCreateWithBytes(kCFAllocatorDefault, - generalNameContent.content.data, generalNameContent.content.length, - kCFStringEncodingASCII, NULL); - if (url) { - if (!*urls) - *urls = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(*urls, url); - CFRelease(url); - } - break; - } - default: - secinfo("cert", "bad general name for id-ad-ocsp AccessDescription t: 0x%02llx v: %.*s", - generalNameContent.tag, (int)generalNameContent.content.length, generalNameContent.content.data); - goto badDER; - } - } - require_quiet(drtn == DR_EndOfSequence, badDER); - return; -badDER: - secinfo("cert", "failed to parse Authority Information Access extension"); -} - -static void SecCEPSubjectInfoAccess(SecCertificateRefP certificate, - const SecCertificateExtension *extn) { - secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); -} - -static void SecCEPNetscapeCertType(SecCertificateRefP certificate, - const SecCertificateExtension *extn) { - secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); -} - -static void SecCEPEntrustVersInfo(SecCertificateRefP certificate, - const SecCertificateExtension *extn) { - secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); -} - -/* Dictionary key callback for comparing to DERItems. */ -static Boolean SecDERItemEqual(const void *value1, const void *value2) { - return DEROidCompare((const DERItem *)value1, (const DERItem *)value2); -} - -/* Dictionary key callback calculating the hash of a DERItem. */ -static CFHashCode SecDERItemHash(const void *value) { - const DERItem *derItem = (const DERItem *)value; - CFHashCode hash = derItem->length; - DERSize ix = derItem->length > 8 ? derItem->length - 8 : 0; - for (; ix < derItem->length; ++ix) { - hash = (hash << 9) + (hash >> 23) + derItem->data[ix]; - } - - return hash; -} - -/* Dictionary key callbacks using the above 2 functions. */ -static const CFDictionaryKeyCallBacks SecDERItemKeyCallBacks = { - 0, /* version */ - NULL, /* retain */ - NULL, /* release */ - NULL, /* copyDescription */ - SecDERItemEqual, /* equal */ - SecDERItemHash /* hash */ -}; - -static void SecCertificateRegisterClass(void) { - static const CFRuntimeClass kSecCertificateClass = { - 0, /* version */ - "SecCertificate", /* class name */ - NULL, /* init */ - NULL, /* copy */ - SecCertificateDestroy, /* dealloc */ - SecCertificateEqual, /* equal */ - SecCertificateHash, /* hash */ - NULL, /* copyFormattingDesc */ - SecCertificateCopyDescription /* copyDebugDesc */ - }; - - kSecCertificateTypeID = _CFRuntimeRegisterClass(&kSecCertificateClass); - - /* Build a dictionary that maps from extension OIDs to callback functions - which can parse the extension of the type given. */ - static const void *extnOIDs[] = { - &oidSubjectKeyIdentifier, - &oidKeyUsage, - &oidPrivateKeyUsagePeriod, - &oidSubjectAltName, - &oidIssuerAltName, - &oidBasicConstraints, - &oidCrlDistributionPoints, - &oidCertificatePolicies, - &oidPolicyMappings, - &oidAuthorityKeyIdentifier, - &oidPolicyConstraints, - &oidExtendedKeyUsage, - &oidInhibitAnyPolicy, - &oidAuthorityInfoAccess, - &oidSubjectInfoAccess, - &oidNetscapeCertType, - &oidEntrustVersInfo - }; - static const void *extnParsers[] = { - SecCEPSubjectKeyIdentifier, - SecCEPKeyUsage, - SecCEPPrivateKeyUsagePeriod, - SecCEPSubjectAltName, - SecCEPIssuerAltName, - SecCEPBasicConstraints, - SecCEPCrlDistributionPoints, - SecCEPCertificatePolicies, - SecCEPPolicyMappings, - SecCEPAuthorityKeyIdentifier, - SecCEPPolicyConstraints, - SecCEPExtendedKeyUsage, - SecCEPInhibitAnyPolicy, - SecCEPAuthorityInfoAccess, - SecCEPSubjectInfoAccess, - SecCEPNetscapeCertType, - SecCEPEntrustVersInfo - }; - gExtensionParsers = CFDictionaryCreate(kCFAllocatorDefault, extnOIDs, - extnParsers, sizeof(extnOIDs) / sizeof(*extnOIDs), - &SecDERItemKeyCallBacks, NULL); -} - -/* Given the contents of an X.501 Name return the contents of a normalized - X.501 name. */ -static CFDataRef createNormalizedX501Name(CFAllocatorRef allocator, - const DERItem *x501name) { - CFMutableDataRef result = CFDataCreateMutable(allocator, x501name->length); - CFIndex length = x501name->length; - CFDataSetLength(result, length); - UInt8 *base = CFDataGetMutableBytePtr(result); - - DERSequence rdnSeq; - DERReturn drtn = DERDecodeSeqContentInit(x501name, &rdnSeq); - - require_noerr_quiet(drtn, badDER); - DERDecodedInfo rdn; - - /* Always points to last rdn tag. */ - const DERByte *rdnTag = rdnSeq.nextItem; - /* Offset relative to base of current rdn set tag. */ - CFIndex rdnTagLocation = 0; - while ((drtn = DERDecodeSeqNext(&rdnSeq, &rdn)) == DR_Success) { - require_quiet(rdn.tag == ASN1_CONSTR_SET, badDER); - /* We don't allow empty RDNs. */ - require_quiet(rdn.content.length != 0, badDER); - /* Length of the tag and length of the current rdn. */ - CFIndex rdnTLLength = rdn.content.data - rdnTag; - CFIndex rdnContentLength = rdn.content.length; - /* Copy the tag and length of the RDN. */ - memcpy(base + rdnTagLocation, rdnTag, rdnTLLength); - - DERSequence atvSeq; - drtn = DERDecodeSeqContentInit(&rdn.content, &atvSeq); - DERDecodedInfo atv; - /* Always points to tag of current atv sequence. */ - const DERByte *atvTag = atvSeq.nextItem; - /* Offset relative to base of current atv sequence tag. */ - CFIndex atvTagLocation = rdnTagLocation + rdnTLLength; - while ((drtn = DERDecodeSeqNext(&atvSeq, &atv)) == DR_Success) { - require_quiet(atv.tag == ASN1_CONSTR_SEQUENCE, badDER); - /* Length of the tag and length of the current atv. */ - CFIndex atvTLLength = atv.content.data - atvTag; - CFIndex atvContentLength = atv.content.length; - /* Copy the tag and length of the atv and the atv itself. */ - memcpy(base + atvTagLocation, atvTag, - atvTLLength + atv.content.length); - - /* Now decode the atv sequence. */ - DERAttributeTypeAndValue atvPair; - drtn = DERParseSequenceContent(&atv.content, - DERNumAttributeTypeAndValueItemSpecs, - DERAttributeTypeAndValueItemSpecs, - &atvPair, sizeof(atvPair)); - require_noerr_quiet(drtn, badDER); - require_quiet(atvPair.type.length != 0, badDER); - DERDecodedInfo value; - drtn = DERDecodeItem(&atvPair.value, &value); - require_noerr_quiet(drtn, badDER); - - /* (c) attribute values in PrintableString are not case sensitive - (e.g., "Marianne Swanson" is the same as "MARIANNE SWANSON"); and - - (d) attribute values in PrintableString are compared after - removing leading and trailing white space and converting internal - substrings of one or more consecutive white space characters to a - single space. */ - if (value.tag == ASN1_PRINTABLE_STRING) { - /* Offset relative to base of current value tag. */ - CFIndex valueTagLocation = atvTagLocation + atvPair.value.data - atvTag; - CFIndex valueTLLength = value.content.data - atvPair.value.data; - CFIndex valueContentLength = value.content.length; - - /* Now copy all the bytes, but convert to upper case while - doing so and convert multiple whitespace chars into a - single space. */ - bool lastWasBlank = false; - CFIndex valueLocation = valueTagLocation + valueTLLength; - CFIndex valueCurrentLocation = valueLocation; - CFIndex ix; - for (ix = 0; ix < valueContentLength; ++ix) { - UInt8 ch = value.content.data[ix]; - if (isblank(ch)) { - if (lastWasBlank) { - continue; - } else { - /* Don't insert a space for first character - we encounter. */ - if (valueCurrentLocation > valueLocation) { - base[valueCurrentLocation++] = ' '; - } - lastWasBlank = true; - } - } else { - lastWasBlank = false; - if ('a' <= ch && ch <= 'z') { - base[valueCurrentLocation++] = ch + 'A' - 'a'; - } else { - base[valueCurrentLocation++] = ch; - } - } - } - /* Finally if lastWasBlank remove the trailing space. */ - if (lastWasBlank && valueCurrentLocation > valueLocation) { - valueCurrentLocation--; - } - /* Adjust content length to normalized length. */ - valueContentLength = valueCurrentLocation - valueLocation; - - /* Number of bytes by which the length should be shorted. */ - CFIndex lengthDiff = value.content.length - valueContentLength; - if (lengthDiff == 0) { - /* Easy case no need to adjust lengths. */ - } else { - /* Hard work we need to go back and fix up length fields - for: - 1) The value itself. - 2) The ATV Sequence containing type/value - 3) The RDN Set containing one or more atv pairs. - 4) The result. - */ - - /* Step 1 fix up length of value. */ - /* Length of value tag and length minus the tag. */ - DERSize newValueTLLength = valueTLLength - 1; - drtn = DEREncodeLength(valueContentLength, - base + valueTagLocation + 1, &newValueTLLength); - /* Add the length of the tag back in. */ - newValueTLLength++; - CFIndex valueLLDiff = valueTLLength - newValueTLLength; - if (valueLLDiff) { - /* The size of the length field changed, let's slide - the value back by valueLLDiff bytes. */ - memmove(base + valueTagLocation + newValueTLLength, - base + valueTagLocation + valueTLLength, - valueContentLength); - /* The length diff for the enclosing object. */ - lengthDiff += valueLLDiff; - } - - /* Step 2 fix up length of the enclosing ATV Sequence. */ - atvContentLength -= lengthDiff; - DERSize newATVTLLength = atvTLLength - 1; - drtn = DEREncodeLength(atvContentLength, - base + atvTagLocation + 1, &newATVTLLength); - /* Add the length of the tag back in. */ - newATVTLLength++; - CFIndex atvLLDiff = atvTLLength - newATVTLLength; - if (atvLLDiff) { - /* The size of the length field changed, let's slide - the value back by valueLLDiff bytes. */ - memmove(base + atvTagLocation + newATVTLLength, - base + atvTagLocation + atvTLLength, - atvContentLength); - /* The length diff for the enclosing object. */ - lengthDiff += atvLLDiff; - atvTLLength = newATVTLLength; - } - - /* Step 3 fix up length of enclosing RDN Set. */ - rdnContentLength -= lengthDiff; - DERSize newRDNTLLength = rdnTLLength - 1; - drtn = DEREncodeLength(rdnContentLength, - base + rdnTagLocation + 1, &newRDNTLLength); - /* Add the length of the tag back in. */ - newRDNTLLength++; - CFIndex rdnLLDiff = rdnTLLength - newRDNTLLength; - if (rdnLLDiff) { - /* The size of the length field changed, let's slide - the value back by valueLLDiff bytes. */ - memmove(base + rdnTagLocation + newRDNTLLength, - base + rdnTagLocation + rdnTLLength, - rdnContentLength); - /* The length diff for the enclosing object. */ - lengthDiff += rdnLLDiff; - rdnTLLength = newRDNTLLength; - - /* Adjust the locations that might have changed due to - this slide. */ - atvTagLocation -= rdnLLDiff; - } - } - } - atvTagLocation += atvTLLength + atvContentLength; - atvTag = atvSeq.nextItem; - } - require_quiet(drtn == DR_EndOfSequence, badDER); - rdnTagLocation += rdnTLLength + rdnContentLength; - rdnTag = rdnSeq.nextItem; - } - require_quiet(drtn == DR_EndOfSequence, badDER); - /* Truncate the result to the proper length. */ - CFDataSetLength(result, rdnTagLocation); - - return result; - -badDER: - CFRelease(result); - return NULL; -} - -/* AUDIT[securityd]: - certificate->_der is a caller provided data of any length (might be 0). - - Top level certificate decode. - */ -static bool SecCertificateParse(SecCertificateRefP certificate) -{ - DERReturn drtn; - - check(certificate); - CFAllocatorRef allocator = CFGetAllocator(certificate); - - /* top level decode */ - DERSignedCertCrl signedCert; - drtn = DERParseSequence(&certificate->_der, DERNumSignedCertCrlItemSpecs, - DERSignedCertCrlItemSpecs, &signedCert, - sizeof(signedCert)); - require_noerr_quiet(drtn, badCert); - /* Store tbs since we need to digest it for verification later on. */ - certificate->_tbs = signedCert.tbs; - - /* decode the TBSCert - it was saved in full DER form */ - DERTBSCert tbsCert; - drtn = DERParseSequence(&signedCert.tbs, - DERNumTBSCertItemSpecs, DERTBSCertItemSpecs, - &tbsCert, sizeof(tbsCert)); - require_noerr_quiet(drtn, badCert); - - /* sequence we're given: decode the signedCerts Signature Algorithm. */ - /* This MUST be the same as the certificate->_tbsSigAlg with the exception - of the params field. */ - drtn = DERParseSequenceContent(&signedCert.sigAlg, - DERNumAlgorithmIdItemSpecs, DERAlgorithmIdItemSpecs, - &certificate->_sigAlg, sizeof(certificate->_sigAlg)); - require_noerr_quiet(drtn, badCert); - - /* The contents of signedCert.sig is a bit string whose contents - are the signature itself. */ - DERByte numUnusedBits; - drtn = DERParseBitString(&signedCert.sig, - &certificate->_signature, &numUnusedBits); - require_noerr_quiet(drtn, badCert); - - /* Now decode the tbsCert. */ - - /* First we turn the optional version into an int. */ - if (tbsCert.version.length) { - DERDecodedInfo decoded; - drtn = DERDecodeItem(&tbsCert.version, &decoded); - require_noerr_quiet(drtn, badCert); - require_quiet(decoded.tag == ASN1_INTEGER, badCert); - require_quiet(decoded.content.length == 1, badCert); - certificate->_version = decoded.content.data[0]; - require_quiet(certificate->_version > 0, badCert); - require_quiet(certificate->_version < 3, badCert); - } else { - certificate->_version = 0; - } - - /* The serial number is in the tbsCert.serialNum - it was saved in - INTEGER form without the tag and length. */ - certificate->_serialNum = tbsCert.serialNum; - certificate->_serialNumber = CFDataCreate(allocator, - tbsCert.serialNum.data, tbsCert.serialNum.length); - - /* sequence we're given: decode the tbsCerts TBS Signature Algorithm. */ - drtn = DERParseSequenceContent(&tbsCert.tbsSigAlg, - DERNumAlgorithmIdItemSpecs, DERAlgorithmIdItemSpecs, - &certificate->_tbsSigAlg, sizeof(certificate->_tbsSigAlg)); - require_noerr_quiet(drtn, badCert); - - /* The issuer is in the tbsCert.issuer - it's a sequence without the tag - and length fields. */ - certificate->_issuer = tbsCert.issuer; - certificate->_normalizedIssuer = createNormalizedX501Name(allocator, - &tbsCert.issuer); - - /* sequence we're given: decode the tbsCerts Validity sequence. */ - DERValidity validity; - drtn = DERParseSequenceContent(&tbsCert.validity, - DERNumValidityItemSpecs, DERValidityItemSpecs, - &validity, sizeof(validity)); - require_noerr_quiet(drtn, badCert); - require_quiet(derDateGetAbsoluteTime(&validity.notBefore, - &certificate->_notBefore), badCert); - require_quiet(derDateGetAbsoluteTime(&validity.notAfter, - &certificate->_notAfter), badCert); - - /* The subject is in the tbsCert.subject - it's a sequence without the tag - and length fields. */ - certificate->_subject = tbsCert.subject; - certificate->_normalizedSubject = createNormalizedX501Name(allocator, - &tbsCert.subject); - - /* sequence we're given: encoded DERSubjPubKeyInfo - it was saved in full DER form */ - DERSubjPubKeyInfo pubKeyInfo; - drtn = DERParseSequence(&tbsCert.subjectPubKey, - DERNumSubjPubKeyInfoItemSpecs, DERSubjPubKeyInfoItemSpecs, - &pubKeyInfo, sizeof(pubKeyInfo)); - require_noerr_quiet(drtn, badCert); - - /* sequence we're given: decode the pubKeyInfos DERAlgorithmId */ - drtn = DERParseSequenceContent(&pubKeyInfo.algId, - DERNumAlgorithmIdItemSpecs, DERAlgorithmIdItemSpecs, - &certificate->_algId, sizeof(certificate->_algId)); - require_noerr_quiet(drtn, badCert); - - /* Now we can figure out the key's algorithm id and params based on - certificate->_algId.oid. */ - - /* The contents of pubKeyInfo.pubKey is a bit string whose contents - are a PKCS1 format RSA key. */ - drtn = DERParseBitString(&pubKeyInfo.pubKey, - &certificate->_pubKeyDER, &numUnusedBits); - require_noerr_quiet(drtn, badCert); - - /* The contents of tbsCert.issuerID is a bit string. */ - certificate->_issuerUniqueID = tbsCert.issuerID; - - /* The contents of tbsCert.subjectID is a bit string. */ - certificate->_subjectUniqueID = tbsCert.subjectID; - - /* Extensions. */ - if (tbsCert.extensions.length) { - CFIndex extensionCount = 0; - DERSequence derSeq; - DERTag tag; - drtn = DERDecodeSeqInit(&tbsCert.extensions, &tag, - &derSeq); - require_noerr_quiet(drtn, badCert); - require_quiet(tag == ASN1_CONSTR_SEQUENCE, badCert); - DERDecodedInfo currDecoded; - while ((drtn = DERDecodeSeqNext(&derSeq, &currDecoded)) == DR_Success) { -#if 0 -/* ! = MUST recognize ? = SHOULD recognize -*/ - - KnownExtension _subjectKeyID; /* ?SubjectKeyIdentifier id-ce 14 */ - KnownExtension _keyUsage; /* !KeyUsage id-ce 15 */ - KnownExtension _subjectAltName; /* !SubjectAltName id-ce 17 */ - KnownExtension _basicConstraints; /* !BasicConstraints id-ce 19 */ - KnownExtension _authorityKeyID; /* ?AuthorityKeyIdentifier id-ce 35 */ - KnownExtension _extKeyUsage; /* !ExtKeyUsage id-ce 37 */ - KnownExtension _netscapeCertType; /* 2.16.840.1.113730.1.1 netscape 1 1 */ - KnownExtension _qualCertStatements; /* QCStatements id-pe 3 */ - - KnownExtension _issuerAltName; /* IssuerAltName id-ce 18 */ - KnownExtension _nameConstraints; /* !NameConstraints id-ce 30 */ - KnownExtension _cRLDistributionPoints; /* CRLDistributionPoints id-ce 31 */ - KnownExtension _certificatePolicies; /* !CertificatePolicies id-ce 32 */ - KnownExtension _policyMappings; /* ?PolicyMappings id-ce 33 */ - KnownExtension _policyConstraints; /* !PolicyConstraints id-ce 36 */ - KnownExtension _freshestCRL; /* FreshestCRL id-ce 46 */ - KnownExtension _inhibitAnyPolicy; /* !InhibitAnyPolicy id-ce 54 */ - - KnownExtension _authorityInfoAccess; /* AuthorityInfoAccess id-pe 1 */ - KnownExtension _subjectInfoAccess; /* SubjectInfoAccess id-pe 11 */ -#endif - - extensionCount++; - } - require_quiet(drtn == DR_EndOfSequence, badCert); - - /* Put some upper limit on the number of extentions allowed. */ - require_quiet(extensionCount < 10000, badCert); - certificate->_extensionCount = extensionCount; - CFIndex mallocCount = extensionCount > 0 ? extensionCount : 1; - certificate->_extensions = - malloc(sizeof(SecCertificateExtension) * mallocCount); - require_quiet(certificate->_extensions, badCert); - - CFIndex ix = 0; - drtn = DERDecodeSeqInit(&tbsCert.extensions, &tag, &derSeq); - require_noerr_quiet(drtn, badCert); - for (ix = 0; ix < extensionCount; ++ix) { - drtn = DERDecodeSeqNext(&derSeq, &currDecoded); - require_quiet(drtn == DR_Success || - (ix == extensionCount - 1 && drtn == DR_EndOfSequence), badCert); - require_quiet(currDecoded.tag == ASN1_CONSTR_SEQUENCE, badCert); - DERExtension extn; - drtn = DERParseSequenceContent(&currDecoded.content, - DERNumExtensionItemSpecs, DERExtensionItemSpecs, - &extn, sizeof(extn)); - require_noerr_quiet(drtn, badCert); - /* Copy stuff into certificate->extensions[ix]. */ - certificate->_extensions[ix].extnID = extn.extnID; - require_noerr_quiet(drtn = DERParseBooleanWithDefault(&extn.critical, false, - &certificate->_extensions[ix].critical), badCert); - certificate->_extensions[ix].extnValue = extn.extnValue; - - SecCertificateExtensionParser parser = - (SecCertificateExtensionParser)CFDictionaryGetValue( - gExtensionParsers, &certificate->_extensions[ix].extnID); - if (parser) { - /* Invoke the parser. */ - parser(certificate, &certificate->_extensions[ix]); - } else if (certificate->_extensions[ix].critical) { - secinfo("cert", "Found unknown critical extension"); - certificate->_foundUnknownCriticalExtension = true; - } else { - secinfo("cert", "Found unknown non critical extension"); - } - } - } - - return true; - -badCert: - return false; -} - - -/* Public API functions. */ -CFTypeID SecCertificateGetTypeIDP(void) { - pthread_once(&kSecCertificateRegisterClass, SecCertificateRegisterClass); - return kSecCertificateTypeID; -} - -SecCertificateRefP SecCertificateCreateWithBytesP(CFAllocatorRef allocator, - const UInt8 *der_bytes, CFIndex der_length) { - check(der_bytes); - check(der_length); - CFIndex size = sizeof(struct __SecCertificate) + der_length; - SecCertificateRefP result = (SecCertificateRefP)_CFRuntimeCreateInstance( - allocator, SecCertificateGetTypeIDP(), size - sizeof(CFRuntimeBase), 0); - if (result) { - memset((char*)result + sizeof(result->_base), 0, - sizeof(*result) - sizeof(result->_base)); - result->_der.data = ((DERByte *)result + sizeof(*result)); - result->_der.length = der_length; - if(der_bytes) { - memcpy(result->_der.data, der_bytes, der_length); - } - if (!SecCertificateParse(result)) { - CFRelease(result); - return NULL; - } - } - return result; -} - -/* @@@ Placeholder until iap submits a binary is fixed. */ -SecCertificateRefP SecCertificateCreate(CFAllocatorRef allocator, - const UInt8 *der_bytes, CFIndex der_length); - -SecCertificateRefP SecCertificateCreate(CFAllocatorRef allocator, - const UInt8 *der_bytes, CFIndex der_length) { - return SecCertificateCreateWithBytesP(allocator, der_bytes, der_length); -} -/* @@@ End of placeholder. */ - -/* AUDIT[securityd](done): - der_certificate is a caller provided data of any length (might be 0), only - its cf type has been checked. - */ -SecCertificateRefP SecCertificateCreateWithDataP(CFAllocatorRef allocator, - CFDataRef der_certificate) { - check(der_certificate); - CFIndex size = sizeof(struct __SecCertificate); - SecCertificateRefP result = (SecCertificateRefP)_CFRuntimeCreateInstance( - allocator, SecCertificateGetTypeIDP(), size - sizeof(CFRuntimeBase), 0); - if (result) { - memset((char*)result + sizeof(result->_base), 0, size - sizeof(result->_base)); - result->_der_data = CFDataCreateCopy(allocator, der_certificate); - result->_der.data = (DERByte *)CFDataGetBytePtr(result->_der_data); - result->_der.length = CFDataGetLength(result->_der_data); - if (!SecCertificateParse(result)) { - CFRelease(result); - return NULL; - } - } - return result; -} - -CFDataRef SecCertificateCopyDataP(SecCertificateRefP certificate) { - check(certificate); - CFDataRef result; - if (certificate->_der_data) { - CFRetain(certificate->_der_data); - result = certificate->_der_data; - } else { - result = CFDataCreate(CFGetAllocator(certificate), - certificate->_der.data, certificate->_der.length); -#if 0 - /* FIXME: If we wish to cache result we need to lock the certificate. - Also this create 2 copies of the certificate data which is somewhat - suboptimal. */ - CFRetain(result); - certificate->_der_data = result; -#endif - } - - return result; -} - -CFIndex SecCertificateGetLengthP(SecCertificateRefP certificate) { - return certificate->_der.length; -} - -const UInt8 *SecCertificateGetBytePtrP(SecCertificateRefP certificate) { - return certificate->_der.data; -} - -/* From rfc3280 - Appendix B. ASN.1 Notes - - Object Identifiers (OIDs) are used throughout this specification to - identify certificate policies, public key and signature algorithms, - certificate extensions, etc. There is no maximum size for OIDs. - This specification mandates support for OIDs which have arc elements - with values that are less than 2^28, that is, they MUST be between 0 - and 268,435,455, inclusive. This allows each arc element to be - represented within a single 32 bit word. Implementations MUST also - support OIDs where the length of the dotted decimal (see [RFC 2252], - section 4.1) string representation can be up to 100 bytes - (inclusive). Implementations MUST be able to handle OIDs with up to - 20 elements (inclusive). CAs SHOULD NOT issue certificates which - contain OIDs that exceed these requirements. Likewise, CRL issuers - SHOULD NOT issue CRLs which contain OIDs that exceed these - requirements. -*/ - -/* Oids longer than this are considered invalid. */ -#define MAX_OID_SIZE 32 - -static CFStringRef SecDERItemCopyOIDDecimalRepresentation(CFAllocatorRef allocator, - const DERItem *oid) { - - if (oid->length == 0) { - return SecFrameworkCopyLocalizedString(CFSTR(""), - CFSTR("SecCertificate")); - } - if (oid->length > MAX_OID_SIZE) { - return SecFrameworkCopyLocalizedString(CFSTR("Oid too long"), - CFSTR("SecCertificate")); - } - - CFMutableStringRef result = CFStringCreateMutable(allocator, 0); - - // The first two levels are encoded into one byte, since the root level - // has only 3 nodes (40*x + y). However if x = joint-iso-itu-t(2) then - // y may be > 39, so we have to add special-case handling for this. - uint32_t x = oid->data[0] / 40; - uint32_t y = oid->data[0] % 40; - if (x > 2) - { - // Handle special case for large y if x = 2 - y += (x - 2) * 40; - x = 2; - } - CFStringAppendFormat(result, NULL, CFSTR("%u.%u"), x, y); - - uint32_t value = 0; - for (x = 1; x < oid->length; ++x) - { - value = (value << 7) | (oid->data[x] & 0x7F); - /* @@@ value may not span more than 4 bytes. */ - /* A max number of 20 values is allowed. */ - if (!(oid->data[x] & 0x80)) - { - CFStringAppendFormat(result, NULL, CFSTR(".%lu"), (unsigned long)value); - value = 0; - } - } - return result; -} - -static CFStringRef copyLocalizedOidDescription(CFAllocatorRef allocator, - const DERItem *oid) { - if (oid->length == 0) { - return SecFrameworkCopyLocalizedString(CFSTR(""), - CFSTR("SecCertificate")); - } - - /* Build the key we use to lookup the localized OID description. */ - CFMutableStringRef oidKey = CFStringCreateMutable(allocator, - oid->length * 3 + 5); - CFStringAppendFormat(oidKey, NULL, CFSTR("06 %02lX"), (unsigned long)oid->length); - DERSize ix; - for (ix = 0; ix < oid->length; ++ix) - CFStringAppendFormat(oidKey, NULL, CFSTR(" %02X"), oid->data[ix]); - - CFStringRef name = SecFrameworkCopyLocalizedString(oidKey, CFSTR("OID")); - if (CFEqual(oidKey, name)) { - CFRelease(name); - name = SecDERItemCopyOIDDecimalRepresentation(allocator, oid); - } - CFRelease(oidKey); - - return name; -} - -/* Return the ipAddress as a dotted quad for ipv4 or as 8 colon separated - 4 digit hex strings for ipv6. Return NULL if the passed in IP doesn't - have a length of exactly 4 or 16 octects. */ -static CFStringRef copyIPAddressContentDescription(CFAllocatorRef allocator, - const DERItem *ip) { - /* @@@ This is the IP Address as an OCTECT STRING. For IPv4 it's - 4 octects addr, or 8 octects, addr/mask for ipv6 it's - 16 octects addr, or 32 octects addr/mask. */ - CFStringRef value = NULL; - if (ip->length == 4) { - value = CFStringCreateWithFormat(allocator, NULL, - CFSTR("%u.%u.%u.%u"), - ip->data[0], ip->data[1], ip->data[2], ip->data[3]); - } else if (ip->length == 16) { - value = CFStringCreateWithFormat(allocator, NULL, - CFSTR("%02x%02x:%02x%02x:%02x%02x:%02x%02x:" - "%02x%02x:%02x%02x:%02x%02x:%02x%02x"), - ip->data[0], ip->data[1], ip->data[2], ip->data[3], - ip->data[4], ip->data[5], ip->data[6], ip->data[7], - ip->data[8], ip->data[9], ip->data[10], ip->data[11], - ip->data[12], ip->data[13], ip->data[14], ip->data[15]); - } - - return value; -} - -#if 0 -static CFStringRef copyFullOidDescription(CFAllocatorRef allocator, - const DERItem *oid) { - CFStringRef decimal = SecDERItemCopyOIDDecimalRepresentation(allocator, oid); - CFStringRef name = copyLocalizedOidDescription(allocator, oid); - CFStringRef oid_string = CFStringCreateWithFormat(allocator, NULL, - CFSTR("%@ (%@)"), name, decimal); - CFRelease(name); - CFRelease(decimal); - return oid_string; -} -#endif - -void appendPropertyP(CFMutableArrayRef properties, - CFStringRef propertyType, CFStringRef label, CFTypeRef value) { - CFDictionaryRef property; - if (label) { - CFStringRef localizedLabel = SecFrameworkCopyLocalizedString(label, - CFSTR("SecCertificate")); - const void *all_keys[4]; - all_keys[0] = kSecPropertyKeyType; - all_keys[1] = kSecPropertyKeyLabel; - all_keys[2] = kSecPropertyKeyLocalizedLabel; - all_keys[3] = kSecPropertyKeyValue; - const void *property_values[] = { - propertyType, - label, - localizedLabel, - value, - }; - property = CFDictionaryCreate(CFGetAllocator(properties), - all_keys, property_values, value ? 4 : 3, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFRelease(localizedLabel); - } else { - const void *nolabel_keys[2]; - nolabel_keys[0] = kSecPropertyKeyType; - nolabel_keys[1] = kSecPropertyKeyValue; - const void *property_values[] = { - propertyType, - value, - }; - property = CFDictionaryCreate(CFGetAllocator(properties), - nolabel_keys, property_values, 2, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - } - - CFArrayAppendValue(properties, property); - CFRelease(property); -} - -/* YYMMDDhhmmZ */ -#define UTC_TIME_NOSEC_ZULU_LEN 11 -/* YYMMDDhhmmssZ */ -#define UTC_TIME_ZULU_LEN 13 -/* YYMMDDhhmmssThhmm */ -#define UTC_TIME_LOCALIZED_LEN 17 -/* YYYYMMDDhhmmssZ */ -#define GENERALIZED_TIME_ZULU_LEN 15 -/* YYYYMMDDhhmmssThhmm */ -#define GENERALIZED_TIME_LOCALIZED_LEN 19 - -/* Parse 2 digits at (*p)[0] and (*p)[1] and return the result. Also - advance *p by 2. */ -static inline SInt32 parseDecimalPair(const DERByte **p) { - const DERByte *cp = *p; - *p += 2; - return 10 * (cp[0] - '0') + cp[1] - '0'; -} - -/* Decode a choice of UTCTime or GeneralizedTime to a CFAbsoluteTime. Return - true if the date was valid and properly decoded, also return the result in - absTime. Return false otherwise. */ -static CFAbsoluteTime SecAbsoluteTimeFromDateContent(DERTag tag, const uint8_t *bytes, - size_t length) { - check(bytes); - if (length == 0) - return NULL_TIME; - - bool isUtcLength = false; - bool isLocalized = false; - bool noSeconds = false; - switch (length) { - case UTC_TIME_NOSEC_ZULU_LEN: /* YYMMDDhhmmZ */ - isUtcLength = true; - noSeconds = true; - break; - case UTC_TIME_ZULU_LEN: /* YYMMDDhhmmssZ */ - isUtcLength = true; - break; - case GENERALIZED_TIME_ZULU_LEN: /* YYYYMMDDhhmmssZ */ - break; - case UTC_TIME_LOCALIZED_LEN: /* YYMMDDhhmmssThhmm (where T=[+,-]) */ - isUtcLength = true; - /*DROPTHROUGH*/ - case GENERALIZED_TIME_LOCALIZED_LEN:/* YYYYMMDDhhmmssThhmm (where T=[+,-]) */ - isLocalized = true; - break; - default: /* unknown format */ - return NULL_TIME; - } - - /* Make sure the der tag fits the thing inside it. */ - if (tag == ASN1_UTC_TIME) { - if (!isUtcLength) - return NULL_TIME; - } else if (tag == ASN1_GENERALIZED_TIME) { - if (isUtcLength) - return NULL_TIME; - } else { - return NULL_TIME; - } - - const DERByte *cp = bytes; - /* Check that all characters are digits, except if localized the timezone - indicator or if not localized the 'Z' at the end. */ - DERSize ix; - for (ix = 0; ix < length; ++ix) { - if (!(isdigit(cp[ix]))) { - if ((isLocalized && ix == length - 5 && - (cp[ix] == '+' || cp[ix] == '-')) || - (!isLocalized && ix == length - 1 && cp[ix] == 'Z')) { - continue; - } - return NULL_TIME; - } - } - - /* Initialize the fields in a gregorian date struct. */ - CFGregorianDate gdate; - if (isUtcLength) { - SInt32 year = parseDecimalPair(&cp); - if (year < 50) { - /* 0 <= year < 50 : assume century 21 */ - gdate.year = 2000 + year; - } else if (year < 70) { - /* 50 <= year < 70 : illegal per PKIX */ - return false; - } else { - /* 70 < year <= 99 : assume century 20 */ - gdate.year = 1900 + year; - } - } else { - gdate.year = 100 * parseDecimalPair(&cp) + parseDecimalPair(&cp); - } - gdate.month = parseDecimalPair(&cp); - gdate.day = parseDecimalPair(&cp); - gdate.hour = parseDecimalPair(&cp); - gdate.minute = parseDecimalPair(&cp); - if (noSeconds) { - gdate.second = 0; - } else { - gdate.second = parseDecimalPair(&cp); - } - - CFTimeInterval timeZoneOffset = 0; - if (isLocalized) { - /* ZONE INDICATOR */ - SInt32 multiplier = *cp++ == '+' ? 60 : -60; - timeZoneOffset = multiplier * - (parseDecimalPair(&cp) + 60 * parseDecimalPair(&cp)); - } else { - timeZoneOffset = 0; - } - - secinfo("dateparse", - "date %.*s year: %04d-%02d-%02d %02d:%02d:%02.f %+05.f", - (int)length, bytes, (int)gdate.year, gdate.month, - gdate.day, gdate.hour, gdate.minute, gdate.second, - timeZoneOffset / 60); - - if (!CFGregorianDateIsValid(gdate, kCFGregorianAllUnits)) - return false; - CFTimeZoneRef timeZone = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, - timeZoneOffset); - if (!timeZone) - return NULL_TIME; - CFAbsoluteTime absTime = CFGregorianDateGetAbsoluteTime(gdate, timeZone); - CFRelease(timeZone); - return absTime; -} - -static bool derDateContentGetAbsoluteTime(DERTag tag, const DERItem *date, - CFAbsoluteTime *pabsTime) { - CFAbsoluteTime absTime = SecAbsoluteTimeFromDateContent(tag, date->data, - date->length); - if (absTime == NULL_TIME) - return false; - - *pabsTime = absTime; - return true; -} - -/* Decode a choice of UTCTime or GeneralizedTime to a CFAbsoluteTime. Return - true if the date was valid and properly decoded, also return the result in - absTime. Return false otherwise. */ -static bool derDateGetAbsoluteTime(const DERItem *dateChoice, - CFAbsoluteTime *absTime) { - check(dateChoice); - check(absTime); - if (dateChoice->length == 0) - return false; - - DERDecodedInfo decoded; - if (DERDecodeItem(dateChoice, &decoded)) - return false; - - return derDateContentGetAbsoluteTime(decoded.tag, &decoded.content, - absTime); -} - -static void appendDataProperty(CFMutableArrayRef properties, - CFStringRef label, const DERItem *der_data) { - CFDataRef data = CFDataCreate(CFGetAllocator(properties), - der_data->data, der_data->length); - appendPropertyP(properties, kSecPropertyTypeData, label, data); - CFRelease(data); -} - -static void appendUnparsedProperty(CFMutableArrayRef properties, - CFStringRef label, const DERItem *der_data) { - CFStringRef newLabel = CFStringCreateWithFormat(CFGetAllocator(properties), - NULL, CFSTR("Unparsed %@"), label); - appendDataProperty(properties, newLabel, der_data); - CFRelease(newLabel); -} - -static void appendInvalidProperty(CFMutableArrayRef properties, - CFStringRef label, const DERItem *der_data) { - CFStringRef newLabel = CFStringCreateWithFormat(CFGetAllocator(properties), - NULL, CFSTR("Invalid %@"), label); - appendDataProperty(properties, newLabel, der_data); - CFRelease(newLabel); -} - -static void appendDateContentProperty(CFMutableArrayRef properties, - CFStringRef label, DERTag tag, const DERItem *dateContent) { - CFAbsoluteTime absTime; - if (!derDateContentGetAbsoluteTime(tag, dateContent, &absTime)) { - /* Date decode failure insert hex bytes instead. */ - return appendInvalidProperty(properties, label, dateContent); - } - CFDateRef date = CFDateCreate(CFGetAllocator(properties), absTime); - appendPropertyP(properties, kSecPropertyTypeDate, label, date); - CFRelease(date); -} - -static void appendDateProperty(CFMutableArrayRef properties, - CFStringRef label, CFAbsoluteTime absTime) { - CFDateRef date = CFDateCreate(CFGetAllocator(properties), absTime); - appendPropertyP(properties, kSecPropertyTypeDate, label, date); - CFRelease(date); -} - -static void appendIPAddressContentProperty(CFMutableArrayRef properties, - CFStringRef label, const DERItem *ip) { - CFStringRef value = - copyIPAddressContentDescription(CFGetAllocator(properties), ip); - if (value) { - appendPropertyP(properties, kSecPropertyTypeString, label, value); - CFRelease(value); - } else { - appendUnparsedProperty(properties, label, ip); - } -} - -static void appendURLContentProperty(CFMutableArrayRef properties, - CFStringRef label, const DERItem *urlContent) { - CFURLRef url = CFURLCreateWithBytes(CFGetAllocator(properties), - urlContent->data, urlContent->length, kCFStringEncodingASCII, NULL); - if (url) { - appendPropertyP(properties, kSecPropertyTypeURL, label, url); - CFRelease(url); - } else { - appendInvalidProperty(properties, label, urlContent); - } -} - -static void appendURLProperty(CFMutableArrayRef properties, - CFStringRef label, const DERItem *url) { - DERDecodedInfo decoded; - DERReturn drtn; - - drtn = DERDecodeItem(url, &decoded); - if (drtn || decoded.tag != ASN1_IA5_STRING) { - appendInvalidProperty(properties, label, url); - } else { - appendURLContentProperty(properties, label, &decoded.content); - } -} - -static void appendOIDProperty(CFMutableArrayRef properties, - CFStringRef label, const DERItem *oid) { - CFStringRef oid_string = copyLocalizedOidDescription(CFGetAllocator(properties), - oid); - appendPropertyP(properties, kSecPropertyTypeString, label, oid_string); - CFRelease(oid_string); -} - -static void appendAlgorithmProperty(CFMutableArrayRef properties, - CFStringRef label, const DERAlgorithmId *algorithm) { - CFMutableArrayRef alg_props = - CFArrayCreateMutable(CFGetAllocator(properties), 0, - &kCFTypeArrayCallBacks); - appendOIDProperty(alg_props, CFSTR("Algorithm"), &algorithm->oid); - if (algorithm->params.length) { - if (algorithm->params.length == 2 && - algorithm->params.data[0] == ASN1_NULL && - algorithm->params.data[1] == 0) { - /* @@@ Localize or perhaps skip it? */ - appendPropertyP(alg_props, kSecPropertyTypeString, - CFSTR("Parameters"), CFSTR("none")); - } else { - appendUnparsedProperty(alg_props, CFSTR("Parameters"), - &algorithm->params); - } - } - appendPropertyP(properties, kSecPropertyTypeSection, label, alg_props); - CFRelease(alg_props); -} - -static CFStringRef copyHexDescription(CFAllocatorRef allocator, - const DERItem *blob) { - CFIndex ix, length = blob->length /* < 24 ? blob->length : 24 */; - CFMutableStringRef string = CFStringCreateMutable(allocator, - blob->length * 3 - 1); - for (ix = 0; ix < length; ++ix) - if (ix == 0) - CFStringAppendFormat(string, NULL, CFSTR("%02X"), blob->data[ix]); - else - CFStringAppendFormat(string, NULL, CFSTR(" %02X"), blob->data[ix]); - - return string; -} - -static CFStringRef copyBlobString(CFAllocatorRef allocator, - CFStringRef blobType, CFStringRef quanta, const DERItem *blob) { - CFStringRef blobFormat = SecFrameworkCopyLocalizedString( - CFSTR("%@; %d %@; data = %@"), CFSTR("SecCertificate") - /*, "format string for encoded field data (e.g. Sequence; 128 bytes; " - "data = 00 00 ...)" */); - CFStringRef hex = copyHexDescription(allocator, blob); - CFStringRef result = CFStringCreateWithFormat(allocator, NULL, - blobFormat, blobType, blob->length, quanta, hex); - CFRelease(hex); - CFRelease(blobFormat); - - return result; -} - -static CFStringRef copyContentString(CFAllocatorRef allocator, - const DERItem *string, CFStringEncoding encoding, - bool printableOnly) { - /* Strip potential bogus trailing zero from printable strings. */ - DERSize length = string->length; - if (length && string->data[length - 1] == 0) { - /* Don't mess with the length of UTF16 strings though. */ - if (encoding != kCFStringEncodingUTF16) - length--; - } - /* A zero length string isn't considered printable. */ - if (!length && printableOnly) - return NULL; - - /* Passing true for the 5th paramater to CFStringCreateWithBytes() makes - it treat kCFStringEncodingUTF16 as big endian by default, whereas - passing false makes it treat it as native endian by default. */ - CFStringRef result = CFStringCreateWithBytes(allocator, string->data, - length, encoding, encoding == kCFStringEncodingUTF16); - if (result) - return result; - - return printableOnly ? NULL : copyHexDescription(allocator, string); -} - -/* From rfc3280 - Appendix B. ASN.1 Notes - - CAs MUST force the serialNumber to be a non-negative integer, that - is, the sign bit in the DER encoding of the INTEGER value MUST be - zero - this can be done by adding a leading (leftmost) `00'H octet if - necessary. This removes a potential ambiguity in mapping between a - string of octets and an integer value. - - As noted in section 4.1.2.2, serial numbers can be expected to - contain long integers. Certificate users MUST be able to handle - serialNumber values up to 20 octets in length. Conformant CAs MUST - NOT use serialNumber values longer than 20 octets. -*/ - -/* Return the given numeric data as a string: decimal up to 64 bits, - hex otherwise. */ -static CFStringRef copyIntegerContentDescription(CFAllocatorRef allocator, - const DERItem *integer) { - uint64_t value = 0; - CFIndex ix, length = integer->length; - - if (length == 0 || length > 8) - return copyHexDescription(allocator, integer); - - for(ix = 0; ix < length; ++ix) { - value <<= 8; - value += integer->data[ix]; - } - - return CFStringCreateWithFormat(allocator, NULL, CFSTR("%llu"), value); -} - -static CFStringRef copyDERThingContentDescription(CFAllocatorRef allocator, - DERTag tag, const DERItem *derThing, bool printableOnly) { - switch(tag) { - case ASN1_INTEGER: - case ASN1_BOOLEAN: - return printableOnly ? NULL : copyIntegerContentDescription(allocator, derThing); - case ASN1_PRINTABLE_STRING: - case ASN1_IA5_STRING: - return copyContentString(allocator, derThing, kCFStringEncodingASCII, printableOnly); - case ASN1_UTF8_STRING: - case ASN1_GENERAL_STRING: - case ASN1_UNIVERSAL_STRING: - return copyContentString(allocator, derThing, kCFStringEncodingUTF8, printableOnly); - case ASN1_T61_STRING: // 20, also BER_TAG_TELETEX_STRING - case ASN1_VIDEOTEX_STRING: // 21 - case ASN1_VISIBLE_STRING: // 26 - return copyContentString(allocator, derThing, kCFStringEncodingISOLatin1, printableOnly); - case ASN1_BMP_STRING: // 30 - return copyContentString(allocator, derThing, kCFStringEncodingUTF16, printableOnly); - case ASN1_OCTET_STRING: - return printableOnly ? NULL : copyBlobString(allocator, CFSTR("Byte string"), CFSTR("bytes"), - derThing); - //return copyBlobString(BYTE_STRING_STR, BYTES_STR, derThing); - case ASN1_BIT_STRING: - return printableOnly ? NULL : copyBlobString(allocator, CFSTR("Bit string"), CFSTR("bits"), - derThing); - case (DERByte)ASN1_CONSTR_SEQUENCE: - return printableOnly ? NULL : copyBlobString(allocator, CFSTR("Sequence"), CFSTR("bytes"), - derThing); - case (DERByte)ASN1_CONSTR_SET: - return printableOnly ? NULL : copyBlobString(allocator, CFSTR("Set"), CFSTR("bytes"), - derThing); - case ASN1_OBJECT_ID: - return printableOnly ? NULL : copyLocalizedOidDescription(allocator, derThing); - default: - /* @@@ Localize. */ - /* "format string for undisplayed field data with a given DER tag" */ - return printableOnly ? NULL : CFStringCreateWithFormat(allocator, NULL, - CFSTR("not displayed (tag = %llu; length %d)"), - tag, (int)derThing->length); - } -} - -static CFStringRef copyDERThingDescription(CFAllocatorRef allocator, - const DERItem *derThing, bool printableOnly) { - DERDecodedInfo decoded; - DERReturn drtn; - - drtn = DERDecodeItem(derThing, &decoded); - if (drtn) { - return printableOnly ? NULL : copyHexDescription(allocator, derThing); - } else { - return copyDERThingContentDescription(allocator, decoded.tag, - &decoded.content, false); - } -} - -static void appendDERThingProperty(CFMutableArrayRef properties, - CFStringRef label, const DERItem *derThing) { - CFStringRef value = copyDERThingDescription(CFGetAllocator(properties), - derThing, false); - appendPropertyP(properties, kSecPropertyTypeString, label, value); - CFReleaseSafe(value); -} - -static OSStatus appendRDNProperty(void *context, const DERItem *rdnType, - const DERItem *rdnValue, CFIndex rdnIX) { - CFMutableArrayRef properties = (CFMutableArrayRef)context; - if (rdnIX > 0) { - /* If there is more than one value pair we create a subsection for the - second pair, and append things to the subsection for subsequent - pairs. */ - CFIndex lastIX = CFArrayGetCount(properties) - 1; - CFTypeRef lastValue = CFArrayGetValueAtIndex(properties, lastIX); - if (rdnIX == 1) { - /* Since this is the second rdn pair for a given rdn, we setup a - new subsection for this rdn. We remove the first property - from the properties array and make it the first element in the - subsection instead. */ - CFMutableArrayRef rdn_props = CFArrayCreateMutable( - CFGetAllocator(properties), 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(rdn_props, lastValue); - CFArrayRemoveValueAtIndex(properties, lastIX); - appendPropertyP(properties, kSecPropertyTypeSection, NULL, rdn_props); - properties = rdn_props; - } else { - /* Since this is the third or later rdn pair we have already - created a subsection in the top level properties array. Instead - of appending to that directly we append to the array inside the - subsection. */ - properties = (CFMutableArrayRef)CFDictionaryGetValue( - (CFDictionaryRef)lastValue, kSecPropertyKeyValue); - } - } - - /* Finally we append the new rdn value to the property array. */ - CFStringRef label = copyLocalizedOidDescription(CFGetAllocator(properties), - rdnType); - if (label) { - appendDERThingProperty(properties, label, rdnValue); - CFRelease(label); - return errSecSuccess; - } else { - return errSecInvalidCertificate; - } -} - -static CFArrayRef createPropertiesForRDNContent(CFAllocatorRef allocator, - const DERItem *rdnSetContent) { - CFMutableArrayRef properties = CFArrayCreateMutable(allocator, 0, - &kCFTypeArrayCallBacks); - OSStatus status = parseRDNContent(rdnSetContent, properties, - appendRDNProperty); - if (status) { - CFArrayRemoveAllValues(properties); - appendInvalidProperty(properties, CFSTR("RDN"), rdnSetContent); - } - - return properties; -} - -/* - From rfc3739 - 3.1.2. Subject - - When parsing the subject here are some tips for a short name of the cert. - Choice I: commonName - Choice II: givenName - Choice III: pseudonym - - The commonName attribute value SHALL, when present, contain a name - of the subject. This MAY be in the subject's preferred - presentation format, or a format preferred by the CA, or some - other format. Pseudonyms, nicknames, and names with spelling - other than defined by the registered name MAY be used. To - understand the nature of the name presented in commonName, - complying applications MAY have to examine present values of the - givenName and surname attributes, or the pseudonym attribute. - -*/ -static CFArrayRef createPropertiesForX501NameContent(CFAllocatorRef allocator, - const DERItem *x501NameContent) { - CFMutableArrayRef properties = CFArrayCreateMutable(allocator, 0, - &kCFTypeArrayCallBacks); - OSStatus status = parseX501NameContent(x501NameContent, properties, - appendRDNProperty); - if (status) { - CFArrayRemoveAllValues(properties); - appendInvalidProperty(properties, CFSTR("X.501 Name"), x501NameContent); - } - - return properties; -} - -static CFArrayRef createPropertiesForX501Name(CFAllocatorRef allocator, - const DERItem *x501Name) { - CFMutableArrayRef properties = CFArrayCreateMutable(allocator, 0, - &kCFTypeArrayCallBacks); - OSStatus status = parseX501Name(x501Name, properties, appendRDNProperty); - if (status) { - CFArrayRemoveAllValues(properties); - appendInvalidProperty(properties, CFSTR("X.501 Name"), x501Name); - } - - return properties; -} - -static void appendIntegerProperty(CFMutableArrayRef properties, - CFStringRef label, const DERItem *integer) { - CFStringRef string = copyIntegerContentDescription( - CFGetAllocator(properties), integer); - appendPropertyP(properties, kSecPropertyTypeString, label, string); - CFRelease(string); -} - -static void appendBoolProperty(CFMutableArrayRef properties, - CFStringRef label, bool boolean) { - appendPropertyP(properties, kSecPropertyTypeString, - label, boolean ? CFSTR("Yes") : CFSTR("No")); -} - -static void appendBooleanProperty(CFMutableArrayRef properties, - CFStringRef label, const DERItem *boolean, bool defaultValue) { - bool result; - DERReturn drtn = DERParseBooleanWithDefault(boolean, defaultValue, &result); - if (drtn) { - /* Couldn't parse boolean; dump the raw unparsed data as hex. */ - appendInvalidProperty(properties, label, boolean); - } else { - appendBoolProperty(properties, label, result); - } -} - -static void appendBitStringContentNames(CFMutableArrayRef properties, - CFStringRef label, const DERItem *bitStringContent, - const CFStringRef *names, CFIndex namesCount) { - DERSize len = bitStringContent->length - 1; - require_quiet(len == 1 || len == 2, badDER); - DERByte numUnusedBits = bitStringContent->data[0]; - require_quiet(numUnusedBits < 8, badDER); - uint_fast16_t bits = 8 * len - numUnusedBits; - require_quiet(bits <= (uint_fast16_t)namesCount, badDER); - uint_fast16_t value = bitStringContent->data[1]; - uint_fast16_t mask; - if (len > 1) { - value = (value << 8) + bitStringContent->data[2]; - mask = 0x8000; - } else { - mask = 0x80; - } - uint_fast16_t ix; - bool didOne = false; - CFMutableStringRef string = - CFStringCreateMutable(CFGetAllocator(properties), 0); - for (ix = 0; ix < bits; ++ix) { - if (value & mask) { - if (didOne) { - CFStringAppend(string, CFSTR(", ")); - } else { - didOne = true; - } - CFStringAppend(string, names[ix]); - } - mask >>= 1; - } - appendPropertyP(properties, kSecPropertyTypeString, label, string); - CFRelease(string); - return; -badDER: - appendInvalidProperty(properties, label, bitStringContent); -} - -static void appendBitStringNames(CFMutableArrayRef properties, - CFStringRef label, const DERItem *bitString, - const CFStringRef *names, CFIndex namesCount) { - DERDecodedInfo bitStringContent; - DERReturn drtn = DERDecodeItem(bitString, &bitStringContent); - require_noerr_quiet(drtn, badDER); - require_quiet(bitStringContent.tag == ASN1_BIT_STRING, badDER); - appendBitStringContentNames(properties, label, &bitStringContent.content, - names, namesCount); - return; -badDER: - appendInvalidProperty(properties, label, bitString); -} - -#if 0 -typedef uint16_t SecKeyUsage; - -#define kSecKeyUsageDigitalSignature 0x8000 -#define kSecKeyUsageNonRepudiation 0x4000 -#define kSecKeyUsageKeyEncipherment 0x2000 -#define kSecKeyUsageDataEncipherment 0x1000 -#define kSecKeyUsageKeyAgreement 0x0800 -#define kSecKeyUsageKeyCertSign 0x0400 -#define kSecKeyUsageCRLSign 0x0200 -#define kSecKeyUsageEncipherOnly 0x0100 -#define kSecKeyUsageDecipherOnly 0x0080 - -/* - KeyUsage ::= BIT STRING { - digitalSignature (0), - nonRepudiation (1), - keyEncipherment (2), - dataEncipherment (3), - keyAgreement (4), - keyCertSign (5), - cRLSign (6), - encipherOnly (7), - decipherOnly (8) } - */ -static void appendKeyUsage(CFMutableArrayRef properties, - const DERItem *extnValue) { - if ((extnValue->length != 4 && extnValue->length != 5) || - extnValue->data[0] != ASN1_BIT_STRING || - extnValue->data[1] < 2 || extnValue->data[1] > 3 || - extnValue->data[2] > 7) { - appendInvalidProperty(properties, CFSTR("KeyUsage Extension"), - extnValue); - } else { - CFMutableStringRef string = - CFStringCreateMutable(CFGetAllocator(properties), 0); - SecKeyUsage usage = (extnValue->data[3] << 8); - if (extnValue->length == 5) - usage += extnValue->data[4]; - secinfo("keyusage", "keyusage: %04X", usage); - static const CFStringRef usageNames[] = { - CFSTR("Digital Signature"), - CFSTR("Non-Repudiation"), - CFSTR("Key Encipherment"), - CFSTR("Data Encipherment"), - CFSTR("Key Agreement"), - CFSTR("Cert Sign"), - CFSTR("CRL Sign"), - CFSTR("Encipher"), - CFSTR("Decipher"), - }; - bool didOne = false; - SecKeyUsage mask = kSecKeyUsageDigitalSignature; - CFIndex ix, bits = (extnValue->data[1] - 1) * 8 - extnValue->data[2]; - for (ix = 0; ix < bits; ++ix) { - if (usage & mask) { - if (didOne) { - CFStringAppend(string, CFSTR(", ")); - } else { - didOne = true; - } - /* @@@ Localize usageNames[ix]. */ - CFStringAppend(string, usageNames[ix]); - } - mask >>= 1; - } - appendPropertyP(properties, kSecPropertyTypeString, CFSTR("Usage"), - string); - CFRelease(string); - } -} -#else -static void appendKeyUsage(CFMutableArrayRef properties, - const DERItem *extnValue) { - static const CFStringRef usageNames[] = { - CFSTR("Digital Signature"), - CFSTR("Non-Repudiation"), - CFSTR("Key Encipherment"), - CFSTR("Data Encipherment"), - CFSTR("Key Agreement"), - CFSTR("Cert Sign"), - CFSTR("CRL Sign"), - CFSTR("Encipher Only"), - CFSTR("Decipher Only") - }; - appendBitStringNames(properties, CFSTR("Usage"), extnValue, - usageNames, sizeof(usageNames) / sizeof(*usageNames)); -} -#endif - -static void appendPrivateKeyUsagePeriod(CFMutableArrayRef properties, - const DERItem *extnValue) { - DERPrivateKeyUsagePeriod pkup; - DERReturn drtn = DERParseSequence(extnValue, - DERNumPrivateKeyUsagePeriodItemSpecs, DERPrivateKeyUsagePeriodItemSpecs, - &pkup, sizeof(pkup)); - require_noerr_quiet(drtn, badDER); - if (pkup.notBefore.length) { - appendDateContentProperty(properties, CFSTR("Not Valid Before"), - ASN1_GENERALIZED_TIME, &pkup.notBefore); - } - if (pkup.notAfter.length) { - appendDateContentProperty(properties, CFSTR("Not Valid After"), - ASN1_GENERALIZED_TIME, &pkup.notAfter); - } - return; -badDER: - appendInvalidProperty(properties, CFSTR("Private Key Usage Period"), - extnValue); -} - -static void appendStringContentProperty(CFMutableArrayRef properties, - CFStringRef label, const DERItem *stringContent, - CFStringEncoding encoding) { - CFStringRef string = CFStringCreateWithBytes(CFGetAllocator(properties), - stringContent->data, stringContent->length, encoding, FALSE); - if (string) { - appendPropertyP(properties, kSecPropertyTypeString, label, string); - CFRelease(string); - } else { - appendInvalidProperty(properties, label, stringContent); - } -} - -/* - OtherName ::= SEQUENCE { - type-id OBJECT IDENTIFIER, - value [0] EXPLICIT ANY DEFINED BY type-id } -*/ -static void appendOtherNameContentProperty(CFMutableArrayRef properties, - const DERItem *otherNameContent) { - DEROtherName on; - DERReturn drtn = DERParseSequenceContent(otherNameContent, - DERNumOtherNameItemSpecs, DEROtherNameItemSpecs, - &on, sizeof(on)); - require_noerr_quiet(drtn, badDER); - CFAllocatorRef allocator = CFGetAllocator(properties); - CFStringRef oid_string = copyLocalizedOidDescription(allocator, - &on.typeIdentifier); - CFStringRef value_string = copyDERThingDescription(allocator, &on.value, false); - if (value_string) - appendPropertyP(properties, kSecPropertyTypeString, oid_string, - value_string); - else - appendUnparsedProperty(properties, oid_string, &on.value); - - CFReleaseNull(value_string); - CFReleaseNull(oid_string); - return; -badDER: - appendInvalidProperty(properties, CFSTR("Other Name"), otherNameContent); -} - -/* - 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 bool appendGeneralNameContentProperty(CFMutableArrayRef properties, - DERTag tag, const DERItem *generalName) { - switch (tag) { - case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0: - appendOtherNameContentProperty(properties, generalName); - break; - case ASN1_CONTEXT_SPECIFIC | 1: - /* IA5String. */ - appendStringContentProperty(properties, CFSTR("Email Address"), - generalName, kCFStringEncodingASCII); - break; - case ASN1_CONTEXT_SPECIFIC | 2: - /* IA5String. */ - appendStringContentProperty(properties, CFSTR("DNS Name"), generalName, - kCFStringEncodingASCII); - break; - case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3: - appendUnparsedProperty(properties, CFSTR("X.400 Address"), - generalName); - break; - case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 4: - { - CFArrayRef directory_plist = - createPropertiesForX501Name(CFGetAllocator(properties), - generalName); - appendPropertyP(properties, kSecPropertyTypeSection, - CFSTR("Directory Name"), directory_plist); - CFRelease(directory_plist); - break; - } - case ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 5: - appendUnparsedProperty(properties, CFSTR("EDI Party Name"), - generalName); - 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. */ - appendURLProperty(properties, CFSTR("URI"), generalName); - break; - case ASN1_CONTEXT_SPECIFIC | 6: - appendURLContentProperty(properties, CFSTR("URI"), generalName); - break; - case ASN1_CONTEXT_SPECIFIC | 7: - appendIPAddressContentProperty(properties, CFSTR("IP Address"), - generalName); - break; - case ASN1_CONTEXT_SPECIFIC | 8: - appendOIDProperty(properties, CFSTR("Registered ID"), generalName); - break; - default: - goto badDER; - } - return true; -badDER: - return false; -} - -static void appendGeneralNameProperty(CFMutableArrayRef properties, - const DERItem *generalName) { - DERDecodedInfo generalNameContent; - DERReturn drtn = DERDecodeItem(generalName, &generalNameContent); - require_noerr_quiet(drtn, badDER); - if (appendGeneralNameContentProperty(properties, generalNameContent.tag, - &generalNameContent.content)) - return; -badDER: - appendInvalidProperty(properties, CFSTR("General Name"), generalName); -} - - -/* - GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName - */ -static void appendGeneralNamesContent(CFMutableArrayRef properties, - const DERItem *generalNamesContent) { - DERSequence gnSeq; - DERReturn drtn = DERDecodeSeqContentInit(generalNamesContent, &gnSeq); - require_noerr_quiet(drtn, badDER); - DERDecodedInfo generalNameContent; - while ((drtn = DERDecodeSeqNext(&gnSeq, &generalNameContent)) == - DR_Success) { - if (!appendGeneralNameContentProperty(properties, - generalNameContent.tag, &generalNameContent.content)) { - goto badDER; - } - } - require_quiet(drtn == DR_EndOfSequence, badDER); - return; -badDER: - appendInvalidProperty(properties, CFSTR("General Names"), - generalNamesContent); -} - -static void appendGeneralNames(CFMutableArrayRef properties, - const DERItem *generalNames) { - DERDecodedInfo generalNamesContent; - DERReturn drtn = DERDecodeItem(generalNames, &generalNamesContent); - require_noerr_quiet(drtn, badDER); - require_quiet(generalNamesContent.tag == ASN1_CONSTR_SEQUENCE, - badDER); - appendGeneralNamesContent(properties, &generalNamesContent.content); - return; -badDER: - appendInvalidProperty(properties, CFSTR("General Names"), generalNames); -} - -/* -BasicConstraints ::= SEQUENCE { - cA BOOLEAN DEFAULT FALSE, - pathLenConstraint INTEGER (0..MAX) OPTIONAL } -*/ -static void appendBasicConstraints(CFMutableArrayRef properties, - const DERItem *extnValue) { - DERBasicConstraints basicConstraints; - DERReturn drtn = DERParseSequence(extnValue, - DERNumBasicConstraintsItemSpecs, DERBasicConstraintsItemSpecs, - &basicConstraints, sizeof(basicConstraints)); - require_noerr_quiet(drtn, badDER); - - appendBooleanProperty(properties, CFSTR("Certificate Authority"), - &basicConstraints.cA, false); - - if (basicConstraints.pathLenConstraint.length != 0) { - appendIntegerProperty(properties, CFSTR("Path Length Constraint"), - &basicConstraints.pathLenConstraint); - } - return; -badDER: - appendInvalidProperty(properties, CFSTR("Basic Constraints"), extnValue); -} - -/* - CRLDistPointsSyntax ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint - - DistributionPoint ::= SEQUENCE { - distributionPoint [0] DistributionPointName OPTIONAL, - reasons [1] ReasonFlags OPTIONAL, - cRLIssuer [2] GeneralNames OPTIONAL } - - DistributionPointName ::= CHOICE { - fullName [0] GeneralNames, - nameRelativeToCRLIssuer [1] RelativeDistinguishedName } - - ReasonFlags ::= BIT STRING { - unused (0), - keyCompromise (1), - cACompromise (2), - affiliationChanged (3), - superseded (4), - cessationOfOperation (5), - certificateHold (6), - privilegeWithdrawn (7), - aACompromise (8) } -*/ -static void appendCrlDistributionPoints(CFMutableArrayRef properties, - const DERItem *extnValue) { - CFAllocatorRef allocator = CFGetAllocator(properties); - DERTag tag; - DERSequence dpSeq; - DERReturn drtn = DERDecodeSeqInit(extnValue, &tag, &dpSeq); - require_noerr_quiet(drtn, badDER); - require_quiet(tag == ASN1_CONSTR_SEQUENCE, badDER); - DERDecodedInfo dpSeqContent; - while ((drtn = DERDecodeSeqNext(&dpSeq, &dpSeqContent)) == DR_Success) { - require_quiet(dpSeqContent.tag == ASN1_CONSTR_SEQUENCE, badDER); - DERDistributionPoint dp; - drtn = DERParseSequenceContent(&dpSeqContent.content, - DERNumDistributionPointItemSpecs, - DERDistributionPointItemSpecs, - &dp, sizeof(dp)); - require_noerr_quiet(drtn, badDER); - if (dp.distributionPoint.length) { - DERDecodedInfo distributionPointName; - drtn = DERDecodeItem(&dp.distributionPoint, &distributionPointName); - require_noerr_quiet(drtn, badDER); - if (distributionPointName.tag == - (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0)) { - /* Full Name */ - appendGeneralNamesContent(properties, - &distributionPointName.content); - } else if (distributionPointName.tag == - (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1)) { - CFArrayRef rdn_props = createPropertiesForRDNContent(allocator, - &dp.reasons); - appendPropertyP(properties, kSecPropertyTypeSection, - CFSTR("Name Relative To CRL Issuer"), rdn_props); - CFRelease(rdn_props); - } else { - goto badDER; - } - } - if (dp.reasons.length) { - static const CFStringRef reasonNames[] = { - CFSTR("Unused"), - CFSTR("Key Compromise"), - CFSTR("CA Compromise"), - CFSTR("Affiliation Changed"), - CFSTR("Superseded"), - CFSTR("Cessation Of Operation"), - CFSTR("Certificate Hold"), - CFSTR("Priviledge Withdrawn"), - CFSTR("AA Compromise") - }; - appendBitStringContentNames(properties, CFSTR("Reasons"), - &dp.reasons, - reasonNames, sizeof(reasonNames) / sizeof(*reasonNames)); - } - if (dp.cRLIssuer.length) { - CFMutableArrayRef crlIssuer = CFArrayCreateMutable(allocator, 0, - &kCFTypeArrayCallBacks); - appendPropertyP(properties, kSecPropertyTypeSection, - CFSTR("CRL Issuer"), crlIssuer); - CFRelease(crlIssuer); - appendGeneralNames(crlIssuer, &dp.cRLIssuer); - } - } - require_quiet(drtn == DR_EndOfSequence, badDER); - return; -badDER: - appendInvalidProperty(properties, CFSTR("Crl Distribution Points"), - extnValue); -} - -/* Decode a sequence of integers into a comma separated list of ints. */ -static void appendIntegerSequenceContent(CFMutableArrayRef properties, - CFStringRef label, const DERItem *intSequenceContent) { - CFMutableStringRef value = NULL; - CFStringRef intDesc = NULL; - CFAllocatorRef allocator = CFGetAllocator(properties); - DERSequence intSeq; - DERReturn drtn = DERDecodeSeqContentInit(intSequenceContent, &intSeq); - require_noerr_quiet(drtn, badDER); - DERDecodedInfo intContent; - - while ((drtn = DERDecodeSeqNext(&intSeq, &intContent)) - == DR_Success) { - require_quiet(intContent.tag == ASN1_INTEGER, badDER); - intDesc = copyIntegerContentDescription( - allocator, &intContent.content); - require_quiet(intDesc, badDER); - if (value) { - CFStringAppendFormat(value, NULL, CFSTR(", %@"), intDesc); - } else { - value = CFStringCreateMutableCopy(allocator, 0, intDesc); - require_quiet(value, badDER); - } - CFReleaseNull(intDesc); - } - require_quiet(drtn == DR_EndOfSequence, badDER); - if (value) { - appendPropertyP(properties, kSecPropertyTypeString, - CFSTR("Notice Numbers"), value); - CFRelease(value); - return; - } - /* DROPTHOUGH if !value. */ -badDER: - CFReleaseNull(value); - CFReleaseNull(intDesc); - appendInvalidProperty(properties, label, intSequenceContent); -} - -static void appendCertificatePolicies(CFMutableArrayRef properties, - const DERItem *extnValue) { - CFAllocatorRef allocator = CFGetAllocator(properties); - CFStringRef piLabel = NULL, pqLabel = NULL; - DERTag tag; - DERSequence piSeq; - DERReturn drtn = DERDecodeSeqInit(extnValue, &tag, &piSeq); - require_noerr_quiet(drtn, badDER); - require_quiet(tag == ASN1_CONSTR_SEQUENCE, badDER); - DERDecodedInfo piContent; - int pin = 1; - while ((drtn = DERDecodeSeqNext(&piSeq, &piContent)) == DR_Success) { - require_quiet(piContent.tag == ASN1_CONSTR_SEQUENCE, badDER); - DERPolicyInformation pi; - drtn = DERParseSequenceContent(&piContent.content, - DERNumPolicyInformationItemSpecs, - DERPolicyInformationItemSpecs, - &pi, sizeof(pi)); - require_noerr_quiet(drtn, badDER); - require_quiet(piLabel = CFStringCreateWithFormat(allocator, NULL, - CFSTR("Policy Identifier #%d"), pin++), badDER); - appendOIDProperty(properties, piLabel, &pi.policyIdentifier); - CFReleaseNull(piLabel); - if (pi.policyQualifiers.length == 0) - continue; - - DERSequence pqSeq; - drtn = DERDecodeSeqContentInit(&pi.policyQualifiers, &pqSeq); - require_noerr_quiet(drtn, badDER); - DERDecodedInfo pqContent; - int pqn = 1; - while ((drtn = DERDecodeSeqNext(&pqSeq, &pqContent)) == DR_Success) { - DERPolicyQualifierInfo pqi; - drtn = DERParseSequenceContent(&pqContent.content, - DERNumPolicyQualifierInfoItemSpecs, - DERPolicyQualifierInfoItemSpecs, - &pqi, sizeof(pqi)); - require_noerr_quiet(drtn, badDER); - DERDecodedInfo qualifierContent; - drtn = DERDecodeItem(&pqi.qualifier, &qualifierContent); - require_noerr_quiet(drtn, badDER); - require_quiet(pqLabel = CFStringCreateWithFormat(allocator, NULL, - CFSTR("Policy Qualifier #%d"), pqn++), badDER); - appendOIDProperty(properties, pqLabel, &pqi.policyQualifierID); - CFReleaseNull(pqLabel); - if (DEROidCompare(&oidQtCps, &pqi.policyQualifierID)) { - require_quiet(qualifierContent.tag == ASN1_IA5_STRING, badDER); - appendURLContentProperty(properties, - CFSTR("CPS URI"), - &qualifierContent.content); - } else if (DEROidCompare(&oidQtUNotice, &pqi.policyQualifierID)) { - require_quiet(qualifierContent.tag == ASN1_CONSTR_SEQUENCE, badDER); - DERUserNotice un; - drtn = DERParseSequenceContent(&qualifierContent.content, - DERNumUserNoticeItemSpecs, - DERUserNoticeItemSpecs, - &un, sizeof(un)); - require_noerr_quiet(drtn, badDER); - if (un.noticeRef.length) { - DERNoticeReference nr; - drtn = DERParseSequenceContent(&un.noticeRef, - DERNumNoticeReferenceItemSpecs, - DERNoticeReferenceItemSpecs, - &nr, sizeof(nr)); - require_noerr_quiet(drtn, badDER); - appendDERThingProperty(properties, - CFSTR("Organization"), - &nr.organization); - appendIntegerSequenceContent(properties, - CFSTR("Notice Numbers"), &nr.noticeNumbers); - } - if (un.explicitText.length) { - appendDERThingProperty(properties, CFSTR("Explicit Text"), - &un.explicitText); - } - } else { - appendUnparsedProperty(properties, CFSTR("Qualifier"), - &pqi.qualifier); - } - } - require_quiet(drtn == DR_EndOfSequence, badDER); - } - require_quiet(drtn == DR_EndOfSequence, badDER); - return; -badDER: - CFReleaseNull(piLabel); - CFReleaseNull(pqLabel); - appendInvalidProperty(properties, CFSTR("Certificate Policies"), - extnValue); -} - -static void appendSubjectKeyIdentifier(CFMutableArrayRef properties, - const DERItem *extnValue) { - DERReturn drtn; - DERDecodedInfo keyIdentifier; - drtn = DERDecodeItem(extnValue, &keyIdentifier); - require_noerr_quiet(drtn, badDER); - require_quiet(keyIdentifier.tag == ASN1_OCTET_STRING, badDER); - appendDataProperty(properties, CFSTR("Key Identifier"), - &keyIdentifier.content); - - return; -badDER: - appendInvalidProperty(properties, CFSTR("Invalid Subject Key Identifier"), - extnValue); -} - -/* -AuthorityKeyIdentifier ::= SEQUENCE { - keyIdentifier [0] KeyIdentifier OPTIONAL, - authorityCertIssuer [1] GeneralNames OPTIONAL, - authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } - -- authorityCertIssuer and authorityCertSerialNumber MUST both - -- be present or both be absent - -KeyIdentifier ::= OCTET STRING -*/ -static void appendAuthorityKeyIdentifier(CFMutableArrayRef properties, - const DERItem *extnValue) { - DERAuthorityKeyIdentifier akid; - DERReturn drtn; - drtn = DERParseSequence(extnValue, - DERNumAuthorityKeyIdentifierItemSpecs, - DERAuthorityKeyIdentifierItemSpecs, - &akid, sizeof(akid)); - require_noerr_quiet(drtn, badDER); - if (akid.keyIdentifier.length) { - appendDataProperty(properties, CFSTR("Key Identifier"), - &akid.keyIdentifier); - } - if (akid.authorityCertIssuer.length || - akid.authorityCertSerialNumber.length) { - require_quiet(akid.authorityCertIssuer.length && - akid.authorityCertSerialNumber.length, badDER); - /* Perhaps put in a subsection called Authority Certificate Issuer. */ - appendGeneralNamesContent(properties, - &akid.authorityCertIssuer); - appendIntegerProperty(properties, - CFSTR("Authority Certificate Serial Number"), - &akid.authorityCertSerialNumber); - } - - return; -badDER: - appendInvalidProperty(properties, CFSTR("Authority Key Identifier"), - extnValue); -} - -/* - PolicyConstraints ::= SEQUENCE { - requireExplicitPolicy [0] SkipCerts OPTIONAL, - inhibitPolicyMapping [1] SkipCerts OPTIONAL } - - SkipCerts ::= INTEGER (0..MAX) -*/ -static void appendPolicyConstraints(CFMutableArrayRef properties, - const DERItem *extnValue) { - DERPolicyConstraints pc; - DERReturn drtn; - drtn = DERParseSequence(extnValue, - DERNumPolicyConstraintsItemSpecs, - DERPolicyConstraintsItemSpecs, - &pc, sizeof(pc)); - require_noerr_quiet(drtn, badDER); - if (pc.requireExplicitPolicy.length) { - appendIntegerProperty(properties, - CFSTR("Require Explicit Policy"), &pc.requireExplicitPolicy); - } - if (pc.inhibitPolicyMapping.length) { - appendIntegerProperty(properties, - CFSTR("Inhibit Policy Mapping"), &pc.inhibitPolicyMapping); - } - - return; - -badDER: - appendInvalidProperty(properties, CFSTR("Policy Constraints"), extnValue); -} - -/* -extendedKeyUsage EXTENSION ::= { - SYNTAX SEQUENCE SIZE (1..MAX) OF KeyPurposeId - IDENTIFIED BY id-ce-extKeyUsage } - -KeyPurposeId ::= OBJECT IDENTIFIER -*/ -static void appendExtendedKeyUsage(CFMutableArrayRef properties, - const DERItem *extnValue) { - DERTag tag; - DERSequence derSeq; - DERReturn drtn = DERDecodeSeqInit(extnValue, &tag, &derSeq); - require_noerr_quiet(drtn, badDER); - require_quiet(tag == ASN1_CONSTR_SEQUENCE, badDER); - DERDecodedInfo currDecoded; - while ((drtn = DERDecodeSeqNext(&derSeq, &currDecoded)) == DR_Success) { - require_quiet(currDecoded.tag == ASN1_OBJECT_ID, badDER); - appendOIDProperty(properties, CFSTR("Purpose"), - &currDecoded.content); - } - require_quiet(drtn == DR_EndOfSequence, badDER); - return; -badDER: - appendInvalidProperty(properties, CFSTR("Extended Key Usage"), extnValue); -} - -/* - id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 } - - AuthorityInfoAccessSyntax ::= - SEQUENCE SIZE (1..MAX) OF AccessDescription - - AccessDescription ::= SEQUENCE { - accessMethod OBJECT IDENTIFIER, - accessLocation GeneralName } - - id-ad OBJECT IDENTIFIER ::= { id-pkix 48 } - - id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 } - - id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 } -*/ -static void appendInfoAccess(CFMutableArrayRef properties, - const DERItem *extnValue) { - DERTag tag; - DERSequence adSeq; - DERReturn drtn = DERDecodeSeqInit(extnValue, &tag, &adSeq); - require_noerr_quiet(drtn, badDER); - require_quiet(tag == ASN1_CONSTR_SEQUENCE, badDER); - DERDecodedInfo adContent; - while ((drtn = DERDecodeSeqNext(&adSeq, &adContent)) == DR_Success) { - require_quiet(adContent.tag == ASN1_CONSTR_SEQUENCE, badDER); - DERAccessDescription ad; - drtn = DERParseSequenceContent(&adContent.content, - DERNumAccessDescriptionItemSpecs, - DERAccessDescriptionItemSpecs, - &ad, sizeof(ad)); - require_noerr_quiet(drtn, badDER); - appendOIDProperty(properties, CFSTR("Access Method"), - &ad.accessMethod); - //CFSTR("Access Location"); - appendGeneralNameProperty(properties, &ad.accessLocation); - } - require_quiet(drtn == DR_EndOfSequence, badDER); - return; -badDER: - appendInvalidProperty(properties, CFSTR("Authority Information Access"), - extnValue); -} - -static void appendNetscapeCertType(CFMutableArrayRef properties, - const DERItem *extnValue) { - static const CFStringRef certTypes[] = { - CFSTR("SSL client"), - CFSTR("SSL server"), - CFSTR("S/MIME"), - CFSTR("Object Signing"), - CFSTR("Reserved"), - CFSTR("SSL CA"), - CFSTR("S/MIME CA"), - CFSTR("Object Signing CA") - }; - appendBitStringNames(properties, CFSTR("Usage"), extnValue, - certTypes, sizeof(certTypes) / sizeof(*certTypes)); -} - -#if 0 -static void appendEntrustVersInfo(CFMutableArrayRef properties, - const DERItem *extnValue) { -} - -/* - * The list of Qualified Cert Statement statementIds we understand, even though - * we don't actually do anything with them; if these are found in a Qualified - * Cert Statement that's critical, we can truthfully say "yes we understand this". - */ -static const CSSM_OID_PTR knownQualifiedCertStatements[] = -{ - /* id-qcs := { id-pkix 11 } */ - (const CSSM_OID_PTR)&CSSMOID_OID_QCS_SYNTAX_V1, /* id-qcs 1 */ - (const CSSM_OID_PTR)&CSSMOID_OID_QCS_SYNTAX_V2, /* id-qcs 2 */ - (const CSSM_OID_PTR)&CSSMOID_ETSI_QCS_QC_COMPLIANCE, - (const CSSM_OID_PTR)&CSSMOID_ETSI_QCS_QC_LIMIT_VALUE, - (const CSSM_OID_PTR)&CSSMOID_ETSI_QCS_QC_RETENTION, - (const CSSM_OID_PTR)&CSSMOID_ETSI_QCS_QC_SSCD -}; -#define NUM_KNOWN_QUAL_CERT_STATEMENTS (sizeof(knownQualifiedCertStatements) / sizeof(CSSM_OID_PTR)) -*/ -static void appendQCCertStatements(CFMutableArrayRef properties, - const DERItem *extnValue) { -} - -#endif - -static bool appendPrintableDERSequenceP(CFMutableArrayRef properties, - CFStringRef label, const DERItem *sequence) { - DERTag tag; - DERSequence derSeq; - DERReturn drtn = DERDecodeSeqInit(sequence, &tag, &derSeq); - require_noerr_quiet(drtn, badSequence); - require_quiet(tag == ASN1_CONSTR_SEQUENCE, badSequence); - DERDecodedInfo currDecoded; - bool appendedSomething = false; - while ((drtn = DERDecodeSeqNext(&derSeq, &currDecoded)) == DR_Success) { - switch (currDecoded.tag) - { - case 0: // 0 - case ASN1_SEQUENCE: // 16 - case ASN1_SET: // 17 - // skip constructed object lengths - break; - - case ASN1_UTF8_STRING: // 12 - case ASN1_NUMERIC_STRING: // 18 - case ASN1_PRINTABLE_STRING: // 19 - case ASN1_T61_STRING: // 20, also ASN1_TELETEX_STRING - case ASN1_VIDEOTEX_STRING: // 21 - case ASN1_IA5_STRING: // 22 - case ASN1_GRAPHIC_STRING: // 25 - case ASN1_VISIBLE_STRING: // 26, also ASN1_ISO646_STRING - case ASN1_GENERAL_STRING: // 27 - case ASN1_UNIVERSAL_STRING: // 28 - { - CFStringRef string = - copyDERThingContentDescription(CFGetAllocator(properties), - currDecoded.tag, &currDecoded.content, false); - require_quiet(string, badSequence); - - appendPropertyP(properties, kSecPropertyTypeString, label, - string); - CFReleaseNull(string); - appendedSomething = true; - break; - } - default: - break; - } - } - require_quiet(drtn == DR_EndOfSequence, badSequence); - return appendedSomething; -badSequence: - return false; -} - -static void appendExtension(CFMutableArrayRef parent, - const SecCertificateExtension *extn) { - CFAllocatorRef allocator = CFGetAllocator(parent); - CFMutableArrayRef properties = CFArrayCreateMutable(allocator, 0, - &kCFTypeArrayCallBacks); - const DERItem - *extnID = &extn->extnID, - *extnValue = &extn->extnValue; - - appendBoolProperty(properties, CFSTR("Critical"), extn->critical); - -#if 1 - bool handled = true; - /* Extensions that we know how to handle ourselves... */ - if (extnID->length == oidSubjectKeyIdentifier.length && - !memcmp(extnID->data, oidSubjectKeyIdentifier.data, extnID->length - 1)) - { - switch (extnID->data[extnID->length - 1]) { - case 14: /* SubjectKeyIdentifier id-ce 14 */ - appendSubjectKeyIdentifier(properties, extnValue); - break; - case 15: /* KeyUsage id-ce 15 */ - appendKeyUsage(properties, extnValue); - break; - case 16: /* PrivateKeyUsagePeriod id-ce 16 */ - appendPrivateKeyUsagePeriod(properties, extnValue); - break; - case 17: /* SubjectAltName id-ce 17 */ - case 18: /* IssuerAltName id-ce 18 */ - appendGeneralNames(properties, extnValue); - break; - case 19: /* BasicConstraints id-ce 19 */ - appendBasicConstraints(properties, extnValue); - break; - case 30: /* NameConstraints id-ce 30 */ - handled = false; - break; - case 31: /* CRLDistributionPoints id-ce 31 */ - appendCrlDistributionPoints(properties, extnValue); - break; - case 32: /* CertificatePolicies id-ce 32 */ - appendCertificatePolicies(properties, extnValue); - break; - case 33: /* PolicyMappings id-ce 33 */ - handled = false; - break; - case 35: /* AuthorityKeyIdentifier id-ce 35 */ - appendAuthorityKeyIdentifier(properties, extnValue); - break; - case 36: /* PolicyConstraints id-ce 36 */ - appendPolicyConstraints(properties, extnValue); - break; - case 37: /* ExtKeyUsage id-ce 37 */ - appendExtendedKeyUsage(properties, extnValue); - break; - case 46: /* FreshestCRL id-ce 46 */ - handled = false; - break; - case 54: /* InhibitAnyPolicy id-ce 54 */ - handled = false; - break; - default: - handled = false; - break; - } - } else if (extnID->length == oidAuthorityInfoAccess.length && - !memcmp(extnID->data, oidAuthorityInfoAccess.data, extnID->length - 1)) - { - switch (extnID->data[extnID->length - 1]) { - case 1: /* AuthorityInfoAccess id-pe 1 */ - appendInfoAccess(properties, extnValue); - break; - case 3: /* QCStatements id-pe 3 */ - handled = false; - break; - case 11: /* SubjectInfoAccess id-pe 11 */ - appendInfoAccess(properties, extnValue); - break; - default: - handled = false; - break; - } - } else if (DEROidCompare(extnID, &oidNetscapeCertType)) { - /* 2.16.840.1.113730.1.1 netscape 1 1 */ - appendNetscapeCertType(properties, extnValue); - } else { - handled = false; - } - - if (!handled) { - /* Try to parse and display printable string(s). */ - if (appendPrintableDERSequenceP(properties, CFSTR("Data"), extnValue)) { - /* Nothing to do here appendPrintableDERSequenceP did the work. */ - } else { - /* Couldn't parse extension; dump the raw unparsed data as hex. */ - appendUnparsedProperty(properties, CFSTR("Data"), extnValue); - } - } -#else - /* Extensions that we know how to handle ourselves... */ - if (DEROidCompare(extnID, &oidSubjectKeyIdentifier)) { - appendSubjectKeyIdentifier(properties, extnValue); - } else if (DEROidCompare(extnID, &oidKeyUsage)) { - appendKeyUsage(properties, extnValue); - } else if (DEROidCompare(extnID, &oidPrivateKeyUsagePeriod)) { - appendPrivateKeyUsagePeriod(properties, extnValue); - } else if (DEROidCompare(extnID, &oidSubjectAltName)) { - appendGeneralNames(properties, extnValue); - } else if (DEROidCompare(extnID, &oidIssuerAltName)) { - appendGeneralNames(properties, extnValue); - } else if (DEROidCompare(extnID, &oidBasicConstraints)) { - appendBasicConstraints(properties, extnValue); - } else if (DEROidCompare(extnID, &oidCrlDistributionPoints)) { - appendCrlDistributionPoints(properties, extnValue); - } else if (DEROidCompare(extnID, &oidCertificatePolicies)) { - appendCertificatePolicies(properties, extnValue); - } else if (DEROidCompare(extnID, &oidAuthorityKeyIdentifier)) { - appendAuthorityKeyIdentifier(properties, extnValue); - } else if (DEROidCompare(extnID, &oidPolicyConstraints)) { - appendPolicyConstraints(properties, extnValue); - } else if (DEROidCompare(extnID, &oidExtendedKeyUsage)) { - appendExtendedKeyUsage(properties, extnValue); - } else if (DEROidCompare(extnID, &oidAuthorityInfoAccess)) { - appendInfoAccess(properties, extnValue); - } else if (DEROidCompare(extnID, &oidSubjectInfoAccess)) { - appendInfoAccess(properties, extnValue); - } else if (DEROidCompare(extnID, &oidNetscapeCertType)) { - appendNetscapeCertType(properties, extnValue); -#if 0 - } else if (DEROidCompare(extnID, &oidEntrustVersInfo)) { - appendEntrustVersInfo(properties, extnValue); -#endif - } else - /* Try to parse and display printable string(s). */ - if (appendPrintableDERSequenceP(properties, CFSTR("Data"), extnValue)) { - /* Nothing to do here appendPrintableDERSequenceP did the work. */ - } else { - /* Couldn't parse extension; dump the raw unparsed data as hex. */ - appendUnparsedProperty(properties, CFSTR("Data"), extnValue); - } -#endif - CFStringRef oid_string = copyLocalizedOidDescription(allocator, extnID); - appendPropertyP(parent, kSecPropertyTypeSection, oid_string, properties); - CFRelease(oid_string); - CFRelease(properties); -} - -/* Different types of summary types from least desired to most desired. */ -enum SummaryType { - kSummaryTypeNone, - kSummaryTypePrintable, - kSummaryTypeOrganizationName, - kSummaryTypeOrganizationalUnitName, - kSummaryTypeCommonName, -}; - -struct Summary { - enum SummaryType type; - CFStringRef summary; - CFStringRef description; -}; - -static OSStatus obtainSummaryFromX501Name(void *context, - const DERItem *type, const DERItem *value, CFIndex rdnIX) { - struct Summary *summary = (struct Summary *)context; - enum SummaryType stype = kSummaryTypeNone; - CFStringRef string = NULL; - if (DEROidCompare(type, &oidCommonName)) { - /* We skip Common Names that have generic values. */ - const char tfm[] = "Thawte Freemail Member"; - if ((value->length == sizeof(tfm) + 1) && - !memcmp(value->data + 2, tfm, sizeof(tfm) - 1)) { - return errSecSuccess; - } - stype = kSummaryTypeCommonName; - } else if (DEROidCompare(type, &oidOrganizationalUnitName)) { - stype = kSummaryTypeOrganizationalUnitName; - } else if (DEROidCompare(type, &oidOrganizationName)) { - stype = kSummaryTypeOrganizationName; - } else if (DEROidCompare(type, &oidDescription)) { - if (!summary->description) { - summary->description = string = copyDERThingDescription(kCFAllocatorDefault, value, true); - CFRetain(string); - } - stype = kSummaryTypePrintable; - } else { - stype = kSummaryTypePrintable; - } - - /* Use the first field we encounter of the highest priority type. */ - if (summary->type < stype) { - if (!string) { - string = copyDERThingDescription(kCFAllocatorDefault, value, true); - } - - if (string) { - CFReleaseSafe(summary->summary); - summary->summary = string; - summary->type = stype; - } - } else { - CFReleaseSafe(string); - } - - return errSecSuccess; -} - -CFStringRef SecCertificateCopySubjectSummaryP(SecCertificateRefP certificate) { - struct Summary summary = {}; - parseX501NameContent(&certificate->_subject, &summary, obtainSummaryFromX501Name); - /* If we found a description and a common name we change the summary to - CommonName (Description). */ - if (summary.description) { - if (summary.type == kSummaryTypeCommonName) { - CFStringRef newSummary = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, - CFSTR("%@ (%@)"), summary.summary, summary.description); - CFRelease(summary.summary); - summary.summary = newSummary; - } - CFRelease(summary.description); - } - - if (!summary.summary) { - /* If we didn't find a suitable printable string in the subject at all, we try - the first email address in the certificate instead. */ - CFArrayRef names = SecCertificateCopyRFC822NamesP(certificate); - if (!names) { - /* If we didn't find any email addresses in the certificate, we try finding - a DNS name instead. */ - names = SecCertificateCopyDNSNamesP(certificate); - } - if (names) { - summary.summary = CFArrayGetValueAtIndex(names, 0); - CFRetain(summary.summary); - CFRelease(names); - } - } - - return summary.summary; -} - -CFStringRef SecCertificateCopyIssuerSummaryP(SecCertificateRefP certificate) { - struct Summary summary = {}; - parseX501NameContent(&certificate->_issuer, &summary, obtainSummaryFromX501Name); - /* If we found a description and a common name we change the summary to - CommonName (Description). */ - if (summary.description) { - if (summary.type == kSummaryTypeCommonName) { - CFStringRef newSummary = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, - CFSTR("%@ (%@)"), summary.summary, summary.description); - CFRelease(summary.summary); - summary.summary = newSummary; - } - CFRelease(summary.description); - } - - return summary.summary; -} - -/* Return the earliest date on which all certificates in this chain are still - valid. */ -static CFAbsoluteTime SecCertificateGetChainsLastValidity( - SecCertificateRefP certificate) { - CFAbsoluteTime earliest = certificate->_notAfter; -#if 0 - while (certificate->_parent) { - certificate = certificate->_parent; - if (earliest > certificate->_notAfter) - earliest = certificate->_notAfter; - } -#endif - - return earliest; -} - -/* Return the latest date on which all certificates in this chain will be - valid. */ -static CFAbsoluteTime SecCertificateGetChainsFirstValidity( - SecCertificateRefP certificate) { - CFAbsoluteTime latest = certificate->_notBefore; -#if 0 - while (certificate->_parent) { - certificate = certificate->_parent; - if (latest < certificate->_notBefore) - latest = certificate->_notBefore; - } -#endif - - return latest; -} - -bool SecCertificateIsValidP(SecCertificateRefP certificate, - CFAbsoluteTime verifyTime) { - check(certificate); - return certificate->_notBefore <= verifyTime && - verifyTime <= certificate->_notAfter; -} - -CFIndex SecCertificateVersionP(SecCertificateRefP certificate) { - return certificate->_version + 1; -} - -CFAbsoluteTime SecCertificateNotValidBeforeP(SecCertificateRefP certificate) { - return certificate->_notBefore; -} - -CFAbsoluteTime SecCertificateNotValidAfterP(SecCertificateRefP certificate) { - return certificate->_notAfter; -} - -CFMutableArrayRef SecCertificateCopySummaryPropertiesP( - SecCertificateRefP certificate, CFAbsoluteTime verifyTime) { - CFAllocatorRef allocator = CFGetAllocator(certificate); - CFMutableArrayRef summary = CFArrayCreateMutable(allocator, 0, - &kCFTypeArrayCallBacks); - - /* First we put the subject summary name. */ - CFStringRef ssummary = SecCertificateCopySubjectSummaryP(certificate); - if (ssummary) { - appendPropertyP(summary, kSecPropertyTypeTitle, - NULL, ssummary); - CFRelease(ssummary); - } -#if 0 - CFStringRef isummary = CFSTR("Issuer Summary"); - appendPropertyP(summary, kSecPropertyTypeString, - CFSTR("Issued By"), isummary); - CFRelease(isummary); -#endif - - /* Let see if this certificate is currently valid. */ - CFStringRef label; - CFAbsoluteTime when; - CFStringRef message; - CFStringRef ptype; - if (verifyTime > certificate->_notAfter) { - label = CFSTR("Expired"); - when = certificate->_notAfter; - ptype = kSecPropertyTypeError; - message = CFSTR("This certificate has expired"); - } else if (certificate->_notBefore > verifyTime) { - label = CFSTR("Valid from"); - when = certificate->_notBefore; - ptype = kSecPropertyTypeError; - message = CFSTR("This certificate is not yet valid"); - } else { - CFAbsoluteTime last = SecCertificateGetChainsLastValidity(certificate); - CFAbsoluteTime first = SecCertificateGetChainsFirstValidity(certificate); - if (verifyTime > last) { - label = CFSTR("Expired"); - when = last; - ptype = kSecPropertyTypeError; - message = CFSTR("This certificate has an issuer that has expired"); - } else if (verifyTime < first) { - label = CFSTR("Valid from"); - when = first; - ptype = kSecPropertyTypeError; - message = CFSTR("This certificate has an issuer that is not yet valid"); - } else { - label = CFSTR("Expires"); - when = certificate->_notAfter; - ptype = kSecPropertyTypeSuccess; - message = CFSTR("This certificate is valid"); - } - } - - appendDateProperty(summary, label, when); - appendPropertyP(summary, ptype, NULL, message); - - return summary; -} - -CFArrayRef SecCertificateCopyPropertiesP(SecCertificateRefP certificate) { - if (!certificate->_properties) { - CFAllocatorRef allocator = CFGetAllocator(certificate); - CFMutableArrayRef properties = CFArrayCreateMutable(allocator, 0, - &kCFTypeArrayCallBacks); - require_quiet(properties, out); - - /* First we put the Subject Name in the property list. */ - CFArrayRef subject_plist = createPropertiesForX501NameContent(allocator, - &certificate->_subject); - if (subject_plist) { - appendPropertyP(properties, kSecPropertyTypeSection, - CFSTR("Subject Name"), subject_plist); - } - CFReleaseNull(subject_plist); - - /* Next we put the Issuer Name in the property list. */ - CFArrayRef issuer_plist = createPropertiesForX501NameContent(allocator, - &certificate->_issuer); - if (issuer_plist) { - appendPropertyP(properties, kSecPropertyTypeSection, - CFSTR("Issuer Name"), issuer_plist); - } - CFReleaseNull(issuer_plist); - - /* Version */ - CFStringRef versionString = CFStringCreateWithFormat(allocator, NULL, CFSTR("%d"), - certificate->_version + 1); - if (versionString) { - appendPropertyP(properties, kSecPropertyTypeString, - CFSTR("Version"), versionString); - } - CFReleaseNull(versionString); - - /* Serial Number */ - if (certificate->_serialNum.length) { - appendIntegerProperty(properties, CFSTR("Serial Number"), - &certificate->_serialNum); - } - - /* Signature algorithm. */ - appendAlgorithmProperty(properties, CFSTR("Signature Algorithm"), - &certificate->_tbsSigAlg); - - - /* Validity dates. */ - appendDateProperty(properties, CFSTR("Not Valid Before"), - certificate->_notBefore); - appendDateProperty(properties, CFSTR("Not Valid After"), - certificate->_notAfter); - - if (certificate->_subjectUniqueID.length) { - appendDataProperty(properties, CFSTR("Subject Unique ID"), - &certificate->_subjectUniqueID); - } - if (certificate->_issuerUniqueID.length) { - appendDataProperty(properties, CFSTR("Issuer Unique ID"), - &certificate->_issuerUniqueID); - } - - /* Public key algorithm. */ - appendAlgorithmProperty(properties, CFSTR("Public Key Algorithm"), - &certificate->_algId); - - /* Consider breaking down an RSA public key into modulus and - exponent? */ - appendDataProperty(properties, CFSTR("Public Key Data"), - &certificate->_pubKeyDER); - /* @@@ Key Size. */ - /* @@@ Key Usage. */ - - appendDataProperty(properties, CFSTR("Signature"), - &certificate->_signature); - - CFIndex ix; - for (ix = 0; ix < certificate->_extensionCount; ++ix) { - appendExtension(properties, &certificate->_extensions[ix]); - } - - /* @@@ Key Fingerprints. */ - - certificate->_properties = properties; - } - -out: - CFRetainSafe(certificate->_properties); - return certificate->_properties; -} - -CFDataRef SecCertificateCopySerialNumberP( - SecCertificateRefP certificate) { - if (certificate->_serialNumber) { - CFRetain(certificate->_serialNumber); - } - return certificate->_serialNumber; -} - -/* - * Accessor for normalized issuer content - */ -CFDataRef SecCertificateGetNormalizedIssuerContentP( - SecCertificateRefP certificate) { - return certificate->_normalizedIssuer; -} - -/* - * Accessor for normalized subject content - */ -CFDataRef SecCertificateGetNormalizedSubjectContentP( - SecCertificateRefP certificate) { - return certificate->_normalizedSubject; -} - -/* - * Returns DER-encoded normalized issuer sequence - * for use with SecItemCopyMatching; caller must release - */ -CFDataRef SecCertificateCopyNormalizedIssuerSequenceP( - SecCertificateRefP certificate) { - if (!certificate || !certificate->_normalizedIssuer) { - return NULL; - } - DERItem tmpdi; - tmpdi.data = (DERByte *)CFDataGetBytePtr(certificate->_normalizedIssuer); - tmpdi.length = CFDataGetLength(certificate->_normalizedIssuer); - - return SecDERItemCopySequenceP(&tmpdi); -} - -/* - * Returns DER-encoded normalized subject sequence - * for use with SecItemCopyMatching; caller must release - */ -CFDataRef SecCertificateCopyNormalizedSubjectSequenceP( - SecCertificateRefP certificate) { - if (!certificate || !certificate->_normalizedSubject) { - return NULL; - } - DERItem tmpdi; - tmpdi.data = (DERByte *)CFDataGetBytePtr(certificate->_normalizedSubject); - tmpdi.length = CFDataGetLength(certificate->_normalizedSubject); - - return SecDERItemCopySequenceP(&tmpdi); -} - -/* Verify that certificate was signed by issuerKey. */ -OSStatus SecCertificateIsSignedByP(SecCertificateRefP certificate, - SecKeyRefP issuerKey) { - /* Setup algId in SecAsn1AlgId format. */ - SecAsn1AlgId algId; - algId.algorithm.Length = certificate->_tbsSigAlg.oid.length; - algId.algorithm.Data = certificate->_tbsSigAlg.oid.data; - algId.parameters.Length = certificate->_tbsSigAlg.params.length; - algId.parameters.Data = certificate->_tbsSigAlg.params.data; - -#if 0 - OSStatus status = SecKeyDigestAndVerify(issuerKey, &algId, - certificate->_tbs.data, certificate->_tbs.length, - certificate->_signature.data, certificate->_signature.length); - if (status) { - secinfo("verify", "signature verify failed: %d", status); - return errSecNotSigner; - } -#endif - - return errSecSuccess; -} - -#if 0 -static OSStatus SecCertificateIsIssuedBy(SecCertificateRefP certificate, - SecCertificateRefP issuer, bool signatureCheckOnly) { - if (!signatureCheckOnly) { - /* It turns out we don't actually need to use normalized subject and - issuer according to rfc2459. */ - - /* If present we should check issuerID against the issuer subjectID. */ - - /* If we have an AuthorityKeyIdentifier extension that has a keyIdentifier - then we should look for a SubjectKeyIdentifier in the issuer - certificate. - If we have a authorityCertSerialNumber we can use that for chaining. - If we have a authorityCertIssuer we can use that? (or not) */ - - /* Verify that this cert was issued by issuer. Do so by chaining - either issuerID to subjectID or normalized issuer to normalized - subject. */ - CFDataRef normalizedIssuer = - SecCertificateGetNormalizedIssuerContentP(certificate); - CFDataRef normalizedIssuerSubject = - SecCertificateGetNormalizedSubjectContentP(issuer); - if (normalizedIssuer && normalizedIssuerSubject && - !CFEqual(normalizedIssuer, normalizedIssuerSubject)) - return errSecIssuerMismatch; - } - - /* Next verify that this cert was signed by issuer. */ - SecKeyRef issuerKey = SecCertificateGetPublicKey(issuer); - - /* Get the encodedDigestInfo from the digest of the subject's TBSCert */ - /* FIXME: We sould cache this (or at least the digest) until we find - a suitable issuer. */ - uint8_t signedData[DER_SHA1_DIGEST_INFO_LEN]; - CFIndex signedDataLength; - CertVerifyReturn crtn; - if (DEROidCompare(&certificate->_tbsSigAlg.oid, &oidSha1Rsa)) { - signedDataLength = DER_SHA1_DIGEST_INFO_LEN; - crtn = sha1DigestInfo(&certificate->_tbs, signedData); - } else if(DEROidCompare(&certificate->_tbsSigAlg.oid, &oidMd5Rsa)) { - signedDataLength = DER_MD_DIGEST_INFO_LEN; - crtn = mdDigestInfo(WD_MD5, &certificate->_tbs, signedData); - } else if(DEROidCompare(&certificate->_tbsSigAlg.oid, &oidMd2Rsa)) { - signedDataLength = DER_MD_DIGEST_INFO_LEN; - crtn = mdDigestInfo(WD_MD2, &certificate->_tbs, signedData); - } else { - secinfo("verify", "unsupported algorithm"); - return errSecUnsupportedAlgorithm; - } - if (crtn) { - secinfo("verify", "*DigestInfo returned: %d", crtn); - /* FIXME: Do proper error code translation. */ - return errSecUnsupportedAlgorithm; - } - - OSStatus status = SecKeyRawVerify(issuerKey, kSecPaddingPKCS1, - signedData, signedDataLength, - certificate->_signature.data, certificate->_signature.length); - if (status) { - secinfo("verify", "signature verify failed: %d", status); - return errSecNotSigner; - } - - return errSecSuccess; -} - -static OSStatus _SecCertificateSetParent(SecCertificateRefP certificate, - SecCertificateRefP issuer, bool signatureCheckOnly) { - check(issuer); - if (certificate->_parent) { - /* Setting a certificates issuer twice is only allowed if the new - issuer is equal to the current one. */ - return issuer && CFEqual(certificate->_parent, issuer); - } - -#if 0 - OSStatus status = SecCertificateIsIssuedBy(certificate, issuer, - signatureCheckOnly); -#else - OSStatus status = errSecSuccess; -#endif - if (!status) { - if (CFEqual(certificate, issuer)) { - /* We don't retain ourselves cause that would be bad mojo, - however we do record that we are properly self signed. */ - certificate->_isSelfSigned = kSecSelfSignedTrue; - secinfo("cert", "set self as parent"); - return errSecSuccess; - } - - CFRetain(issuer); - certificate->_parent = issuer; - certificate->_isSelfSigned = kSecSelfSignedFalse; - } - - return status; -} - -static bool SecCertificateIsSelfSignedP(SecCertificateRefP certificate) { - if (certificate->_isSelfSigned == kSecSelfSignedUnknown) { - certificate->_isSelfSigned = - (SecCertificateIsIssuedBy(certificate, certificate, false) ? - kSecSelfSignedTrue : kSecSelfSignedFalse); - } - - return certificate->_isSelfSigned == kSecSelfSignedTrue; -} - -/* Return true iff we were able to set our own parent from one of the - certificates in other_certificates, return false otherwise. If - signatureCheckOnly is true, we can skip the subject == issuer or - authorityKeyIdentifier tests. */ -static bool SecCertificateSetParentFrom(SecCertificateRefP certificate, - CFArrayRef other_certificates, bool signatureCheckOnly) { - CFIndex count = CFArrayGetCount(other_certificates); - CFIndex ix; - for (ix = 0; ix < count; ++ix) { - SecCertificateRefP candidate = (SecCertificateRefP) - CFArrayGetValueAtIndex(other_certificates, ix); - if (_SecCertificateSetParent(certificate, candidate, - signatureCheckOnly)) - return true; - } - return false; -} - -/* Lookup the parent of certificate in the keychain and set it. */ -static bool SecCertificateFindParent(SecCertificateRefP certificate) { - /* FIXME: Search for things other than just subject of our issuer if we - have a subjectID or authorityKeyIdentifier. */ - CFDataRef normalizedIssuer = - SecCertificateGetNormalizedIssuerContentP(certificate); - const void *keys[] = { - kSecClass, - kSecReturnRef, - kSecMatchLimit, - kSecAttrSubject - }, - *values[] = { - kSecClassCertificate, - kCFBooleanTrue, - kSecMatchLimitAll, - normalizedIssuer - }; - CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, 4, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFTypeRef results; - OSStatus status = SecItemCopyMatching(query, &results); - CFRelease(query); - if (status) { - secinfo("cert", "SecCertificateFindParent: SecItemCopyMatching: %d", - status); - return false; - } - CFArrayRef certs = (CFArrayRef)results; - /* Since we already know the certificates we are providing as candidates - have been checked for subject matching, we can ask - SecCertificateSetParentFrom to skip everything except the signature - checks. */ - bool result = SecCertificateSetParentFrom(certificate, certs, true); - CFRelease(certs); - return result; -} - -OSStatus SecCertificateCompleteChainP(SecCertificateRefP certificate, - CFArrayRef other_certificates) { - for (;;) { - if (certificate->_parent == NULL) { - if (SecCertificateIsSelfSignedP(certificate)) - return errSecSuccess; - if (!other_certificates || - !SecCertificateSetParentFrom(certificate, other_certificates,\ - false)) { - if (!SecCertificateFindParent(certificate)) - return errSecIssuerNotFound; - } - } - certificate = certificate->_parent; - } -} -#endif - -static OSStatus appendIPAddressesFromGeneralNames(void *context, - SecCEGeneralNameType gnType, const DERItem *generalName) { - CFMutableArrayRef ipAddresses = (CFMutableArrayRef)context; - if (gnType == GNT_IPAddress) { - CFStringRef string = copyIPAddressContentDescription( - kCFAllocatorDefault, generalName); - if (string) { - CFArrayAppendValue(ipAddresses, string); - CFRelease(string); - } else { - return errSecInvalidCertificate; - } - } - return errSecSuccess; -} - -CFArrayRef SecCertificateCopyIPAddressesP(SecCertificateRefP certificate) { - /* These can only exist in the subject alt name. */ - if (!certificate->_subjectAltName) - return NULL; - - CFMutableArrayRef ipAddresses = CFArrayCreateMutable(kCFAllocatorDefault, - 0, &kCFTypeArrayCallBacks); - OSStatus status = parseGeneralNames(&certificate->_subjectAltName->extnValue, - ipAddresses, appendIPAddressesFromGeneralNames); - if (status || CFArrayGetCount(ipAddresses) == 0) { - CFRelease(ipAddresses); - ipAddresses = NULL; - } - return ipAddresses; -} - -static OSStatus appendDNSNamesFromGeneralNames(void *context, SecCEGeneralNameType gnType, - const DERItem *generalName) { - CFMutableArrayRef dnsNames = (CFMutableArrayRef)context; - if (gnType == GNT_DNSName) { - CFStringRef string = CFStringCreateWithBytes(kCFAllocatorDefault, - generalName->data, generalName->length, - kCFStringEncodingUTF8, FALSE); - if (string) { - CFArrayAppendValue(dnsNames, string); - CFRelease(string); - } else { - return errSecInvalidCertificate; - } - } - return errSecSuccess; -} - -/* Return true if the passed in string matches the - Preferred name syntax from sections 2.3.1. in RFC 1035. - With the added check that we disallow empty dns names. - Also in order to support wildcard DNSNames we allow for the '*' - character anywhere in a dns component where we currently allow - a letter. - - ::= | " " - - ::=