From c1c81c87717aa51f0e1c5aaed795a8209115b4e6 Mon Sep 17 00:00:00 2001 From: liamnichols Date: Mon, 1 Sep 2014 19:18:28 +0100 Subject: [PATCH 01/10] implemented support for touch id --- SSKeychain.xcodeproj/project.pbxproj | 12 +++++++ SSKeychain/SSKeychainAccessControl.h | 51 ++++++++++++++++++++++++++++ SSKeychain/SSKeychainAccessControl.m | 50 +++++++++++++++++++++++++++ SSKeychain/SSKeychainQuery.h | 15 ++++++++ SSKeychain/SSKeychainQuery.m | 38 +++++++++++++++++++++ 5 files changed, 166 insertions(+) create mode 100644 SSKeychain/SSKeychainAccessControl.h create mode 100644 SSKeychain/SSKeychainAccessControl.m diff --git a/SSKeychain.xcodeproj/project.pbxproj b/SSKeychain.xcodeproj/project.pbxproj index 5677bf2..c2ddca9 100644 --- a/SSKeychain.xcodeproj/project.pbxproj +++ b/SSKeychain.xcodeproj/project.pbxproj @@ -7,6 +7,10 @@ objects = { /* Begin PBXBuildFile section */ + 4412CE1C1A9A372F00C35DE1 /* SSKeychainAccessControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 4412CE1A1A9A372F00C35DE1 /* SSKeychainAccessControl.h */; }; + 4412CE1D1A9A372F00C35DE1 /* SSKeychainAccessControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 4412CE1A1A9A372F00C35DE1 /* SSKeychainAccessControl.h */; }; + 4412CE1E1A9A372F00C35DE1 /* SSKeychainAccessControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 4412CE1B1A9A372F00C35DE1 /* SSKeychainAccessControl.m */; }; + 4412CE1F1A9A372F00C35DE1 /* SSKeychainAccessControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 4412CE1B1A9A372F00C35DE1 /* SSKeychainAccessControl.m */; }; E8A6665B1A844D3A00287CA3 /* SSKeychain.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8A666341A844CC400287CA3 /* SSKeychain.framework */; }; E8A666641A844DB700287CA3 /* SSKeychain.h in Headers */ = {isa = PBXBuildFile; fileRef = 21CC42EF17DB878300201DDC /* SSKeychain.h */; settings = {ATTRIBUTES = (Public, ); }; }; E8A666651A844DB700287CA3 /* SSKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = 21CC42F017DB878300201DDC /* SSKeychain.m */; }; @@ -58,6 +62,8 @@ 21CC42F117DB878300201DDC /* SSKeychainQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSKeychainQuery.h; sourceTree = ""; }; 21CC42F217DB878300201DDC /* SSKeychainQuery.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSKeychainQuery.m; sourceTree = ""; }; 21CC42F917DB87C300201DDC /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 4412CE1A1A9A372F00C35DE1 /* SSKeychainAccessControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSKeychainAccessControl.h; sourceTree = ""; }; + 4412CE1B1A9A372F00C35DE1 /* SSKeychainAccessControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSKeychainAccessControl.m; sourceTree = ""; }; E8A666341A844CC400287CA3 /* SSKeychain.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SSKeychain.framework; sourceTree = BUILT_PRODUCTS_DIR; }; E8A6664F1A844CF100287CA3 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E8A666551A844D3A00287CA3 /* SSKeychain iOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SSKeychain iOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -166,6 +172,8 @@ 21CC42F017DB878300201DDC /* SSKeychain.m */, 21CC42F117DB878300201DDC /* SSKeychainQuery.h */, 21CC42F217DB878300201DDC /* SSKeychainQuery.m */, + 4412CE1A1A9A372F00C35DE1 /* SSKeychainAccessControl.h */, + 4412CE1B1A9A372F00C35DE1 /* SSKeychainAccessControl.m */, ); path = SSKeychain; sourceTree = ""; @@ -177,6 +185,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 4412CE1C1A9A372F00C35DE1 /* SSKeychainAccessControl.h in Headers */, E8A666641A844DB700287CA3 /* SSKeychain.h in Headers */, E8A666661A844DB700287CA3 /* SSKeychainQuery.h in Headers */, ); @@ -186,6 +195,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 4412CE1D1A9A372F00C35DE1 /* SSKeychainAccessControl.h in Headers */, E8A6668A1A844E5400287CA3 /* SSKeychain.h in Headers */, E8A6668C1A844E5400287CA3 /* SSKeychainQuery.h in Headers */, ); @@ -341,6 +351,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4412CE1E1A9A372F00C35DE1 /* SSKeychainAccessControl.m in Sources */, E8A666671A844DB700287CA3 /* SSKeychainQuery.m in Sources */, E8A666651A844DB700287CA3 /* SSKeychain.m in Sources */, ); @@ -358,6 +369,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4412CE1F1A9A372F00C35DE1 /* SSKeychainAccessControl.m in Sources */, E8A6668D1A844E5400287CA3 /* SSKeychainQuery.m in Sources */, E8A6668B1A844E5400287CA3 /* SSKeychain.m in Sources */, ); diff --git a/SSKeychain/SSKeychainAccessControl.h b/SSKeychain/SSKeychainAccessControl.h new file mode 100644 index 0000000..98df58e --- /dev/null +++ b/SSKeychain/SSKeychainAccessControl.h @@ -0,0 +1,51 @@ +// +// SSKeychainAccessControl.h +// SSKeychain +// +// Created by Liam Nichols on 01/09/2014. +// Copyright (c) 2014 Sam Soffes. All rights reserved. +// + +#import + +/** kSecAttrAccessible */ +typedef NS_ENUM(NSUInteger, SSKeychainAccessibility) { + /** kSecAttrAccessibleWhenUnlocked */ + SSKeychainAccessibilityWhenUnlocked = 1, + + /** kSecAttrAccessibleAfterFirstUnlock */ + SSKeychainAccessibilityAfterFirstUnlock, + + /** kSecAttrAccessibleAlways */ + SSKeychainAccessibilityAlways, + + /** kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly */ + SSKeychainAccessibilityWhenPasscodeSetThisDeviceOnly, + + /** kSecAttrAccessibleWhenUnlockedThisDeviceOnly */ + SSKeychainAccessibilityWhenUnlockedThisDeviceOnly, + + /** kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly */ + SSKeychainAccessibilityAfterFisrtUnlockThisDeviceOnly, + + /** kSecAttrAccessibleAlwaysThisDeviceOnly */ + SSKeychainAccessibilityAlwaysThisDeviceOnly +}; + +/** SecAccessControlCreateFlags */ +typedef NS_ENUM(NSInteger, SSKeychainCreateFlags) { + /** kSecAccessControlUserPresence */ + SSKeychainCreateFlagUserPresence = 1 << 0 +}; + +extern CFTypeRef getSecAttrAccessibility(SSKeychainAccessibility ssAttr); + +@interface SSKeychainAccessControl : NSObject + ++ (instancetype)accessControlWithAccessibility:(SSKeychainAccessibility)accesibility flags:(SSKeychainCreateFlags)flags; + +@property (nonatomic, assign) SSKeychainAccessibility accessibility; + +@property (nonatomic, assign) SSKeychainCreateFlags flags; + +@end diff --git a/SSKeychain/SSKeychainAccessControl.m b/SSKeychain/SSKeychainAccessControl.m new file mode 100644 index 0000000..f845f31 --- /dev/null +++ b/SSKeychain/SSKeychainAccessControl.m @@ -0,0 +1,50 @@ +// +// SSKeychainAccessControl.m +// SSKeychain +// +// Created by Liam Nichols on 01/09/2014. +// Copyright (c) 2014 Sam Soffes. All rights reserved. +// + +#import "SSKeychainAccessControl.h" + +@implementation SSKeychainAccessControl + ++ (instancetype)accessControlWithAccessibility:(SSKeychainAccessibility)accesibility flags:(SSKeychainCreateFlags)flags +{ + SSKeychainAccessControl *accessControl = [self new]; + accessControl.accessibility = accesibility; + accessControl.flags = flags; + return accessControl; +} + +@end + +CFTypeRef getSecAttrAccessibility(SSKeychainAccessibility ssAttr) +{ + switch (ssAttr) { + case SSKeychainAccessibilityAlways: + return kSecAttrAccessibleAlways; + + case SSKeychainAccessibilityWhenUnlocked: + return kSecAttrAccessibleWhenUnlocked; + + case SSKeychainAccessibilityAfterFirstUnlock: + return kSecAttrAccessibleAfterFirstUnlock; + + case SSKeychainAccessibilityAlwaysThisDeviceOnly: + return kSecAttrAccessibleAlwaysThisDeviceOnly; + + case SSKeychainAccessibilityWhenUnlockedThisDeviceOnly: + return kSecAttrAccessibleWhenUnlockedThisDeviceOnly; + + case SSKeychainAccessibilityWhenPasscodeSetThisDeviceOnly: + return kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly; + + case SSKeychainAccessibilityAfterFisrtUnlockThisDeviceOnly: + return kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly; + + default: + return NULL; + } +} diff --git a/SSKeychain/SSKeychainQuery.h b/SSKeychain/SSKeychainQuery.h index f0579e1..a7a1f94 100644 --- a/SSKeychain/SSKeychainQuery.h +++ b/SSKeychain/SSKeychainQuery.h @@ -9,6 +9,10 @@ @import Foundation; @import Security; +#if __IPHONE_8_0 || __MAC_10_10 + #import "SSKeychainAccessControl.h" +#endif + #if __IPHONE_7_0 || __MAC_10_9 // Keychain synchronization available at compile time #define SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE 1 @@ -46,6 +50,17 @@ typedef NS_ENUM(NSUInteger, SSKeychainQuerySynchronizationMode) { @property (nonatomic) SSKeychainQuerySynchronizationMode synchronizationMode; #endif +#if __IPHONE_8_0 || __MAC_10_10 +/** kSecUseOperationPrompt */ +@property (nonatomic, copy) NSString *useOperationPrompt; + +/** kSecUseNoAuthenticationUI */ +@property (nonatomic, assign) NSNumber *useNoAuthenticationUI; + +/** kSecAttrAccessControl */ +@property (nonatomic, strong) SSKeychainAccessControl *accessControl; +#endif + /** Root storage for password information */ @property (nonatomic, copy) NSData *passwordData; diff --git a/SSKeychain/SSKeychainQuery.m b/SSKeychain/SSKeychainQuery.m index 70ee516..e734fe3 100644 --- a/SSKeychain/SSKeychainQuery.m +++ b/SSKeychain/SSKeychainQuery.m @@ -48,6 +48,31 @@ - (BOOL)save:(NSError *__autoreleasing *)error { [query setObject:(__bridge id)accessibilityType forKey:(__bridge id)kSecAttrAccessible]; } #endif + +#if __IPHONE_8_0 || __MAC_10_10 + if (self.useNoAuthenticationUI) { + [query setObject:self.useNoAuthenticationUI forKey:(__bridge id)kSecUseNoAuthenticationUI]; + } + if (self.accessControl) { + CFErrorRef sacError = NULL; + SecAccessControlRef sacObject; + + sacObject = SecAccessControlCreateWithFlags(kCFAllocatorDefault, + getSecAttrAccessibility(self.accessControl.accessibility), + (CFIndex)self.accessControl.flags, + &sacError); + + if (sacObject == NULL || sacError != NULL) { + if (error) { + *error = (__bridge NSError *)sacError; + } + return NO; + } + + [query setObject:(__bridge id)sacObject forKey:(__bridge id)kSecAttrAccessControl]; + } +#endif + status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); if (status != errSecSuccess && error != NULL) { @@ -94,6 +119,12 @@ - (NSArray *)fetchAll:(NSError *__autoreleasing *)error { [query setObject:@YES forKey:(__bridge id)kSecReturnAttributes]; [query setObject:(__bridge id)kSecMatchLimitAll forKey:(__bridge id)kSecMatchLimit]; +#if __IPHONE_8_0 || __MAC_10_10 + if (self.useOperationPrompt) { + [query setObject:self.useOperationPrompt forKey:(__bridge id)kSecUseOperationPrompt]; + } +#endif + CFTypeRef result = NULL; status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); if (status != errSecSuccess && error != NULL) { @@ -118,6 +149,13 @@ - (BOOL)fetch:(NSError *__autoreleasing *)error { NSMutableDictionary *query = [self query]; [query setObject:@YES forKey:(__bridge id)kSecReturnData]; [query setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; + +#if __IPHONE_8_0 || __MAC_10_10 + if (self.useOperationPrompt) { + [query setObject:self.useOperationPrompt forKey:(__bridge id)kSecUseOperationPrompt]; + } +#endif + status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); if (status != errSecSuccess) { From 0965e35bdd2324123b04a2c9a8003828b21feeb8 Mon Sep 17 00:00:00 2001 From: liamnichols Date: Mon, 1 Sep 2014 19:27:36 +0100 Subject: [PATCH 02/10] added update query --- SSKeychain/SSKeychainQuery.h | 11 ++++++++++- SSKeychain/SSKeychainQuery.m | 38 ++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/SSKeychain/SSKeychainQuery.h b/SSKeychain/SSKeychainQuery.h index a7a1f94..3890b9a 100644 --- a/SSKeychain/SSKeychainQuery.h +++ b/SSKeychain/SSKeychainQuery.h @@ -78,7 +78,7 @@ typedef NS_ENUM(NSUInteger, SSKeychainQuerySynchronizationMode) { ///------------------------ -/// @name Saving & Deleting +/// @name Saving, Updating & Deleting ///------------------------ /** @@ -91,6 +91,15 @@ typedef NS_ENUM(NSUInteger, SSKeychainQuerySynchronizationMode) { */ - (BOOL)save:(NSError **)error; +/** + Updates the receiver's attributes. + + @param error Populated should an error occur. + + @return `YES` if saving was successful, `NO` otherwise. + */ +- (BOOL)update:(NSError **)error; + /** Delete keychain items that match the given account, service, and access group. diff --git a/SSKeychain/SSKeychainQuery.m b/SSKeychain/SSKeychainQuery.m index e734fe3..ee548fe 100644 --- a/SSKeychain/SSKeychainQuery.m +++ b/SSKeychain/SSKeychainQuery.m @@ -82,6 +82,44 @@ - (BOOL)save:(NSError *__autoreleasing *)error { return (status == errSecSuccess); } +- (BOOL)update:(NSError *__autoreleasing *)error +{ + OSStatus status = SSKeychainErrorBadArguments; + if (!self.service || !self.account || !self.passwordData) { + if (error) { + *error = [[self class] errorWithCode:status]; + } + return NO; + } + + NSMutableDictionary *query = [self query]; + NSMutableDictionary *changes = [NSMutableDictionary dictionary]; + + [changes setObject:self.passwordData forKey:(__bridge id)kSecValueData]; + if (self.label) { + [changes setObject:self.label forKey:(__bridge id)kSecAttrLabel]; + } +#if __IPHONE_4_0 && TARGET_OS_IPHONE + CFTypeRef accessibilityType = [SSKeychain accessibilityType]; + if (accessibilityType) { + [changes setObject:(__bridge id)accessibilityType forKey:(__bridge id)kSecAttrAccessible]; + } +#endif + +#if __IPHONE_8_0 || __MAC_10_10 + if (self.useOperationPrompt) { + [changes setObject:self.useOperationPrompt forKey:(__bridge id)kSecUseOperationPrompt]; + } +#endif + + status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)changes); + + if (status != errSecSuccess && error != NULL) { + *error = [[self class] errorWithCode:status]; + } + + return (status == errSecSuccess); +} - (BOOL)deleteItem:(NSError *__autoreleasing *)error { OSStatus status = SSKeychainErrorBadArguments; From eac8011afd96692ad210bbcf97e8ba280e4fd274 Mon Sep 17 00:00:00 2001 From: Liam Nichols Date: Tue, 2 Sep 2014 16:57:34 +0100 Subject: [PATCH 03/10] Update SSKeychainQuery.m --- SSKeychain/SSKeychainQuery.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SSKeychain/SSKeychainQuery.m b/SSKeychain/SSKeychainQuery.m index ee548fe..08116bc 100644 --- a/SSKeychain/SSKeychainQuery.m +++ b/SSKeychain/SSKeychainQuery.m @@ -108,7 +108,7 @@ - (BOOL)update:(NSError *__autoreleasing *)error #if __IPHONE_8_0 || __MAC_10_10 if (self.useOperationPrompt) { - [changes setObject:self.useOperationPrompt forKey:(__bridge id)kSecUseOperationPrompt]; + [query setObject:self.useOperationPrompt forKey:(__bridge id)kSecUseOperationPrompt]; } #endif From 84d8dbeb4c55a8bc7e15fb1f5de31718a5996578 Mon Sep 17 00:00:00 2001 From: Rich Hodgkins Date: Sat, 10 Jan 2015 14:08:18 +0000 Subject: [PATCH 04/10] Correct enum for keychain create flags `SSKeychainCreateFlags` should use `NS_OPTIONS` not `NS_ENUM` so it can be correctly converted in Swift. --- SSKeychain/SSKeychainAccessControl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SSKeychain/SSKeychainAccessControl.h b/SSKeychain/SSKeychainAccessControl.h index 98df58e..39d1a81 100644 --- a/SSKeychain/SSKeychainAccessControl.h +++ b/SSKeychain/SSKeychainAccessControl.h @@ -33,9 +33,9 @@ typedef NS_ENUM(NSUInteger, SSKeychainAccessibility) { }; /** SecAccessControlCreateFlags */ -typedef NS_ENUM(NSInteger, SSKeychainCreateFlags) { +typedef NS_OPTIONS(NSUInteger, SSKeychainCreateFlags) { /** kSecAccessControlUserPresence */ - SSKeychainCreateFlagUserPresence = 1 << 0 + SSKeychainCreateFlagUserPresence = 1UL << 0 }; extern CFTypeRef getSecAttrAccessibility(SSKeychainAccessibility ssAttr); From b85fda9d19e07065ac842f18ca5c7af77f941544 Mon Sep 17 00:00:00 2001 From: Rich Hodgkins Date: Sun, 22 Feb 2015 16:19:08 +0000 Subject: [PATCH 05/10] Marked access control header as Public as this was added after the recent framework refactor. Also changed to use @import. --- SSKeychain.xcodeproj/project.pbxproj | 4 ++-- SSKeychain/SSKeychainAccessControl.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/SSKeychain.xcodeproj/project.pbxproj b/SSKeychain.xcodeproj/project.pbxproj index c2ddca9..71081fa 100644 --- a/SSKeychain.xcodeproj/project.pbxproj +++ b/SSKeychain.xcodeproj/project.pbxproj @@ -7,8 +7,8 @@ objects = { /* Begin PBXBuildFile section */ - 4412CE1C1A9A372F00C35DE1 /* SSKeychainAccessControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 4412CE1A1A9A372F00C35DE1 /* SSKeychainAccessControl.h */; }; - 4412CE1D1A9A372F00C35DE1 /* SSKeychainAccessControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 4412CE1A1A9A372F00C35DE1 /* SSKeychainAccessControl.h */; }; + 4412CE1C1A9A372F00C35DE1 /* SSKeychainAccessControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 4412CE1A1A9A372F00C35DE1 /* SSKeychainAccessControl.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4412CE1D1A9A372F00C35DE1 /* SSKeychainAccessControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 4412CE1A1A9A372F00C35DE1 /* SSKeychainAccessControl.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4412CE1E1A9A372F00C35DE1 /* SSKeychainAccessControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 4412CE1B1A9A372F00C35DE1 /* SSKeychainAccessControl.m */; }; 4412CE1F1A9A372F00C35DE1 /* SSKeychainAccessControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 4412CE1B1A9A372F00C35DE1 /* SSKeychainAccessControl.m */; }; E8A6665B1A844D3A00287CA3 /* SSKeychain.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8A666341A844CC400287CA3 /* SSKeychain.framework */; }; diff --git a/SSKeychain/SSKeychainAccessControl.h b/SSKeychain/SSKeychainAccessControl.h index 39d1a81..eb139c9 100644 --- a/SSKeychain/SSKeychainAccessControl.h +++ b/SSKeychain/SSKeychainAccessControl.h @@ -6,7 +6,7 @@ // Copyright (c) 2014 Sam Soffes. All rights reserved. // -#import +@import Foundation; /** kSecAttrAccessible */ typedef NS_ENUM(NSUInteger, SSKeychainAccessibility) { From 3e7a31b31e3a8b8f6c202ce337a16865b4b54204 Mon Sep 17 00:00:00 2001 From: Rich Hodgkins Date: Sun, 22 Feb 2015 16:39:55 +0000 Subject: [PATCH 06/10] Added #define and method for compile and runtime checking to see if access control is available, matching the system used for checking is synchronization is available --- SSKeychain/SSKeychainQuery.h | 26 ++++++++++++++++++++++++-- SSKeychain/SSKeychainQuery.m | 29 +++++++++++++++++++++++++---- 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/SSKeychain/SSKeychainQuery.h b/SSKeychain/SSKeychainQuery.h index 3890b9a..6619ee3 100644 --- a/SSKeychain/SSKeychainQuery.h +++ b/SSKeychain/SSKeychainQuery.h @@ -10,6 +10,10 @@ @import Security; #if __IPHONE_8_0 || __MAC_10_10 + #define SSKEYCHAIN_ACCESS_CONTROL_AVAILABLE 1 +#endif + +#ifdef SSKEYCHAIN_ACCESS_CONTROL_AVAILABLE #import "SSKeychainAccessControl.h" #endif @@ -50,13 +54,15 @@ typedef NS_ENUM(NSUInteger, SSKeychainQuerySynchronizationMode) { @property (nonatomic) SSKeychainQuerySynchronizationMode synchronizationMode; #endif -#if __IPHONE_8_0 || __MAC_10_10 +#if __IPHONE_8_0 && TARGET_OS_IPHONE /** kSecUseOperationPrompt */ @property (nonatomic, copy) NSString *useOperationPrompt; /** kSecUseNoAuthenticationUI */ @property (nonatomic, assign) NSNumber *useNoAuthenticationUI; +#endif +#if SSKEYCHAIN_ACCESS_CONTROL_AVAILABLE /** kSecAttrAccessControl */ @property (nonatomic, strong) SSKeychainAccessControl *accessControl; #endif @@ -145,7 +151,7 @@ typedef NS_ENUM(NSUInteger, SSKeychainQuerySynchronizationMode) { #ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE /** - Returns a boolean indicating if keychain synchronization is available on the device at runtime. The #define + Returns a boolean indicating if keychain synchronization is available on the device at runtime. The #define SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE is only for compile time. If you are checking for the presence of synchronization, you should use this method. @@ -154,4 +160,20 @@ typedef NS_ENUM(NSUInteger, SSKeychainQuerySynchronizationMode) { + (BOOL)isSynchronizationAvailable; #endif + +///----------------------------- +/// @name Access Control Status +///----------------------------- + +#ifdef SSKEYCHAIN_ACCESS_CONTROL_AVAILABLE +/** + Returns a boolean indicating if keychain access control is available on the device at runtime. The #define + SSKEYCHAIN_ACCESS_CONTROL_AVAILABLE is only for compile time. If you are checking for the presence of access control, + you should use this method. + + @return A value indicating if keychain access control is available + */ ++ (BOOL)isAccessControlAvailable; +#endif + @end diff --git a/SSKeychain/SSKeychainQuery.m b/SSKeychain/SSKeychainQuery.m index 08116bc..80c38b4 100644 --- a/SSKeychain/SSKeychainQuery.m +++ b/SSKeychain/SSKeychainQuery.m @@ -20,6 +20,10 @@ @implementation SSKeychainQuery @synthesize accessGroup = _accessGroup; #endif +#ifdef SSKEYCHAIN_ACCESS_CONTROL_AVAILABLE +@synthesize accessControl = _accessControl; +#endif + #ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE @synthesize synchronizationMode = _synchronizationMode; #endif @@ -49,10 +53,12 @@ - (BOOL)save:(NSError *__autoreleasing *)error { } #endif -#if __IPHONE_8_0 || __MAC_10_10 +#if __IPHONE_8_0 && TARGET_OS_IPHONE if (self.useNoAuthenticationUI) { [query setObject:self.useNoAuthenticationUI forKey:(__bridge id)kSecUseNoAuthenticationUI]; } +#endif +#if SSKEYCHAIN_ACCESS_CONTROL_AVAILABLE if (self.accessControl) { CFErrorRef sacError = NULL; SecAccessControlRef sacObject; @@ -106,7 +112,7 @@ - (BOOL)update:(NSError *__autoreleasing *)error } #endif -#if __IPHONE_8_0 || __MAC_10_10 +#if __IPHONE_8_0 && TARGET_OS_IPHONE if (self.useOperationPrompt) { [query setObject:self.useOperationPrompt forKey:(__bridge id)kSecUseOperationPrompt]; } @@ -157,7 +163,7 @@ - (NSArray *)fetchAll:(NSError *__autoreleasing *)error { [query setObject:@YES forKey:(__bridge id)kSecReturnAttributes]; [query setObject:(__bridge id)kSecMatchLimitAll forKey:(__bridge id)kSecMatchLimit]; -#if __IPHONE_8_0 || __MAC_10_10 +#if __IPHONE_8_0 && TARGET_OS_IPHONE if (self.useOperationPrompt) { [query setObject:self.useOperationPrompt forKey:(__bridge id)kSecUseOperationPrompt]; } @@ -188,7 +194,7 @@ - (BOOL)fetch:(NSError *__autoreleasing *)error { [query setObject:@YES forKey:(__bridge id)kSecReturnData]; [query setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; -#if __IPHONE_8_0 || __MAC_10_10 +#if __IPHONE_8_0 && TARGET_OS_IPHONE if (self.useOperationPrompt) { [query setObject:self.useOperationPrompt forKey:(__bridge id)kSecUseOperationPrompt]; } @@ -251,6 +257,21 @@ + (BOOL)isSynchronizationAvailable { #endif +#pragma mark - Access Control Status + +#ifdef SSKEYCHAIN_ACCESS_CONTROL_AVAILABLE ++ (BOOL)isAccessControlAvailable { +#if TARGET_OS_IPHONE + // Apple suggested way to check for 8.0 at runtime + // https://developer.apple.com/library/ios/documentation/userexperience/conceptual/transitionguide/SupportingEarlieriOS.html + return floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1; +#else + return floor(NSFoundationVersionNumber) > NSFoundationVersionNumber10_9_2; +#endif +} +#endif + + #pragma mark - Private - (NSMutableDictionary *)query { From 9d93c8b90687b4a768df19b8ae31dd2a8a2a4a1a Mon Sep 17 00:00:00 2001 From: Rich Hodgkins Date: Sun, 22 Feb 2015 16:42:09 +0000 Subject: [PATCH 07/10] Changed header import to non-user header type and added @import to access control header --- SSKeychain/SSKeychainAccessControl.h | 1 + SSKeychain/SSKeychainQuery.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/SSKeychain/SSKeychainAccessControl.h b/SSKeychain/SSKeychainAccessControl.h index eb139c9..a34eaf3 100644 --- a/SSKeychain/SSKeychainAccessControl.h +++ b/SSKeychain/SSKeychainAccessControl.h @@ -7,6 +7,7 @@ // @import Foundation; +@import Security; /** kSecAttrAccessible */ typedef NS_ENUM(NSUInteger, SSKeychainAccessibility) { diff --git a/SSKeychain/SSKeychainQuery.h b/SSKeychain/SSKeychainQuery.h index 6619ee3..63608bc 100644 --- a/SSKeychain/SSKeychainQuery.h +++ b/SSKeychain/SSKeychainQuery.h @@ -14,7 +14,7 @@ #endif #ifdef SSKEYCHAIN_ACCESS_CONTROL_AVAILABLE - #import "SSKeychainAccessControl.h" + #import #endif #if __IPHONE_7_0 || __MAC_10_9 From 84ca924f9ec014515bcbb6f520c32c2593fcac08 Mon Sep 17 00:00:00 2001 From: Rich Hodgkins Date: Sun, 22 Feb 2015 16:43:44 +0000 Subject: [PATCH 08/10] Fixed Xcode warning about SSKeychain.strings being imported as UTF-8, while it actually contains UTF-16 --- SSKeychain.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SSKeychain.xcodeproj/project.pbxproj b/SSKeychain.xcodeproj/project.pbxproj index 71081fa..211a496 100644 --- a/SSKeychain.xcodeproj/project.pbxproj +++ b/SSKeychain.xcodeproj/project.pbxproj @@ -56,7 +56,7 @@ 21CC42AE17DB874300201DDC /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 21CC42C317DB874300201DDC /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 21CC42DB17DB877900201DDC /* SSKeychainTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSKeychainTests.m; sourceTree = ""; }; - 21CC42EE17DB878300201DDC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/SSKeychain.strings; sourceTree = ""; }; + 21CC42EE17DB878300201DDC /* en */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/SSKeychain.strings; sourceTree = ""; }; 21CC42EF17DB878300201DDC /* SSKeychain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSKeychain.h; sourceTree = ""; }; 21CC42F017DB878300201DDC /* SSKeychain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSKeychain.m; sourceTree = ""; }; 21CC42F117DB878300201DDC /* SSKeychainQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSKeychainQuery.h; sourceTree = ""; }; From f7ca23ec7b3df8bc6769ed2bc442380445cc6f77 Mon Sep 17 00:00:00 2001 From: Rich Hodgkins Date: Sun, 22 Feb 2015 16:54:49 +0000 Subject: [PATCH 09/10] Added Travis CI config file and setup to run tests --- .travis.yml | 4 ++ Readme.markdown | 2 +- SSKeychain.xcodeproj/project.pbxproj | 68 +++++++++++++++------------- 3 files changed, 41 insertions(+), 33 deletions(-) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..a3badee --- /dev/null +++ b/.travis.yml @@ -0,0 +1,4 @@ +language: objective-c +script: + - xcodebuild -project SSKeychain.xcodeproj -scheme "SSKeychain iOS" clean build test + - xcodebuild -project SSKeychain.xcodeproj -scheme "SSKeychain Mac" -configuration Debug clean build test \ No newline at end of file diff --git a/Readme.markdown b/Readme.markdown index 52b369e..0f128c2 100644 --- a/Readme.markdown +++ b/Readme.markdown @@ -1,4 +1,4 @@ -# SSKeychain +# SSKeychain [![Build Status](https://travis-ci.org/soffes/sskeychain.svg?branch=travis)](https://travis-ci.org/soffes/sskeychain) SSKeychain is a simple wrapper for accessing accounts, getting passwords, setting passwords, and deleting passwords using the system Keychain on Mac OS X and iOS. diff --git a/SSKeychain.xcodeproj/project.pbxproj b/SSKeychain.xcodeproj/project.pbxproj index 211a496..f89327e 100644 --- a/SSKeychain.xcodeproj/project.pbxproj +++ b/SSKeychain.xcodeproj/project.pbxproj @@ -11,6 +11,11 @@ 4412CE1D1A9A372F00C35DE1 /* SSKeychainAccessControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 4412CE1A1A9A372F00C35DE1 /* SSKeychainAccessControl.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4412CE1E1A9A372F00C35DE1 /* SSKeychainAccessControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 4412CE1B1A9A372F00C35DE1 /* SSKeychainAccessControl.m */; }; 4412CE1F1A9A372F00C35DE1 /* SSKeychainAccessControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 4412CE1B1A9A372F00C35DE1 /* SSKeychainAccessControl.m */; }; + 4412CE3A1A9A4C3000C35DE1 /* SSKeychain.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8A6666F1A844E4100287CA3 /* SSKeychain.framework */; }; + 4412CE401A9A50A800C35DE1 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4412CE3F1A9A50A800C35DE1 /* Security.framework */; }; + 4412CE421A9A50AE00C35DE1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4412CE411A9A50AE00C35DE1 /* Foundation.framework */; }; + 4412CE441A9A50B400C35DE1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4412CE431A9A50B400C35DE1 /* Foundation.framework */; }; + 4412CE4C1A9A527200C35DE1 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4412CE451A9A50B700C35DE1 /* Security.framework */; }; E8A6665B1A844D3A00287CA3 /* SSKeychain.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8A666341A844CC400287CA3 /* SSKeychain.framework */; }; E8A666641A844DB700287CA3 /* SSKeychain.h in Headers */ = {isa = PBXBuildFile; fileRef = 21CC42EF17DB878300201DDC /* SSKeychain.h */; settings = {ATTRIBUTES = (Public, ); }; }; E8A666651A844DB700287CA3 /* SSKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = 21CC42F017DB878300201DDC /* SSKeychain.m */; }; @@ -18,7 +23,6 @@ E8A666671A844DB700287CA3 /* SSKeychainQuery.m in Sources */ = {isa = PBXBuildFile; fileRef = 21CC42F217DB878300201DDC /* SSKeychainQuery.m */; }; E8A666681A844DBA00287CA3 /* SSKeychain.strings in Resources */ = {isa = PBXBuildFile; fileRef = 21CC42ED17DB878300201DDC /* SSKeychain.strings */; }; E8A666691A844E0500287CA3 /* SSKeychainTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 21CC42DB17DB877900201DDC /* SSKeychainTests.m */; }; - E8A6667A1A844E4100287CA3 /* SSKeychain.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8A6666F1A844E4100287CA3 /* SSKeychain.framework */; }; E8A6668A1A844E5400287CA3 /* SSKeychain.h in Headers */ = {isa = PBXBuildFile; fileRef = 21CC42EF17DB878300201DDC /* SSKeychain.h */; settings = {ATTRIBUTES = (Public, ); }; }; E8A6668B1A844E5400287CA3 /* SSKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = 21CC42F017DB878300201DDC /* SSKeychain.m */; }; E8A6668C1A844E5400287CA3 /* SSKeychainQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = 21CC42F117DB878300201DDC /* SSKeychainQuery.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -45,25 +49,19 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 21B85B1E18EC9391009D2B98 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; - 21B85B2518EC9455009D2B98 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = Library/Frameworks/Cocoa.framework; sourceTree = DEVELOPER_DIR; }; - 21B85B2818EC9455009D2B98 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; - 21B85B2918EC9455009D2B98 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; - 21B85B2A18EC9455009D2B98 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 21B85B6E18EC963A009D2B98 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/Cocoa.framework; sourceTree = DEVELOPER_DIR; }; - 21CC42AA17DB874300201DDC /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 21CC42AC17DB874300201DDC /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - 21CC42AE17DB874300201DDC /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 21CC42C317DB874300201DDC /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 21CC42DB17DB877900201DDC /* SSKeychainTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSKeychainTests.m; sourceTree = ""; }; 21CC42EE17DB878300201DDC /* en */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/SSKeychain.strings; sourceTree = ""; }; 21CC42EF17DB878300201DDC /* SSKeychain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSKeychain.h; sourceTree = ""; }; 21CC42F017DB878300201DDC /* SSKeychain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSKeychain.m; sourceTree = ""; }; 21CC42F117DB878300201DDC /* SSKeychainQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSKeychainQuery.h; sourceTree = ""; }; 21CC42F217DB878300201DDC /* SSKeychainQuery.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSKeychainQuery.m; sourceTree = ""; }; - 21CC42F917DB87C300201DDC /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; 4412CE1A1A9A372F00C35DE1 /* SSKeychainAccessControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSKeychainAccessControl.h; sourceTree = ""; }; 4412CE1B1A9A372F00C35DE1 /* SSKeychainAccessControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSKeychainAccessControl.m; sourceTree = ""; }; + 4412CE201A9A400400C35DE1 /* .travis.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = .travis.yml; sourceTree = ""; usesTabs = 0; }; + 4412CE3F1A9A50A800C35DE1 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 4412CE411A9A50AE00C35DE1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 4412CE431A9A50B400C35DE1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 4412CE451A9A50B700C35DE1 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; E8A666341A844CC400287CA3 /* SSKeychain.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SSKeychain.framework; sourceTree = BUILT_PRODUCTS_DIR; }; E8A6664F1A844CF100287CA3 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E8A666551A844D3A00287CA3 /* SSKeychain iOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SSKeychain iOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -77,6 +75,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 4412CE421A9A50AE00C35DE1 /* Foundation.framework in Frameworks */, + 4412CE401A9A50A800C35DE1 /* Security.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -92,6 +92,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 4412CE441A9A50B400C35DE1 /* Foundation.framework in Frameworks */, + 4412CE4C1A9A527200C35DE1 /* Security.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -99,26 +101,17 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - E8A6667A1A844E4100287CA3 /* SSKeychain.framework in Frameworks */, + 4412CE3A1A9A4C3000C35DE1 /* SSKeychain.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 21B85B2718EC9455009D2B98 /* Other Frameworks */ = { - isa = PBXGroup; - children = ( - 21B85B2818EC9455009D2B98 /* AppKit.framework */, - 21B85B2918EC9455009D2B98 /* CoreData.framework */, - 21B85B2A18EC9455009D2B98 /* Foundation.framework */, - ); - name = "Other Frameworks"; - sourceTree = ""; - }; 21CC429E17DB874300201DDC = { isa = PBXGroup; children = ( + 4412CE201A9A400400C35DE1 /* .travis.yml */, 21CC42EC17DB878300201DDC /* SSKeychain */, 21CC42D917DB877900201DDC /* Tests */, 21CC42A917DB874300201DDC /* Frameworks */, @@ -141,15 +134,8 @@ 21CC42A917DB874300201DDC /* Frameworks */ = { isa = PBXGroup; children = ( - 21B85B6E18EC963A009D2B98 /* Cocoa.framework */, - 21B85B1E18EC9391009D2B98 /* Security.framework */, - 21CC42F917DB87C300201DDC /* Security.framework */, - 21CC42AA17DB874300201DDC /* Foundation.framework */, - 21CC42AC17DB874300201DDC /* CoreGraphics.framework */, - 21CC42AE17DB874300201DDC /* UIKit.framework */, - 21CC42C317DB874300201DDC /* XCTest.framework */, - 21B85B2518EC9455009D2B98 /* Cocoa.framework */, - 21B85B2718EC9455009D2B98 /* Other Frameworks */, + 4412CE471A9A50C400C35DE1 /* Mac */, + 4412CE481A9A50D100C35DE1 /* iOS */, ); name = Frameworks; sourceTree = ""; @@ -178,6 +164,24 @@ path = SSKeychain; sourceTree = ""; }; + 4412CE471A9A50C400C35DE1 /* Mac */ = { + isa = PBXGroup; + children = ( + 4412CE451A9A50B700C35DE1 /* Security.framework */, + 4412CE431A9A50B400C35DE1 /* Foundation.framework */, + ); + name = Mac; + sourceTree = ""; + }; + 4412CE481A9A50D100C35DE1 /* iOS */ = { + isa = PBXGroup; + children = ( + 4412CE411A9A50AE00C35DE1 /* Foundation.framework */, + 4412CE3F1A9A50A800C35DE1 /* Security.framework */, + ); + name = iOS; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ From c30a5712f294d2eff5f2a1a76c7cdf9b080848a1 Mon Sep 17 00:00:00 2001 From: Rich Hodgkins Date: Mon, 23 Feb 2015 20:29:45 +0000 Subject: [PATCH 10/10] Commented out Mac build to create a successful Travis build for pull request --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a3badee..194f89c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ language: objective-c script: - xcodebuild -project SSKeychain.xcodeproj -scheme "SSKeychain iOS" clean build test - - xcodebuild -project SSKeychain.xcodeproj -scheme "SSKeychain Mac" -configuration Debug clean build test \ No newline at end of file +# - xcodebuild -project SSKeychain.xcodeproj -scheme "SSKeychain Mac" -configuration Debug clean build test \ No newline at end of file