Skip to content

Commit

Permalink
chore: Update the keychain attribute to AccessibleAfterFirstUnlockThi…
Browse files Browse the repository at this point in the history
…sDeviceOnly (aws-amplify#4159)
  • Loading branch information
royjit authored Jun 1, 2022
1 parent ea2cdeb commit 828ffa4
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ - (instancetype)initWithServer:(NSURL *)server protocolType:(AWSCognitoAuthUICKe

- (void)commonInit
{
_accessibility = AWSCognitoAuthUICKeyChainStoreAccessibilityAfterFirstUnlock;
_accessibility = AWSCognitoAuthUICKeyChainStoreAccessibilityAfterFirstUnlockThisDeviceOnly;
}

#pragma mark -
Expand Down
2 changes: 1 addition & 1 deletion AWSCore/UICKeyChainStore/AWSUICKeyChainStore.m
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ - (instancetype)initWithServer:(NSURL *)server protocolType:(AWSUICKeyChainStore

- (void)commonInit
{
_accessibility = AWSUICKeyChainStoreAccessibilityAfterFirstUnlock;
_accessibility = AWSUICKeyChainStoreAccessibilityAfterFirstUnlockThisDeviceOnly;
}

#pragma mark -
Expand Down
32 changes: 32 additions & 0 deletions AWSIoT/AWSIoTKeyChainTypes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License").
// You may not use this file except in compliance with the License.
// A copy of the License is located at
//
// http://aws.amazon.com/apache2.0
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
//

#import <Foundation/Foundation.h>

@class AWSIoTMessage;

NS_ASSUME_NONNULL_BEGIN

typedef NS_ENUM(NSInteger, AWSIoTKeyChainAccessibility) {
AWSIoTKeyChainAccessibilityWhenUnlocked = 1,
AWSIoTKeyChainAccessibilityAfterFirstUnlock,
AWSIoTKeyChainAccessibilityAlways,
AWSIoTKeyChainAccessibilityWhenPasscodeSetThisDeviceOnly,
AWSIoTKeyChainAccessibilityWhenUnlockedThisDeviceOnly,
AWSIoTKeyChainAccessibilityAfterFirstUnlockThisDeviceOnly,
AWSIoTKeyChainAccessibilityAlwaysThisDeviceOnly,
};

NS_ASSUME_NONNULL_END
3 changes: 3 additions & 0 deletions AWSIoT/AWSIoTManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
//

#import "AWSIoTService.h"
#import "AWSIoTKeyChainTypes.h"

//CreateCertificateWithResponse
@interface AWSIoTCreateCertificateResponse : AWSModel
Expand Down Expand Up @@ -217,4 +218,6 @@
*/
+ (BOOL)deleteCertificate;

+ (void)setKeyChainAccessibility:(AWSIoTKeyChainAccessibility)accessibility;

@end
4 changes: 4 additions & 0 deletions AWSIoT/AWSIoTManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -382,4 +382,8 @@ + (BOOL)isValidCertificate:(NSString *)certificateId {
return [AWSIoTKeychain isValidCertificate:[NSString stringWithFormat:@"%@%@",[AWSIoTKeychain privateKeyTag], certificateId ]];
}

+ (void)setKeyChainAccessibility:(AWSIoTKeyChainAccessibility)accessibility {
[AWSIoTKeychain setKeyChainAccessibility:accessibility];
}

@end
3 changes: 3 additions & 0 deletions AWSIoT/Internal/AWSIoTKeychain.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#import <Security/Security.h>
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCryptor.h>
#import "AWSIoTKeyChainTypes.h"

FOUNDATION_EXPORT NSString *const AWSIoTKeychainStartPrivateKeyTag;
FOUNDATION_EXPORT NSString *const AWSIoTKeychainEndPrivateKeyTag;
Expand Down Expand Up @@ -59,4 +60,6 @@ FOUNDATION_EXPORT NSString *const AWSIoTKeychainEndCertKeyTag;
+ (BOOL)addPrivateKey:(NSData *)privkey tag:(NSString *)tag;
+ (BOOL)deletePrivateKeyWithTag:(NSString*)tag;

+ (void)setKeyChainAccessibility:(AWSIoTKeyChainAccessibility)accessibility;

@end
43 changes: 38 additions & 5 deletions AWSIoT/Internal/AWSIoTKeychain.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
NSString *const AWSIoTKeychainStartCertKeyTag = @"-----BEGIN CERTIFICATE-----\n";
NSString *const AWSIoTKeychainEndCertKeyTag = @"\n-----END CERTIFICATE-----";

static AWSIoTKeyChainAccessibility _accessibility = AWSIoTKeyChainAccessibilityAfterFirstUnlockThisDeviceOnly;

@implementation AWSIoTKeychain

+ (NSString*)publicKeyTag {
Expand Down Expand Up @@ -205,6 +207,7 @@ + (BOOL)addCertificateRef:(SecCertificateRef)certRef {
[queryCertificate setObject:(id)kSecClassCertificate forKey:(id)kSecClass];
[queryCertificate setObject:[AWSIoTKeychain certTag] forKey:(id)kSecAttrLabel];
[queryCertificate setObject:(__bridge id)certRef forKey:(id)kSecValueRef];
[queryCertificate setObject:(__bridge id)[AWSIoTKeychain accessibilityType] forKey:(id)kSecAttrAccessible];

OSStatus sanityCheck = SecItemAdd((CFDictionaryRef)queryCertificate, nil);
if ((sanityCheck != noErr) && (sanityCheck != errSecDuplicateItem)) {
Expand All @@ -226,7 +229,8 @@ + (BOOL)addCertificate:(NSData*)cert withTag:(NSString*)tag {
[queryCertificate setObject:(id)kSecClassCertificate forKey:(id)kSecClass];
[queryCertificate setObject:tag forKey:(id)kSecAttrLabel];
[queryCertificate setObject:(__bridge id)certRef forKey:(id)kSecValueRef];

[queryCertificate setObject:(__bridge id)[AWSIoTKeychain accessibilityType] forKey:(id)kSecAttrAccessible];

OSStatus sanityCheck = SecItemAdd((CFDictionaryRef)queryCertificate, nil);
if ((sanityCheck != noErr) && (sanityCheck != errSecDuplicateItem)) {
AWSDDLogError(@"add certificate to keychain with error: %d", (int)sanityCheck);
Expand Down Expand Up @@ -394,7 +398,8 @@ + (BOOL)addPublicKeyRef:(SecKeyRef)pubkeyRef tag:(NSString*)tag {
[publicKeyAttr setObject:(__bridge id _Nonnull)(pubkeyRef) forKey:(id)kSecValueRef];
[publicKeyAttr setObject:(id)kSecAttrKeyClassPublic forKey:(id)kSecAttrKeyClass];
[publicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnPersistentRef];

[publicKeyAttr setObject:(__bridge id)[AWSIoTKeychain accessibilityType] forKey:(id)kSecAttrAccessible];

sanityCheck = SecItemAdd((CFDictionaryRef) publicKeyAttr, (CFTypeRef *)&persistPeer);
if ((sanityCheck != noErr) && (sanityCheck != errSecDuplicateItem)){
AWSDDLogError(@"addPublicKeyRef error: %d",(int)sanityCheck);
Expand All @@ -417,7 +422,8 @@ + (BOOL)addPublicKey:(NSData*)pubkey tag:(NSString*)tag {
[publicKeyAttr setObject:pubkey forKey:(id)kSecValueData];
[publicKeyAttr setObject:(id)kSecAttrKeyClassPublic forKey:(id)kSecAttrKeyClass];
[publicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnPersistentRef];

[publicKeyAttr setObject:(__bridge id)[AWSIoTKeychain accessibilityType] forKey:(id)kSecAttrAccessible];

sanityCheck = SecItemAdd((CFDictionaryRef) publicKeyAttr, (CFTypeRef *)&persistPeer);
if ((sanityCheck != noErr) && (sanityCheck != errSecDuplicateItem)){
AWSDDLogError(@"addPublicKey error: %d",(int)sanityCheck);
Expand All @@ -440,7 +446,8 @@ + (BOOL)addPrivateKeyRef:(SecKeyRef)privkeyRef tag:(NSString*)tag {
[privateKeyAttr setObject:(__bridge id _Nonnull)(privkeyRef) forKey:(id)kSecValueRef];
[privateKeyAttr setObject:(id)kSecAttrKeyClassPrivate forKey:(id)kSecAttrKeyClass];
[privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnPersistentRef];

[privateKeyAttr setObject:(__bridge id)[AWSIoTKeychain accessibilityType] forKey:(id)kSecAttrAccessible];

sanityCheck = SecItemAdd((CFDictionaryRef) privateKeyAttr, (CFTypeRef *)&persistPeer);
if ((sanityCheck != noErr) && (sanityCheck != errSecDuplicateItem)){
AWSDDLogError(@"addPrivateKeyRef error: %d",(int)sanityCheck);
Expand All @@ -463,7 +470,8 @@ + (BOOL)addPrivateKey:(NSData*)privkey tag:(NSString*)tag {
[privateKeyAttr setObject:privkey forKey:(id)kSecValueData];
[privateKeyAttr setObject:(id)kSecAttrKeyClassPrivate forKey:(id)kSecAttrKeyClass];
[privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnPersistentRef];

[privateKeyAttr setObject:(__bridge id)[AWSIoTKeychain accessibilityType] forKey:(id)kSecAttrAccessible];

sanityCheck = SecItemAdd((CFDictionaryRef) privateKeyAttr, (CFTypeRef *)&persistPeer);
if ((sanityCheck != noErr) && (sanityCheck != errSecDuplicateItem)){
AWSDDLogError(@"addPrivateKey error: %d",(int)sanityCheck);
Expand Down Expand Up @@ -524,4 +532,29 @@ + (BOOL)deletePrivateKeyWithTag:(NSString*)tag {
return YES;
}

+ (void)setKeyChainAccessibility:(AWSIoTKeyChainAccessibility)accessibility {
_accessibility = accessibility;
}

+ (CFTypeRef)accessibilityType {
switch (_accessibility) {
case AWSIoTKeyChainAccessibilityWhenUnlocked:
return kSecAttrAccessibleWhenUnlocked;
case AWSIoTKeyChainAccessibilityAfterFirstUnlock:
return kSecAttrAccessibleAfterFirstUnlock;
case AWSIoTKeyChainAccessibilityAlways:
return kSecAttrAccessibleAlways;
case AWSIoTKeyChainAccessibilityWhenPasscodeSetThisDeviceOnly:
return kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly;
case AWSIoTKeyChainAccessibilityWhenUnlockedThisDeviceOnly:
return kSecAttrAccessibleWhenUnlockedThisDeviceOnly;
case AWSIoTKeyChainAccessibilityAfterFirstUnlockThisDeviceOnly:
return kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly;
case AWSIoTKeyChainAccessibilityAlwaysThisDeviceOnly:
return kSecAttrAccessibleAlwaysThisDeviceOnly;
default:
return nil;
}
}

@end
4 changes: 4 additions & 0 deletions AWSiOSSDKv2.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,7 @@
B4B8C4BF25ACC10F0054E723 /* AWSLexConfig.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = B4B8C4BE25ACC10E0054E723 /* AWSLexConfig.xcconfig */; };
B4B8C61325ACC1270054E723 /* AWSLexConfig.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = B4B8C4BE25ACC10E0054E723 /* AWSLexConfig.xcconfig */; };
B4B8C9B62845CAB3009E0865 /* AWSCognitoIdentityUserPoolTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B4B8C9B52845CAB3009E0865 /* AWSCognitoIdentityUserPoolTests.m */; };
B4B8C9B7284698D8009E0865 /* AWSIoTKeyChainTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = B4932E1D283D4AB100993CBC /* AWSIoTKeyChainTypes.h */; settings = {ATTRIBUTES = (Public, ); }; };
B4D61CCC23285D8C007E7A12 /* AWSCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE0D416D1C6A66E5006B91B5 /* AWSCore.framework */; };
B4D61CD523285DF5007E7A12 /* AWSConnectParticipant.h in Headers */ = {isa = PBXBuildFile; fileRef = B4D61CCD23285DF3007E7A12 /* AWSConnectParticipant.h */; settings = {ATTRIBUTES = (Public, ); }; };
B4D61CD623285DF5007E7A12 /* AWSConnectParticipantService.h in Headers */ = {isa = PBXBuildFile; fileRef = B4D61CCE23285DF4007E7A12 /* AWSConnectParticipantService.h */; settings = {ATTRIBUTES = (Public, ); }; };
Expand Down Expand Up @@ -3142,6 +3143,7 @@
B47FAF4222C577CE00014548 /* AWSS3TransferUtilityUnitTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AWSS3TransferUtilityUnitTests.m; sourceTree = "<group>"; };
B482E84522EEA9F10075A0A3 /* AWSS3TestHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AWSS3TestHelper.h; sourceTree = "<group>"; };
B482E84622EEA9F20075A0A3 /* AWSS3TestHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AWSS3TestHelper.m; sourceTree = "<group>"; };
B4932E1D283D4AB100993CBC /* AWSIoTKeyChainTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AWSIoTKeyChainTypes.h; sourceTree = "<group>"; };
B4A4DFF522B4201300379396 /* AWSSageMakerRuntime.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AWSSageMakerRuntime.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B4A4DFF822B4201400379396 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
B4A4E01422B4212900379396 /* AWSSageMakerRuntimeService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AWSSageMakerRuntimeService.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -6918,6 +6920,7 @@
CE9DE6351C6A78D70060793F /* Internal */,
CE9DE6101C6A78A60060793F /* Info.plist */,
174F80A62108066F00775D0D /* AWSIoTMQTTTypes.h */,
B4932E1D283D4AB100993CBC /* AWSIoTKeyChainTypes.h */,
);
path = AWSIoT;
sourceTree = "<group>";
Expand Down Expand Up @@ -8168,6 +8171,7 @@
CE9DE66A1C6A78D70060793F /* AWSMQTTMessage.h in Headers */,
03427769269D185200379263 /* AWSIoTMessage+AWSMQTTMessage.h in Headers */,
174F80A72108066F00775D0D /* AWSIoTMQTTTypes.h in Headers */,
B4B8C9B7284698D8009E0865 /* AWSIoTKeyChainTypes.h in Headers */,
CE9DE6681C6A78D70060793F /* AWSMQTTEncoder.h in Headers */,
CE9DE6701C6A78D70060793F /* AWSSRWebSocket.h in Headers */,
CE9DE6641C6A78D70060793F /* AWSIoTWebSocketOutputStream.h in Headers */,
Expand Down
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
# AWS Mobile SDK for iOS CHANGELOG

## Unreleased

-Features for next release

### Bug Fixes

- **AWSCognito**
- Fix the parsing of providerName used in the loginMap to use the right value in case of customer endpoint is configured. (See [PR #4162](https://github.com/aws-amplify/aws-sdk-ios/pull/4162))
- Fix the parsing of providerName used in the loginMap to use the right value in case of customer endpoint is configured. (See [PR #4162](https://github.com/aws-amplify/aws-sdk-ios/pull/4162))

### Misc. Updates

- **Core**
- Update keychain accessibility level to `kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly` as default to keep the keychain value in the device. (See [PR #4159](https://github.com/aws-amplify/aws-sdk-ios/pull/4159))

## 2.27.9

Expand Down

0 comments on commit 828ffa4

Please sign in to comment.