Skip to content

Commit

Permalink
Support generating keys in secure enclave
Browse files Browse the repository at this point in the history
  • Loading branch information
kdubb committed Sep 12, 2021
1 parent 3e912a8 commit de3f3ac
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 10 deletions.
36 changes: 27 additions & 9 deletions Sources/ShieldSecurity/SecKeyPair.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ public struct SecKeyPair {


public class Builder {

public enum Flag {
case secureEnclave
}

public let type: SecKeyType?
public let keySize: Int?
Expand All @@ -46,31 +50,44 @@ public struct SecKeyPair {
return Builder(type: type, keySize: keySize)
}

public func generate(label: String? = nil) throws -> SecKeyPair {
public func generate(label: String? = nil, flags: Set<Flag> = []) throws -> SecKeyPair {
guard let type = type else { fatalError("missing key type") }
guard let keySize = keySize else { fatalError("missing key size") }

var attrs: [String: Any] = [
kSecAttrKeyType as String: type.systemValue,
kSecAttrKeySizeInBits as String: keySize,
var attrs: [CFString: Any] = [
kSecAttrKeyType: type.systemValue,
kSecAttrKeySizeInBits: keySize
]

if let label = label {
attrs[kSecAttrLabel as String] = label
attrs[kSecAttrLabel] = label
}

if flags.contains(.secureEnclave) {
attrs[kSecAttrTokenID] = kSecAttrTokenIDSecureEnclave
}

var publicKey: SecKey?, privateKey: SecKey?
let status = SecKeyGeneratePair(attrs as CFDictionary, &publicKey, &privateKey)
if status != errSecSuccess {
if status != errSecSuccess {
throw SecKeyPair.Error.generateFailed
}

#if os(iOS) || os(watchOS) || os(tvOS)
#if os(iOS) || os(watchOS) || os(tvOS)

if !flags.contains(.secureEnclave) {
try privateKey!.save()
}

try publicKey!.save()
try privateKey!.save()

#endif
#elseif os(macOS)

if flags.contains(.secureEnclave) {
try publicKey!.save()
}

#endif

return SecKeyPair(privateKey: privateKey!, publicKey: publicKey!)
}
Expand Down Expand Up @@ -120,6 +137,7 @@ public struct SecKeyPair {

try publicKey.delete()
try privateKey.delete()

}

public func persistentReferences() throws -> (Data, Data) {
Expand Down
11 changes: 11 additions & 0 deletions Tests/SecKeyPairTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,15 @@ class SecKeyPairTests: XCTestCase {
XCTAssertEqual(plainText, plainText4)

}

func testGenerateSecureEnclave() throws {
try XCTSkipIf(true, "Only runs on iPhone/iPad/AppleTV or a Mac with T2")

let keyPairBuilder = SecKeyPair.Builder(type: .ec, keySize: 256)

var keyPair: SecKeyPair? = nil
XCTAssertNoThrow(keyPair = try keyPairBuilder.generate(label: "Test Secure Key", flags: [.secureEnclave]))
XCTAssertNoThrow(try keyPair?.delete())
}

}
1 change: 0 additions & 1 deletion Tests/SecKeyTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ class SecKeyTests: ParameterizedTestCase {
}

func testECGeneration() throws {

try [192, 256, 384, 521].forEach { keySize in

let keyPair = try SecKeyPair.Builder(type: .ec, keySize: keySize).generate(label: "Test")
Expand Down

0 comments on commit de3f3ac

Please sign in to comment.