Skip to content

Commit

Permalink
Merge e8d701d into 3aff691
Browse files Browse the repository at this point in the history
  • Loading branch information
kimmytaft committed Sep 19, 2018
2 parents 3aff691 + e8d701d commit d973179
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 17 deletions.
8 changes: 6 additions & 2 deletions IBMCloudAppID.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
objects = {

/* Begin PBXBuildFile section */
0987DBB8214C5E3600C01812 /* SecurityUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBA200D1E51F7D9000EB3F5 /* SecurityUtils.swift */; };
0987DBBB2151865D00C01812 /* SecAttrAccessible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0987DBBA2151865D00C01812 /* SecAttrAccessible.swift */; };
181050421EE1BD9200AAA443 /* TokenResponseDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 181050411EE1BD9200AAA443 /* TokenResponseDelegate.swift */; };
4D42CF8A20173BD200EF40B6 /* RefreshToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D42CF8920173BD200EF40B6 /* RefreshToken.swift */; };
4D42CF8C20173BDD00EF40B6 /* RefreshTokenImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D42CF8B20173BDD00EF40B6 /* RefreshTokenImpl.swift */; };
Expand Down Expand Up @@ -58,7 +60,6 @@
EFBA20561E51F7D9000EB3F5 /* PreferenceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBA200A1E51F7D9000EB3F5 /* PreferenceManager.swift */; };
EFBA20581E51F7D9000EB3F5 /* RegistrationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBA200B1E51F7D9000EB3F5 /* RegistrationManager.swift */; };
EFBA205A1E51F7D9000EB3F5 /* safariView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBA200C1E51F7D9000EB3F5 /* safariView.swift */; };
EFBA205C1E51F7D9000EB3F5 /* SecurityUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBA200D1E51F7D9000EB3F5 /* SecurityUtils.swift */; };
EFBA205E1E51F7D9000EB3F5 /* StringPreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBA200E1E51F7D9000EB3F5 /* StringPreference.swift */; };
EFBA20601E51F7D9000EB3F5 /* TokenManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBA200F1E51F7D9000EB3F5 /* TokenManager.swift */; };
EFBA20621E51F7D9000EB3F5 /* AbstractToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFBA20111E51F7D9000EB3F5 /* AbstractToken.swift */; };
Expand Down Expand Up @@ -90,6 +91,7 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
0987DBBA2151865D00C01812 /* SecAttrAccessible.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecAttrAccessible.swift; sourceTree = "<group>"; };
181050411EE1BD9200AAA443 /* TokenResponseDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TokenResponseDelegate.swift; sourceTree = "<group>"; };
3A523D88E31CC7EC37CAFA1D /* Pods-IBMCloudAppID.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-IBMCloudAppID.release.xcconfig"; path = "Pods/Target Support Files/Pods-IBMCloudAppID/Pods-IBMCloudAppID.release.xcconfig"; sourceTree = "<group>"; };
4D42CF8920173BD200EF40B6 /* RefreshToken.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RefreshToken.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -274,6 +276,7 @@
EFBA1FFA1E51F7D9000EB3F5 /* Tokens */,
EFBA1FFE1E51F7D9000EB3F5 /* UserProfileError.swift */,
EFBA1FFF1E51F7D9000EB3F5 /* UserProfileManager.swift */,
0987DBBA2151865D00C01812 /* SecAttrAccessible.swift */,
);
path = api;
sourceTree = "<group>";
Expand Down Expand Up @@ -602,8 +605,8 @@
EFBA205E1E51F7D9000EB3F5 /* StringPreference.swift in Sources */,
EFBA20661E51F7D9000EB3F5 /* IdentityTokenImpl.swift in Sources */,
EFBA20441E51F7D9000EB3F5 /* AppIDConstants.swift in Sources */,
EFBA205C1E51F7D9000EB3F5 /* SecurityUtils.swift in Sources */,
EFBA20461E51F7D9000EB3F5 /* AppIDError.swift in Sources */,
0987DBB8214C5E3600C01812 /* SecurityUtils.swift in Sources */,
EFBA20561E51F7D9000EB3F5 /* PreferenceManager.swift in Sources */,
EFBA206A1E51F7D9000EB3F5 /* Utils.swift in Sources */,
EFBA20501E51F7D9000EB3F5 /* JSONPreference.swift in Sources */,
Expand All @@ -617,6 +620,7 @@
EFBA201E1E51F7D9000EB3F5 /* AppIDTestConstants.swift in Sources */,
EFBA20521E51F7D9000EB3F5 /* LoginWidgetImpl.swift in Sources */,
EFBA204A1E51F7D9000EB3F5 /* AuthorizationManager.swift in Sources */,
0987DBBB2151865D00C01812 /* SecAttrAccessible.swift in Sources */,
EFBA20541E51F7D9000EB3F5 /* OAuthManager.swift in Sources */,
181050421EE1BD9200AAA443 /* TokenResponseDelegate.swift in Sources */,
EFBA20641E51F7D9000EB3F5 /* AccessTokenImpl.swift in Sources */,
Expand Down
26 changes: 23 additions & 3 deletions IBMCloudAppIDTests/SecurityUtilsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,35 @@ class SecurityUtilsTest: XCTestCase {
TestHelpers.savePrivateKeyDataToKeyChain(AppIDTestConstants.privateKeyData, tag: privateKeyTag)
}

func testSecAttrAccessible() {
AppID.secAttrAccess = .accessibleAlways
XCTAssertEqual(AppID.secAttrAccess.rawValue, kSecAttrAccessibleAlways)
}

func testGenerateKeyPairAttrsPrivate() {
let keyPair = SecurityUtils.generateKeyPairAttrs(keySize, publicTag: publicKeyTag, privateTag: privateKeyTag)
let privateAttrs = keyPair["private"] as! [NSString: AnyObject] // tailor:disable
let accessibility = privateAttrs[kSecAttrAccessible]
XCTAssertEqual(accessibility as! CFString, AppID.secAttrAccess.rawValue) // tailor:disable
}

func testGenerateKeyPairAttrsPublic() {
let keyPair = SecurityUtils.generateKeyPairAttrs(keySize, publicTag: publicKeyTag, privateTag: privateKeyTag)
let publicAttrs = keyPair["public"] as! [NSString: AnyObject] // tailor:disable
let accessibility = publicAttrs[kSecAttrAccessible]
XCTAssertEqual(accessibility as! CFString, AppID.secAttrAccess.rawValue) // tailor:disable
}

func testGenerateKeyPairAttrs() {
let keyPair = SecurityUtils.generateKeyPairAttrs(keySize, publicTag: publicKeyTag, privateTag: privateKeyTag)
XCTAssertEqual(keyPair[kSecAttrAccessible] as! CFString, AppID.secAttrAccess.rawValue) // tailor:disable
}

func testKeyPairGeneration() {
TestHelpers.clearDictValuesFromKeyChain([publicKeyTag : kSecClassKey, privateKeyTag : kSecClassKey])
XCTAssertNotNil(try? SecurityUtils.generateKeyPair(keySize, publicTag: publicKeyTag, privateTag: privateKeyTag))
}


func testSaveItemToKeyChain() {
_ = SecurityUtils.saveItemToKeyChain(itemData, label: itemLabel)
XCTAssertEqual(SecurityUtils.getItemFromKeyChain(itemLabel), itemData)
Expand Down Expand Up @@ -68,6 +90,4 @@ class SecurityUtilsTest: XCTestCase {
let signature = try? SecurityUtils.signString("somepayload", keyIds: (publicKeyTag, privateKeyTag), keySize: keySize)
XCTAssertEqual(signature, "ODT3jvWINoDIYrdMPMB-n548VKXnVT7wAg378q3vV4b20gkZq66DOPrkM9JmyOsVcrKO7FWCa0VaLu418rkC3w==")
}


}
4 changes: 2 additions & 2 deletions IBMCloudAppIDTests/TestHelpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ public class TestHelpers {
}

public static func savePrivateKeyDataToKeyChain(_ key:Data,tag:String) {
let publicKeyAttr : [NSString:AnyObject] = [
let privateKeyAttr : [NSString:AnyObject] = [
kSecValueData: key as AnyObject,
kSecClass : kSecClassKey,
kSecAttrApplicationTag: tag as AnyObject,
kSecAttrKeyType : kSecAttrKeyTypeRSA,
kSecAttrKeyClass : kSecAttrKeyClassPrivate

]
SecItemAdd(publicKeyAttr as CFDictionary, nil)
SecItemAdd(privateKeyAttr as CFDictionary, nil)
}

public static func clearDictValuesFromKeyChain(_ dict : [String : NSString]) {
Expand Down
1 change: 1 addition & 0 deletions Source/IBMCloudAppID/api/AppID.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class AppID {

public static var overrideServerHost: String?
public static var overrideAttributesHost: String?
public static var secAttrAccess: SecAttrAccessible = .accessibleAfterFirstUnlock
public static var sharedInstance = AppID()
internal static let logger = Logger.logger(name: AppIDConstants.AppIDLoggerName)

Expand Down
49 changes: 49 additions & 0 deletions Source/IBMCloudAppID/api/SecAttrAccessible.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* * Copyright 2016, 2017, 2018 IBM Corp.
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License 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

public enum SecAttrAccessible: RawRepresentable {

case accessibleAlways // kSecAttrAccessibleAlways
case accessibleAlwaysThisDeviceOnly // kSecAttrAccessibleAlwaysThisDeviceOnly
case accessibleAfterFirstUnlock // kSecAttrAccessibleAfterFirstUnlock
case accessibleAfterFirstUnlockThisDeviceOnly // kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
case accessibleWhenUnlocked // kSecAttrAccessibleWhenUnlocked
case accessibleWhenUnlockedThisDeviceOnly // kSecAttrAccessibleWhenUnlockedThisDeviceOnly
case accessibleWhenPasscodeSetThisDeviceOnly // kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly

public init?(rawValue: CFString) {
switch rawValue {
case kSecAttrAccessibleAlways: self = .accessibleAlways
case kSecAttrAccessibleAlwaysThisDeviceOnly: self = .accessibleAlwaysThisDeviceOnly
case kSecAttrAccessibleAfterFirstUnlock: self = .accessibleAfterFirstUnlock
case kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly: self = .accessibleAfterFirstUnlockThisDeviceOnly
case kSecAttrAccessibleWhenUnlocked: self = .accessibleWhenUnlocked
case kSecAttrAccessibleWhenUnlockedThisDeviceOnly: self = .accessibleWhenUnlockedThisDeviceOnly
case kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly: self = .accessibleWhenPasscodeSetThisDeviceOnly
default: self = .accessibleAfterFirstUnlock
}
}

public var rawValue: CFString {
switch self {
case .accessibleAlways: return kSecAttrAccessibleAlways
case .accessibleAlwaysThisDeviceOnly: return kSecAttrAccessibleAlwaysThisDeviceOnly
case .accessibleAfterFirstUnlock: return kSecAttrAccessibleAfterFirstUnlock
case .accessibleAfterFirstUnlockThisDeviceOnly: return kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
case .accessibleWhenUnlocked: return kSecAttrAccessibleWhenUnlocked
case .accessibleWhenUnlockedThisDeviceOnly: return kSecAttrAccessibleWhenUnlockedThisDeviceOnly
case .accessibleWhenPasscodeSetThisDeviceOnly: return kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
}
}
}
27 changes: 17 additions & 10 deletions Source/IBMCloudAppID/internal/SecurityUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,34 +32,40 @@ internal class SecurityUtils {

}

internal static func generateKeyPair(_ keySize:Int, publicTag:String, privateTag:String) throws {
//make sure keys are deleted
_ = SecurityUtils.deleteKeyFromKeyChain(publicTag)
_ = SecurityUtils.deleteKeyFromKeyChain(privateTag)

var status:OSStatus = noErr
var privateKey:SecKey?
var publicKey:SecKey?

internal static func generateKeyPairAttrs(_ keySize:Int, publicTag:String, privateTag:String) -> [NSString:AnyObject] {
let privateKeyAttr : [NSString:AnyObject] = [
kSecAttrIsPermanent : true as AnyObject,
kSecAttrApplicationTag : privateTag as AnyObject,
kSecAttrKeyClass : kSecAttrKeyClassPrivate
kSecAttrKeyClass : kSecAttrKeyClassPrivate,
kSecAttrAccessible: AppID.secAttrAccess.rawValue
]

let publicKeyAttr : [NSString:AnyObject] = [
kSecAttrIsPermanent : true as AnyObject,
kSecAttrApplicationTag : publicTag as AnyObject,
kSecAttrKeyClass : kSecAttrKeyClassPublic,
kSecAttrAccessible: AppID.secAttrAccess.rawValue
]

let keyPairAttr : [NSString:AnyObject] = [
kSecAttrKeyType : kSecAttrKeyTypeRSA,
kSecAttrAccessible: AppID.secAttrAccess.rawValue,
kSecAttrKeySizeInBits : keySize as AnyObject,
kSecPublicKeyAttrs : publicKeyAttr as AnyObject,
kSecPrivateKeyAttrs : privateKeyAttr as AnyObject
]
return keyPairAttr
}

internal static func generateKeyPair(_ keySize:Int, publicTag:String, privateTag:String) throws {
//make sure keys are deleted
_ = SecurityUtils.deleteKeyFromKeyChain(publicTag)
_ = SecurityUtils.deleteKeyFromKeyChain(privateTag)

var status:OSStatus = noErr
var privateKey:SecKey?
var publicKey:SecKey?
let keyPairAttr = generateKeyPairAttrs(keySize, publicTag: publicTag, privateTag: privateTag)
status = SecKeyGeneratePair(keyPairAttr as CFDictionary, &publicKey, &privateKey)
if (status != errSecSuccess) {
throw AppIDError.generalError
Expand All @@ -73,6 +79,7 @@ internal class SecurityUtils {
kSecAttrKeyType : kSecAttrKeyTypeRSA,
kSecReturnRef : kCFBooleanTrue
]

var result: AnyObject?

let status = SecItemCopyMatching(keyAttr as CFDictionary, &result)
Expand Down

0 comments on commit d973179

Please sign in to comment.