From 0c15ff2ff422f54a019219e3dfe38a1e1a456698 Mon Sep 17 00:00:00 2001 From: Daniel Hugenroth Date: Mon, 20 Nov 2023 14:38:12 +0000 Subject: [PATCH] Update iOS for Swift package --- .github/workflows/android.yaml | 6 + .github/workflows/ios.yaml | 42 ++ ios/.gitignore | 5 - ios/Artifacts/.gitignore | 2 - ios/README.md | 32 +- ios/RainbowSloth/.gitignore | 8 + ios/RainbowSloth/Package.swift | 27 + ios/RainbowSloth/README.md | 49 ++ .../Sources/RainbowSloth}/Hkdf.swift | 6 +- .../Sources/RainbowSloth/PwHash.swift | 29 + .../Sources/RainbowSloth}/RainbowSloth.swift | 28 +- .../Sources/RainbowSloth}/ReHashToEc.swift | 11 +- .../Sources/RainbowSloth}/SecureEnclave.swift | 12 +- .../Sources/RainbowSloth}/Utils.swift | 12 +- .../Tests/RainbowSlothTests}/HkdfTests.swift | 4 +- .../Tests/RainbowSlothTests/PwHashTests.swift | 46 ++ .../RainbowSlothTests}/ReHashToEcTests.swift | 1 + ios/SecureEnclaveBench/Podfile | 9 - ios/SecureEnclaveBench/Podfile.lock | 16 - .../project.pbxproj | 630 ------------------ .../contents.xcworkspacedata | 10 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../SecureEnclaveBench/PwHash.swift | 19 - .../SecureEnclaveBenchTests/PwHashTests.swift | 13 - ios/Sloth/.gitignore | 8 + ios/Sloth/Sloth.xcodeproj/project.pbxproj | 511 ++++++++++++++ .../contents.xcworkspacedata | 0 .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../xcshareddata/swiftpm/Package.resolved | 14 + .../AccentColor.colorset/Contents.json | 0 .../AppIcon.appiconset/Contents.json | 0 .../Sloth}/Assets.xcassets/Contents.json | 0 .../Sloth}/ContentView.swift | 61 +- .../Preview Assets.xcassets/Contents.json | 0 .../Sloth/SlothApp.swift} | 2 +- .../Sloth}/UIDevice.swift | 0 .../SlothTests}/RainbowSlothTests.swift | 2 + .../SlothTests}/SecureEnclaveTests.swift | 2 + ios/build_artifacts.sh | 12 - ios/docs/screenshot-framed.png | Bin 0 -> 98092 bytes 40 files changed, 837 insertions(+), 800 deletions(-) create mode 100644 .github/workflows/ios.yaml delete mode 100644 ios/.gitignore delete mode 100644 ios/Artifacts/.gitignore create mode 100644 ios/RainbowSloth/.gitignore create mode 100644 ios/RainbowSloth/Package.swift create mode 100644 ios/RainbowSloth/README.md rename ios/{SecureEnclaveBench/SecureEnclaveBench => RainbowSloth/Sources/RainbowSloth}/Hkdf.swift (57%) create mode 100644 ios/RainbowSloth/Sources/RainbowSloth/PwHash.swift rename ios/{SecureEnclaveBench/SecureEnclaveBench => RainbowSloth/Sources/RainbowSloth}/RainbowSloth.swift (55%) rename ios/{SecureEnclaveBench/SecureEnclaveBench => RainbowSloth/Sources/RainbowSloth}/ReHashToEc.swift (80%) rename ios/{SecureEnclaveBench/SecureEnclaveBench => RainbowSloth/Sources/RainbowSloth}/SecureEnclave.swift (92%) rename ios/{SecureEnclaveBench/SecureEnclaveBench => RainbowSloth/Sources/RainbowSloth}/Utils.swift (74%) rename ios/{SecureEnclaveBench/SecureEnclaveBenchTests => RainbowSloth/Tests/RainbowSlothTests}/HkdfTests.swift (93%) create mode 100644 ios/RainbowSloth/Tests/RainbowSlothTests/PwHashTests.swift rename ios/{SecureEnclaveBench/SecureEnclaveBenchTests => RainbowSloth/Tests/RainbowSlothTests}/ReHashToEcTests.swift (96%) delete mode 100644 ios/SecureEnclaveBench/Podfile delete mode 100644 ios/SecureEnclaveBench/Podfile.lock delete mode 100644 ios/SecureEnclaveBench/SecureEnclaveBench.xcodeproj/project.pbxproj delete mode 100644 ios/SecureEnclaveBench/SecureEnclaveBench.xcworkspace/contents.xcworkspacedata delete mode 100644 ios/SecureEnclaveBench/SecureEnclaveBench.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 ios/SecureEnclaveBench/SecureEnclaveBench/PwHash.swift delete mode 100644 ios/SecureEnclaveBench/SecureEnclaveBenchTests/PwHashTests.swift create mode 100644 ios/Sloth/.gitignore create mode 100644 ios/Sloth/Sloth.xcodeproj/project.pbxproj rename ios/{SecureEnclaveBench/SecureEnclaveBench.xcodeproj => Sloth/Sloth.xcodeproj}/project.xcworkspace/contents.xcworkspacedata (100%) rename ios/{SecureEnclaveBench/SecureEnclaveBench.xcodeproj => Sloth/Sloth.xcodeproj}/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (100%) create mode 100644 ios/Sloth/Sloth.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved rename ios/{SecureEnclaveBench/SecureEnclaveBench => Sloth/Sloth}/Assets.xcassets/AccentColor.colorset/Contents.json (100%) rename ios/{SecureEnclaveBench/SecureEnclaveBench => Sloth/Sloth}/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename ios/{SecureEnclaveBench/SecureEnclaveBench => Sloth/Sloth}/Assets.xcassets/Contents.json (100%) rename ios/{SecureEnclaveBench/SecureEnclaveBench => Sloth/Sloth}/ContentView.swift (72%) rename ios/{SecureEnclaveBench/SecureEnclaveBench => Sloth/Sloth}/Preview Content/Preview Assets.xcassets/Contents.json (100%) rename ios/{SecureEnclaveBench/SecureEnclaveBench/SecureEnclaveBenchApp.swift => Sloth/Sloth/SlothApp.swift} (76%) rename ios/{SecureEnclaveBench/SecureEnclaveBench => Sloth/Sloth}/UIDevice.swift (100%) rename ios/{SecureEnclaveBench/SecureEnclaveBenchTests => Sloth/SlothTests}/RainbowSlothTests.swift (95%) rename ios/{SecureEnclaveBench/SecureEnclaveBenchTests => Sloth/SlothTests}/SecureEnclaveTests.swift (92%) delete mode 100755 ios/build_artifacts.sh create mode 100644 ios/docs/screenshot-framed.png diff --git a/.github/workflows/android.yaml b/.github/workflows/android.yaml index 45cdf5c..a55dc30 100644 --- a/.github/workflows/android.yaml +++ b/.github/workflows/android.yaml @@ -1,7 +1,13 @@ on: push: + paths: + - "android/**" + - ".github/workflows/android.yaml" branches: [ "main" ] pull_request: + paths: + - "android/**" + - ".github/workflows/android.yaml" branches: [ "main" ] name: Android diff --git a/.github/workflows/ios.yaml b/.github/workflows/ios.yaml new file mode 100644 index 0000000..630a026 --- /dev/null +++ b/.github/workflows/ios.yaml @@ -0,0 +1,42 @@ +on: + pull_request: + paths: + - "ios/**" + - ".github/workflows/ios.yaml" + branches: + - "main" + +name: iOS + +jobs: + build: + name: Synchronize libraries + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v3 + + - name: Add secret key to runner + env: + SLOTH_IOS_KEY: ${{ secrets.SLOTH_IOS_KEY }} + run: | + mkdir -p ~/.ssh + echo "$SLOTH_IOS_KEY" > ~/.ssh/id_ed25519 + chmod 400 ~/.ssh/id_ed25519 + wc ~/.ssh/id_ed25519 + + - name: Checkout remote + run: | + git clone git@github.com:lambdapioneer/sloth-ios.git target + cd target + + - name: Replace contents + run: | + cd target + cp -rv ../ios/RainbowSloth/* . + git add . + + - name: Pushy to remote + run: | + git diff-index --quiet HEAD || git commit -m "Automatic publish from github.com/project" + git push origin main diff --git a/ios/.gitignore b/ios/.gitignore deleted file mode 100644 index bc5de01..0000000 --- a/ios/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -xcuserdata/ -*.ipa -*.dSYM.zip -*.dSYM -.build/ diff --git a/ios/Artifacts/.gitignore b/ios/Artifacts/.gitignore deleted file mode 100644 index d6b7ef3..0000000 --- a/ios/Artifacts/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/ios/README.md b/ios/README.md index 85bd6ad..6463d42 100644 --- a/ios/README.md +++ b/ios/README.md @@ -1,27 +1,20 @@ # Sloth: iOS -We have implemented **RainbowSloth** for iOS as a demo project included in this folder -This code is developed as an academic prototype and not intended for production use yet. +We have implemented **RainbowSloth** for iOS in this folder +It consists of the `RainbowSloth` package and the `Sloth` demo app. -## Getting started -For install the Argon2 dependency using CocoaPods. -If you do not have CocoaPods installed, follow the instructions on their website: https://cocoapods.org/ +## Using the RainbowSloth package -Then enter the iOS folder and execute the following: +The `RainbowSloth` package is synced to another repository to allow it to be included as a Swift package dependency. +Refer to the `README.md` over there: https://github.com/lambdapioneer/sloth-ios -```bash -pod install -``` -Then open the `Sloth.xcworkspace` file in Xcode. -It is important to open the workspace file and not the project file. - - -### Adding Sloth to your iOS project +## Tests -> [!IMPORTANT] -> We have not _yet_ published library artifacts. For now, you need to build the project locally. +Most low-level tests live inside the `RainbowSloth` package. +However, those that require the Secure Enclave live in the `Sloth` app test target as they require entitlements. +When testing, make sure to execute both sets of tests. ## The benchmark app @@ -29,6 +22,8 @@ It is important to open the workspace file and not the project file. The project comes with a benchmark app that is also used to generate the performance numbers that are reported in the paper. You can install it on a real device or a simulator using Xcode. +![Screenshot of the app](docs/screenshot-framed.png) + For our evaluation we created .IPA files that we then run online using AWS DeviceFarm. During these runs we manually interacted with the app through the web interface of DeviceFarm. The app reports the results to a custom server that we run on one of our servers. @@ -38,8 +33,3 @@ To replicate these steps first start the server on a server and update the IP ad Build the artifacts by running `build_artifact.sh`. Start the simulator (or use real devices) and install the IPA file. Execute the scenarios under test using the UI and observe that results are collected on the server as log files. - - -## Tests - -The project bundles tests for the individual components and you can execute them as usual through the IDE on either the simulators or a real device. diff --git a/ios/RainbowSloth/.gitignore b/ios/RainbowSloth/.gitignore new file mode 100644 index 0000000..0023a53 --- /dev/null +++ b/ios/RainbowSloth/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/ios/RainbowSloth/Package.swift b/ios/RainbowSloth/Package.swift new file mode 100644 index 0000000..0385df7 --- /dev/null +++ b/ios/RainbowSloth/Package.swift @@ -0,0 +1,27 @@ +// swift-tools-version: 5.9 + +import PackageDescription + +let package = Package( + name: "RainbowSloth", + platforms: [.iOS(.v14)], + products: [ + .library( + name: "RainbowSloth", + targets: ["RainbowSloth"]), + ], + dependencies: [ + .package(url: "https://github.com/jedisct1/swift-sodium.git", from: "0.9.1"), + ], + targets: [ + .target( + name: "RainbowSloth", + dependencies: [ + .product(name: "Sodium", package: "swift-sodium") + ] + ), + .testTarget( + name: "RainbowSlothTests", + dependencies: ["RainbowSloth"]), + ] +) diff --git a/ios/RainbowSloth/README.md b/ios/RainbowSloth/README.md new file mode 100644 index 0000000..8096533 --- /dev/null +++ b/ios/RainbowSloth/README.md @@ -0,0 +1,49 @@ +# Sloth: iOS + +We have implemented the SE-backed key stretching scheme RainbowSloth for iOS 15+. +This folder gets synced into a designated repository to allow inclusion as a Swift package dependency. + +For changes refer to the main repository here: https://github.com/lambdapioneer/sloth + + +## Setting up + +Add this repository as a dependency to your `Package.swift` file like so: + +```swift + dependencies: [ + .package(url: "https://github.com/lambdapioneer/sloth-ios.git", from: "0.0.1"), + ], + + // ... + + dependencies: [ + .product(name: "RainbowSloth", package: "sloth-ios") + ] +``` + + +## Using RainbowSloth + +After adding the dependency you can import the library in the respective `.swift` files and use it: + +```swift +import RainbowSloth + +// create a new Sloth instance +let sloth = RainbowSloth(withN: 100) // see paper on how to choose `n` + +// create a new key +let (storageState, key) = try sloth.keygen( + pw: "user-passphrase", + handle: "your-identifier", + outputLength: 32 +) + +// re-derive the same key later +let key = try sloth.derive( + storageState: storageState, + pw: "user-passphrase", + outputLength: 32 +) +``` diff --git a/ios/SecureEnclaveBench/SecureEnclaveBench/Hkdf.swift b/ios/RainbowSloth/Sources/RainbowSloth/Hkdf.swift similarity index 57% rename from ios/SecureEnclaveBench/SecureEnclaveBench/Hkdf.swift rename to ios/RainbowSloth/Sources/RainbowSloth/Hkdf.swift index 317249c..82612bd 100644 --- a/ios/SecureEnclaveBench/SecureEnclaveBench/Hkdf.swift +++ b/ios/RainbowSloth/Sources/RainbowSloth/Hkdf.swift @@ -1,14 +1,16 @@ import CryptoKit import Foundation +/// A simple wrapper around `HDKF` with `SHA256` using `Data` types. public struct HkdfSha256 { - public static func derive(salt: Data, ikm: Data, info: Data, l: Int) -> Data { + /// Derives a key from the initial key material `ikm` using the given `salt` and `info`. The output will be `outputLength` bytes long. + public static func derive(salt: Data, ikm: Data, info: Data, outputLength: Int) -> Data { let output = HKDF.deriveKey( inputKeyMaterial: SymmetricKey(data: ikm), salt: salt, info: info, - outputByteCount: l + outputByteCount: outputLength ) return output.withUnsafeBytes { body in Data(body) diff --git a/ios/RainbowSloth/Sources/RainbowSloth/PwHash.swift b/ios/RainbowSloth/Sources/RainbowSloth/PwHash.swift new file mode 100644 index 0000000..a9d53ea --- /dev/null +++ b/ios/RainbowSloth/Sources/RainbowSloth/PwHash.swift @@ -0,0 +1,29 @@ +import Sodium +import Foundation + +/// Wrapper around the Argon2id password hashing algorithm as provided by `Sodium`. +public struct PwHash { + + /// Derives a key from the given `salt` and password `pw`. The output will be `outputLength` bytes long. + public static func derive(salt: Data, pw: Data, outputLength: Int) -> Data { + // OWASP: "Use Argon2id with a minimum configuration of 19 MiB of memory, an iteration count of 2, and 1 degree of parallelism." + let sodium = Sodium.init() + let sodiumPwHash = sodium.pwHash + let res = sodiumPwHash.hash( + outputLength: outputLength, + passwd: Array(pw), + salt: Array(salt), + opsLimit: 2, + memLimit: 19*1024*1024 // 19 MiB + ) + return Data(res!) + } + + /// Creates a new random `salt` byte array that can be used with the `derive` function. + public static func randomSalt(outputLength: Int = 16) -> Data { + var bytes = [UInt8](repeating: 0, count: outputLength) + let result = SecRandomCopyBytes(kSecRandomDefault, bytes.count, &bytes) + assert(result == errSecSuccess, "Failed to generate random bytes") + return Data(bytes) + } +} diff --git a/ios/SecureEnclaveBench/SecureEnclaveBench/RainbowSloth.swift b/ios/RainbowSloth/Sources/RainbowSloth/RainbowSloth.swift similarity index 55% rename from ios/SecureEnclaveBench/SecureEnclaveBench/RainbowSloth.swift rename to ios/RainbowSloth/Sources/RainbowSloth/RainbowSloth.swift index 6434640..136914e 100644 --- a/ios/SecureEnclaveBench/SecureEnclaveBench/RainbowSloth.swift +++ b/ios/RainbowSloth/Sources/RainbowSloth/RainbowSloth.swift @@ -1,20 +1,25 @@ import Foundation -let DEFAULT_HANDLE = Data() -let P256_PUBLIC_KEY_SIZE = 32 +private let P256_PUBLIC_KEY_SIZE = 32 +/// Implementation of the RainbowSloth algorithm for tuneable password-based key stretching on iOS using the SecureEnclave (SE). +/// The parameter `n` determines the number of required SE operations and can be increased for higher security levels. +/// Refer to the paper and documentation for more details. public struct RainbowSloth { var n: Int - init(withN n: Int) { + public init(withN n: Int) { self.n = n; } - func keygen(pw: String, handle: String, outputLength: Int) throws -> (RainbowSlothStorageState, Data) { + /// Generates a new key under the handle `handle` using the password `pw`. The output will be `outputLength` bytes long. + /// Every call to this function will result in a new key and any existing key under the same handle will be overwritten. + /// Calls to `derive` using the returned storage state will result in the same key. + public func keygen(pw: String, handle: String, outputLength: Int) throws -> (RainbowSlothStorageState, Data) { let storageState = RainbowSlothStorageState( handle: handle, - salt: randomSalt() + salt: PwHash.randomSalt() ) try SecureEnclave.resetSecretSeKey(handle: storageState.handle) @@ -24,13 +29,16 @@ public struct RainbowSloth { return (storageState, k) } - func derive(storageState: RainbowSlothStorageState, pw: String, outputLength: Int) throws -> Data { + /// Re-derives a key from the given storage state. The result will be `outputLength` bytes long. + public func derive(storageState: RainbowSlothStorageState, pw: String, outputLength: Int) throws -> Data { let pres = try preambleDerive(storageState: storageState, pw: pw) let k = try innerDerive(storageState: storageState, pres: pres, outputLength: outputLength) return k } - func eval(storageState: RainbowSlothStorageState, pw: String, outputLength: Int, iterations: Int) throws -> [Double] { + /// An evaluation method of the internal derive method to measure the effective time guarantees. The returned array contains + /// `iterations` many measurements of this operation in seconds. + public func eval(storageState: RainbowSlothStorageState, pw: String, outputLength: Int, iterations: Int) throws -> [Double] { let pres = try preambleDerive(storageState: storageState, pw: pw) var durations = [Double]() @@ -47,7 +55,8 @@ public struct RainbowSloth { private func preambleDerive(storageState: RainbowSlothStorageState, pw: String) throws -> [Data] { let l = n * P256_PUBLIC_KEY_SIZE - let pres_combined = PwHash.derive(salt: storageState.salt, pw: pw, l: l) + let pwBytes = pw.data(using: .utf8)! + let pres_combined = PwHash.derive(salt: storageState.salt, pw: pwBytes, outputLength: l) return pres_combined.chunkify(length: P256_PUBLIC_KEY_SIZE) } @@ -66,13 +75,14 @@ public struct RainbowSloth { salt: storageState.salt, ikm: posts_combined, info: Data(), - l: outputLength + outputLength: outputLength ) return k } } +/// The required data to be persisted for later re-deriving the same key using `RainbowSloth`. public struct RainbowSlothStorageState { var handle: String var salt: Data diff --git a/ios/SecureEnclaveBench/SecureEnclaveBench/ReHashToEc.swift b/ios/RainbowSloth/Sources/RainbowSloth/ReHashToEc.swift similarity index 80% rename from ios/SecureEnclaveBench/SecureEnclaveBench/ReHashToEc.swift rename to ios/RainbowSloth/Sources/RainbowSloth/ReHashToEc.swift index d6b6aa3..77b03db 100644 --- a/ios/SecureEnclaveBench/SecureEnclaveBench/ReHashToEc.swift +++ b/ios/RainbowSloth/Sources/RainbowSloth/ReHashToEc.swift @@ -1,8 +1,10 @@ import CryptoKit import Foundation +/// Helper functions for creating and manipulating P256 keys. public struct ReHashToEc { + /// Deterministically maps an input `seed` value to a P256 `SecKey`. public static func rehashToP256(seed: Data) -> SecKey { let salt = Data() let info = Data() @@ -10,7 +12,7 @@ public struct ReHashToEc { while (true) { let seedString = "\(seed.toHex)\(counter)" let currentSeed = seedString.data(using: .ascii)! - var arr = HkdfSha256.derive(salt: salt, ikm: currentSeed, info: info, l: 33) + var arr = HkdfSha256.derive(salt: salt, ikm: currentSeed, info: info, outputLength: 33) arr[0] = 0x02 | (arr[0] & 0x01) // try to convert and for any failure restart the loop with an incremented counter @@ -27,7 +29,8 @@ public struct ReHashToEc { } } - public static func convertCompressedToX963(data: Data) throws -> Data { + /// Convert a P256 key from its compressed representation to the X963 represeantation that is expected for importing it the iOS APIs. + internal static func convertCompressedToX963(data: Data) throws -> Data { // Unfortunately, iOS only added support for the SEC1-style compressed representation // in iOS 16. That works as expected on an array with 33 bytes with the first one being 0x02/0x03 // to indicate which of the possible Y values to choose. @@ -47,14 +50,14 @@ public struct ReHashToEc { } } - static func convertCompressedToX963_below16(data: Data) throws -> Data { + internal static func convertCompressedToX963_below16(data: Data) throws -> Data { // drop the first byte from the compressed SEC-1 representation for Apple's special compact representation let trimmedData = data.subdata(in: 1.. Data { + internal static func convertCompressedToX963_16andAbove(data: Data) throws -> Data { return try P256.Signing.PublicKey.init(compressedRepresentation: data).x963Representation } } diff --git a/ios/SecureEnclaveBench/SecureEnclaveBench/SecureEnclave.swift b/ios/RainbowSloth/Sources/RainbowSloth/SecureEnclave.swift similarity index 92% rename from ios/SecureEnclaveBench/SecureEnclaveBench/SecureEnclave.swift rename to ios/RainbowSloth/Sources/RainbowSloth/SecureEnclave.swift index eb14be8..49e1556 100644 --- a/ios/SecureEnclaveBench/SecureEnclaveBench/SecureEnclave.swift +++ b/ios/RainbowSloth/Sources/RainbowSloth/SecureEnclave.swift @@ -1,6 +1,6 @@ import Foundation -enum PdeSeError: Error { +enum SlothSecureEnclaveError: Error { case loadFailed(String) case genFailed(String) case ecdhFailed(String) @@ -10,7 +10,7 @@ public struct SecureEnclave { public static func runEval(iterations: Int) throws -> [Double] { // create keys to play with - try resetSecretSeKey() + try! resetSecretSeKey() let secretSeKey = try! loadSecretSeKey() debugPrint("secretSeKey", secretSeKey) @@ -74,13 +74,13 @@ public struct SecureEnclave { var pubKey, secretKey: SecKey? let status = SecKeyGeneratePair(pairAttributes as CFDictionary, &pubKey, &secretKey) guard status == errSecSuccess else { - throw PdeSeError.genFailed("generating random public key failed") + throw SlothSecureEnclaveError.genFailed("generating random public key failed") } return pubKey! } - public static func loadSecretSeKey(handle: String = "sloth") throws -> SecKey { + public static func loadSecretSeKey(handle: String = "sloth_default") throws -> SecKey { let query: NSDictionary = [ kSecClass: kSecClassKey, kSecAttrApplicationTag: handle, @@ -91,12 +91,12 @@ public struct SecureEnclave { var item: CFTypeRef? let status = SecItemCopyMatching(query as CFDictionary, &item) guard status == errSecSuccess else { - throw PdeSeError.loadFailed("load failed") + throw SlothSecureEnclaveError.loadFailed("load failed") } return item as! SecKey } - public static func resetSecretSeKey(handle: String = "sloth") throws { + public static func resetSecretSeKey(handle: String = "sloth_default") throws { // (1) delete existing key (if any) under the given handle, as create does not // overwrite existing keys let query: NSDictionary = [ diff --git a/ios/SecureEnclaveBench/SecureEnclaveBench/Utils.swift b/ios/RainbowSloth/Sources/RainbowSloth/Utils.swift similarity index 74% rename from ios/SecureEnclaveBench/SecureEnclaveBench/Utils.swift rename to ios/RainbowSloth/Sources/RainbowSloth/Utils.swift index b7c9bd9..aaad8e2 100644 --- a/ios/SecureEnclaveBench/SecureEnclaveBench/Utils.swift +++ b/ios/RainbowSloth/Sources/RainbowSloth/Utils.swift @@ -1,14 +1,9 @@ import Foundation -public func randomSalt(l: Int = 32) -> Data { - var bytes = [UInt8](repeating: 0, count: l) - let result = SecRandomCopyBytes(kSecRandomDefault, bytes.count, &bytes) - assert(result == errSecSuccess, "Failed to generate random bytes") - return Data(bytes) -} - public extension Data { + + /// Creates a new `Data` object initialized with bytes decoded from the provided hexadecimal-encoded String. init(hex: String) { let l = hex.count / 2 var data = Data(capacity: l) @@ -23,11 +18,13 @@ public extension Data { self = data } + /// Returns a hexadecimal-encoded version of this `Data` object. var toHex: String { return map { String(format: "%02x", $0) } .joined() } + /// Splits this array into arrays that each have `length` bytes. Throws if the `.count` of this object cannot be evenly divided. func chunkify(length: Int) -> [Data] { precondition(self.count % length == 0, "Data is not evenly divisible by chunk size.") let count = self.count / length @@ -41,6 +38,7 @@ public extension Data { return result } + /// Concatenates all given `chunks` to create a new `Data` object. static func combine(chunks: [Data]) -> Data { var result = Data() for chunk in chunks { diff --git a/ios/SecureEnclaveBench/SecureEnclaveBenchTests/HkdfTests.swift b/ios/RainbowSloth/Tests/RainbowSlothTests/HkdfTests.swift similarity index 93% rename from ios/SecureEnclaveBench/SecureEnclaveBenchTests/HkdfTests.swift rename to ios/RainbowSloth/Tests/RainbowSlothTests/HkdfTests.swift index 7bacfda..3ac9ca9 100644 --- a/ios/SecureEnclaveBench/SecureEnclaveBenchTests/HkdfTests.swift +++ b/ios/RainbowSloth/Tests/RainbowSlothTests/HkdfTests.swift @@ -1,3 +1,4 @@ +import RainbowSloth import XCTest final class HkdfTests: XCTestCase { @@ -15,10 +16,9 @@ final class HkdfTests: XCTestCase { let info = Data(hex: "f0f1f2f3f4f5f6f7f8f9") let l = 42 - let actual = HkdfSha256.derive(salt: salt, ikm: ikm, info: info, l: l) + let actual = HkdfSha256.derive(salt: salt, ikm: ikm, info: info, outputLength: l) let expected = Data(hex: "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865") XCTAssertEqual(actual, expected) } - } diff --git a/ios/RainbowSloth/Tests/RainbowSlothTests/PwHashTests.swift b/ios/RainbowSloth/Tests/RainbowSlothTests/PwHashTests.swift new file mode 100644 index 0000000..9b4e0b0 --- /dev/null +++ b/ios/RainbowSloth/Tests/RainbowSlothTests/PwHashTests.swift @@ -0,0 +1,46 @@ +import RainbowSloth +import XCTest + +final class PwHashTests: XCTestCase { + + func testPwHashOutputLengthMatches() throws { + let pw = "test".data(using: .utf8)! + let salt = Data(hex: "0123456789ABCDEF0123456789ABCDEF") + + let res = PwHash.derive(salt: salt, pw: pw, outputLength: 42) + + XCTAssertEqual(res.count, 42) + } + + func testPwHashDifferentPasswordsDifferentOutput() throws { + let pw1 = "test".data(using: .utf8)! + let pw2 = "test2".data(using: .utf8)! + let salt = Data(hex: "0123456789ABCDEF0123456789ABCDEF") + + let res1 = PwHash.derive(salt: salt, pw: pw1, outputLength: 32) + let res2 = PwHash.derive(salt: salt, pw: pw2, outputLength: 32) + + XCTAssertNotEqual(res1, res2) + } + + func testPwHashDifferentSaltsDifferentOutput() throws { + let pw = "test".data(using: .utf8)! + let salt1 = Data(hex: "0123456789ABCDEF0123456789ABCDEF") + let salt2 = Data(hex: "F123456789ABCDEF0123456789ABCDEF") + + let res1 = PwHash.derive(salt: salt1, pw: pw, outputLength: 32) + let res2 = PwHash.derive(salt: salt2, pw: pw, outputLength: 32) + + XCTAssertNotEqual(res1, res2) + } + + func testPwHashSameParametersSameOutput() throws { + let pw = "test".data(using: .utf8)! + let salt = Data(hex: "0123456789ABCDEF0123456789ABCDEF") + + let res1 = PwHash.derive(salt: salt, pw: pw, outputLength: 32) + let res2 = PwHash.derive(salt: salt, pw: pw, outputLength: 32) + + XCTAssertEqual(res1, res2) + } +} diff --git a/ios/SecureEnclaveBench/SecureEnclaveBenchTests/ReHashToEcTests.swift b/ios/RainbowSloth/Tests/RainbowSlothTests/ReHashToEcTests.swift similarity index 96% rename from ios/SecureEnclaveBench/SecureEnclaveBenchTests/ReHashToEcTests.swift rename to ios/RainbowSloth/Tests/RainbowSlothTests/ReHashToEcTests.swift index 92f060a..d8af441 100644 --- a/ios/SecureEnclaveBench/SecureEnclaveBenchTests/ReHashToEcTests.swift +++ b/ios/RainbowSloth/Tests/RainbowSlothTests/ReHashToEcTests.swift @@ -1,3 +1,4 @@ +import RainbowSloth import XCTest final class ReHashToEcTests: XCTestCase { diff --git a/ios/SecureEnclaveBench/Podfile b/ios/SecureEnclaveBench/Podfile deleted file mode 100644 index d1eeb60..0000000 --- a/ios/SecureEnclaveBench/Podfile +++ /dev/null @@ -1,9 +0,0 @@ -target 'SecureEnclaveBench' do - use_frameworks! - - pod 'Argon2Swift' - - target 'SecureEnclaveBenchTests' do - inherit! :search_paths - end -end diff --git a/ios/SecureEnclaveBench/Podfile.lock b/ios/SecureEnclaveBench/Podfile.lock deleted file mode 100644 index b57ee97..0000000 --- a/ios/SecureEnclaveBench/Podfile.lock +++ /dev/null @@ -1,16 +0,0 @@ -PODS: - - Argon2Swift (1.0.4) - -DEPENDENCIES: - - Argon2Swift - -SPEC REPOS: - trunk: - - Argon2Swift - -SPEC CHECKSUMS: - Argon2Swift: 295b8bde7ba61434f227f5610b8813c42e866f74 - -PODFILE CHECKSUM: 90b18f464c3efd9874647c7ef11d7efc2efa01c3 - -COCOAPODS: 1.12.0 diff --git a/ios/SecureEnclaveBench/SecureEnclaveBench.xcodeproj/project.pbxproj b/ios/SecureEnclaveBench/SecureEnclaveBench.xcodeproj/project.pbxproj deleted file mode 100644 index fd689ca..0000000 --- a/ios/SecureEnclaveBench/SecureEnclaveBench.xcodeproj/project.pbxproj +++ /dev/null @@ -1,630 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 56; - objects = { - -/* Begin PBXBuildFile section */ - 3003F74329C5B6A6001D48FC /* RainbowSloth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3003F74229C5B6A6001D48FC /* RainbowSloth.swift */; }; - 3003F74429C5B6A6001D48FC /* RainbowSloth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3003F74229C5B6A6001D48FC /* RainbowSloth.swift */; }; - 300DBA6129AE463C007DA9A6 /* Hkdf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 300DBA6029AE463C007DA9A6 /* Hkdf.swift */; }; - 300DBA6329AE4B44007DA9A6 /* HkdfTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 300DBA6229AE4B44007DA9A6 /* HkdfTests.swift */; }; - 300DBA6429AE53A5007DA9A6 /* Hkdf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 300DBA6029AE463C007DA9A6 /* Hkdf.swift */; }; - 300DBA6629AE54F2007DA9A6 /* SecureEnclaveTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 300DBA6529AE54F2007DA9A6 /* SecureEnclaveTests.swift */; }; - 303ADED029700A3B005E3023 /* SecureEnclave.swift in Sources */ = {isa = PBXBuildFile; fileRef = 303ADECF29700A3B005E3023 /* SecureEnclave.swift */; }; - 303ADED2297026D7005E3023 /* UIDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 303ADED1297026D7005E3023 /* UIDevice.swift */; }; - 30850551296F1A6800FFB481 /* SecureEnclaveBenchApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30850550296F1A6800FFB481 /* SecureEnclaveBenchApp.swift */; }; - 30850553296F1A6800FFB481 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30850552296F1A6800FFB481 /* ContentView.swift */; }; - 30850555296F1A6A00FFB481 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 30850554296F1A6A00FFB481 /* Assets.xcassets */; }; - 30850558296F1A6A00FFB481 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 30850557296F1A6A00FFB481 /* Preview Assets.xcassets */; }; - 30D3BC8829C5F8BA004F6DFD /* PwHash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D3BC8729C5F8BA004F6DFD /* PwHash.swift */; }; - 30D3BC8929C5F8BA004F6DFD /* PwHash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D3BC8729C5F8BA004F6DFD /* PwHash.swift */; }; - 30D3BC8B29C5FB4F004F6DFD /* PwHashTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D3BC8A29C5FB4F004F6DFD /* PwHashTests.swift */; }; - 30D3BC8D29C5FEEC004F6DFD /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D3BC8C29C5FEEC004F6DFD /* Utils.swift */; }; - 30D3BC8E29C5FEEC004F6DFD /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D3BC8C29C5FEEC004F6DFD /* Utils.swift */; }; - 30D3BC9029C603FE004F6DFD /* RainbowSlothTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D3BC8F29C603FE004F6DFD /* RainbowSlothTests.swift */; }; - 30E01BB329B0EF01002D05DC /* SecureEnclave.swift in Sources */ = {isa = PBXBuildFile; fileRef = 303ADECF29700A3B005E3023 /* SecureEnclave.swift */; }; - 30E01BB529B0F80E002D05DC /* ReHashToEc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30E01BB429B0F80E002D05DC /* ReHashToEc.swift */; }; - 30E01BB629B0F80E002D05DC /* ReHashToEc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30E01BB429B0F80E002D05DC /* ReHashToEc.swift */; }; - 30E01BB829B10758002D05DC /* ReHashToEcTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30E01BB729B10758002D05DC /* ReHashToEcTests.swift */; }; - 40EFAA80359694B09071DCD0 /* Pods_SecureEnclaveBench.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7E5577059410859844DECB3 /* Pods_SecureEnclaveBench.framework */; }; - E816CCFCC678E33C1456463E /* Pods_SecureEnclaveBenchTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7896F15D3F3E08E274B44876 /* Pods_SecureEnclaveBenchTests.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 3085055E296F1A6A00FFB481 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 30850545296F1A6800FFB481 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3085054C296F1A6800FFB481; - remoteInfo = SecureEnclaveBench; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 3003F74229C5B6A6001D48FC /* RainbowSloth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RainbowSloth.swift; sourceTree = ""; }; - 300DBA6029AE463C007DA9A6 /* Hkdf.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Hkdf.swift; sourceTree = ""; }; - 300DBA6229AE4B44007DA9A6 /* HkdfTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HkdfTests.swift; sourceTree = ""; }; - 300DBA6529AE54F2007DA9A6 /* SecureEnclaveTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureEnclaveTests.swift; sourceTree = ""; }; - 303ADECF29700A3B005E3023 /* SecureEnclave.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureEnclave.swift; sourceTree = ""; }; - 303ADED1297026D7005E3023 /* UIDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIDevice.swift; sourceTree = ""; }; - 3056BB0DFF210673FF054D85 /* Pods-SecureEnclaveBenchTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SecureEnclaveBenchTests.release.xcconfig"; path = "Target Support Files/Pods-SecureEnclaveBenchTests/Pods-SecureEnclaveBenchTests.release.xcconfig"; sourceTree = ""; }; - 3085054D296F1A6800FFB481 /* SecureEnclaveBench.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SecureEnclaveBench.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 30850550296F1A6800FFB481 /* SecureEnclaveBenchApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureEnclaveBenchApp.swift; sourceTree = ""; }; - 30850552296F1A6800FFB481 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; - 30850554296F1A6A00FFB481 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 30850557296F1A6A00FFB481 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; - 3085055D296F1A6A00FFB481 /* SecureEnclaveBenchTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SecureEnclaveBenchTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 30D3BC8729C5F8BA004F6DFD /* PwHash.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PwHash.swift; sourceTree = ""; }; - 30D3BC8A29C5FB4F004F6DFD /* PwHashTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PwHashTests.swift; sourceTree = ""; }; - 30D3BC8C29C5FEEC004F6DFD /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = ""; }; - 30D3BC8F29C603FE004F6DFD /* RainbowSlothTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RainbowSlothTests.swift; sourceTree = ""; }; - 30E01BB429B0F80E002D05DC /* ReHashToEc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReHashToEc.swift; sourceTree = ""; }; - 30E01BB729B10758002D05DC /* ReHashToEcTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReHashToEcTests.swift; sourceTree = ""; }; - 7896F15D3F3E08E274B44876 /* Pods_SecureEnclaveBenchTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SecureEnclaveBenchTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 8E36CE7BC39DE6058CD8F830 /* Pods-SecureEnclaveBench.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SecureEnclaveBench.debug.xcconfig"; path = "Target Support Files/Pods-SecureEnclaveBench/Pods-SecureEnclaveBench.debug.xcconfig"; sourceTree = ""; }; - A8C6A422BF7C92F896CF025D /* Pods-SecureEnclaveBenchTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SecureEnclaveBenchTests.debug.xcconfig"; path = "Target Support Files/Pods-SecureEnclaveBenchTests/Pods-SecureEnclaveBenchTests.debug.xcconfig"; sourceTree = ""; }; - C7E2EFB1A1538986901492EC /* Pods-SecureEnclaveBench.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SecureEnclaveBench.release.xcconfig"; path = "Target Support Files/Pods-SecureEnclaveBench/Pods-SecureEnclaveBench.release.xcconfig"; sourceTree = ""; }; - F7E5577059410859844DECB3 /* Pods_SecureEnclaveBench.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SecureEnclaveBench.framework; sourceTree = BUILT_PRODUCTS_DIR; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 3085054A296F1A6800FFB481 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 40EFAA80359694B09071DCD0 /* Pods_SecureEnclaveBench.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3085055A296F1A6A00FFB481 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - E816CCFCC678E33C1456463E /* Pods_SecureEnclaveBenchTests.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 30850544296F1A6800FFB481 = { - isa = PBXGroup; - children = ( - 3085054F296F1A6800FFB481 /* SecureEnclaveBench */, - 30850560296F1A6A00FFB481 /* SecureEnclaveBenchTests */, - 3085054E296F1A6800FFB481 /* Products */, - DBD0D1FECE377AF3FF326C76 /* Pods */, - C38E7772D1F0A77A64F74333 /* Frameworks */, - ); - sourceTree = ""; - }; - 3085054E296F1A6800FFB481 /* Products */ = { - isa = PBXGroup; - children = ( - 3085054D296F1A6800FFB481 /* SecureEnclaveBench.app */, - 3085055D296F1A6A00FFB481 /* SecureEnclaveBenchTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 3085054F296F1A6800FFB481 /* SecureEnclaveBench */ = { - isa = PBXGroup; - children = ( - 30850550296F1A6800FFB481 /* SecureEnclaveBenchApp.swift */, - 30850552296F1A6800FFB481 /* ContentView.swift */, - 30850554296F1A6A00FFB481 /* Assets.xcassets */, - 30850556296F1A6A00FFB481 /* Preview Content */, - 303ADECF29700A3B005E3023 /* SecureEnclave.swift */, - 303ADED1297026D7005E3023 /* UIDevice.swift */, - 300DBA6029AE463C007DA9A6 /* Hkdf.swift */, - 30E01BB429B0F80E002D05DC /* ReHashToEc.swift */, - 3003F74229C5B6A6001D48FC /* RainbowSloth.swift */, - 30D3BC8729C5F8BA004F6DFD /* PwHash.swift */, - 30D3BC8C29C5FEEC004F6DFD /* Utils.swift */, - ); - path = SecureEnclaveBench; - sourceTree = ""; - }; - 30850556296F1A6A00FFB481 /* Preview Content */ = { - isa = PBXGroup; - children = ( - 30850557296F1A6A00FFB481 /* Preview Assets.xcassets */, - ); - path = "Preview Content"; - sourceTree = ""; - }; - 30850560296F1A6A00FFB481 /* SecureEnclaveBenchTests */ = { - isa = PBXGroup; - children = ( - 300DBA6229AE4B44007DA9A6 /* HkdfTests.swift */, - 30D3BC8A29C5FB4F004F6DFD /* PwHashTests.swift */, - 300DBA6529AE54F2007DA9A6 /* SecureEnclaveTests.swift */, - 30E01BB729B10758002D05DC /* ReHashToEcTests.swift */, - 30D3BC8F29C603FE004F6DFD /* RainbowSlothTests.swift */, - ); - path = SecureEnclaveBenchTests; - sourceTree = ""; - }; - C38E7772D1F0A77A64F74333 /* Frameworks */ = { - isa = PBXGroup; - children = ( - F7E5577059410859844DECB3 /* Pods_SecureEnclaveBench.framework */, - 7896F15D3F3E08E274B44876 /* Pods_SecureEnclaveBenchTests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - DBD0D1FECE377AF3FF326C76 /* Pods */ = { - isa = PBXGroup; - children = ( - 8E36CE7BC39DE6058CD8F830 /* Pods-SecureEnclaveBench.debug.xcconfig */, - C7E2EFB1A1538986901492EC /* Pods-SecureEnclaveBench.release.xcconfig */, - A8C6A422BF7C92F896CF025D /* Pods-SecureEnclaveBenchTests.debug.xcconfig */, - 3056BB0DFF210673FF054D85 /* Pods-SecureEnclaveBenchTests.release.xcconfig */, - ); - path = Pods; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 3085054C296F1A6800FFB481 /* SecureEnclaveBench */ = { - isa = PBXNativeTarget; - buildConfigurationList = 30850571296F1A6A00FFB481 /* Build configuration list for PBXNativeTarget "SecureEnclaveBench" */; - buildPhases = ( - B3E35FBEE635C2F3E3DEB0EB /* [CP] Check Pods Manifest.lock */, - 30850549296F1A6800FFB481 /* Sources */, - 3085054A296F1A6800FFB481 /* Frameworks */, - 3085054B296F1A6800FFB481 /* Resources */, - B4AA9042F58316AE5F77AB8C /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = SecureEnclaveBench; - productName = SecureEnclaveBench; - productReference = 3085054D296F1A6800FFB481 /* SecureEnclaveBench.app */; - productType = "com.apple.product-type.application"; - }; - 3085055C296F1A6A00FFB481 /* SecureEnclaveBenchTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 30850574296F1A6A00FFB481 /* Build configuration list for PBXNativeTarget "SecureEnclaveBenchTests" */; - buildPhases = ( - 28FDBC4A90A64965F6BC3E42 /* [CP] Check Pods Manifest.lock */, - 30850559296F1A6A00FFB481 /* Sources */, - 3085055A296F1A6A00FFB481 /* Frameworks */, - 3085055B296F1A6A00FFB481 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 3085055F296F1A6A00FFB481 /* PBXTargetDependency */, - ); - name = SecureEnclaveBenchTests; - productName = SecureEnclaveBenchTests; - productReference = 3085055D296F1A6A00FFB481 /* SecureEnclaveBenchTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 30850545296F1A6800FFB481 /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = 1; - LastSwiftUpdateCheck = 1420; - LastUpgradeCheck = 1420; - TargetAttributes = { - 3085054C296F1A6800FFB481 = { - CreatedOnToolsVersion = 14.2; - }; - 3085055C296F1A6A00FFB481 = { - CreatedOnToolsVersion = 14.2; - TestTargetID = 3085054C296F1A6800FFB481; - }; - }; - }; - buildConfigurationList = 30850548296F1A6800FFB481 /* Build configuration list for PBXProject "SecureEnclaveBench" */; - compatibilityVersion = "Xcode 14.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 30850544296F1A6800FFB481; - productRefGroup = 3085054E296F1A6800FFB481 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 3085054C296F1A6800FFB481 /* SecureEnclaveBench */, - 3085055C296F1A6A00FFB481 /* SecureEnclaveBenchTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 3085054B296F1A6800FFB481 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 30850558296F1A6A00FFB481 /* Preview Assets.xcassets in Resources */, - 30850555296F1A6A00FFB481 /* Assets.xcassets in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3085055B296F1A6A00FFB481 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 28FDBC4A90A64965F6BC3E42 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-SecureEnclaveBenchTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - B3E35FBEE635C2F3E3DEB0EB /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-SecureEnclaveBench-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - B4AA9042F58316AE5F77AB8C /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-SecureEnclaveBench/Pods-SecureEnclaveBench-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-SecureEnclaveBench/Pods-SecureEnclaveBench-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SecureEnclaveBench/Pods-SecureEnclaveBench-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 30850549296F1A6800FFB481 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 303ADED029700A3B005E3023 /* SecureEnclave.swift in Sources */, - 30850553296F1A6800FFB481 /* ContentView.swift in Sources */, - 30D3BC8D29C5FEEC004F6DFD /* Utils.swift in Sources */, - 30850551296F1A6800FFB481 /* SecureEnclaveBenchApp.swift in Sources */, - 300DBA6129AE463C007DA9A6 /* Hkdf.swift in Sources */, - 303ADED2297026D7005E3023 /* UIDevice.swift in Sources */, - 3003F74329C5B6A6001D48FC /* RainbowSloth.swift in Sources */, - 30D3BC8829C5F8BA004F6DFD /* PwHash.swift in Sources */, - 30E01BB529B0F80E002D05DC /* ReHashToEc.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 30850559296F1A6A00FFB481 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 300DBA6329AE4B44007DA9A6 /* HkdfTests.swift in Sources */, - 30E01BB329B0EF01002D05DC /* SecureEnclave.swift in Sources */, - 30D3BC8B29C5FB4F004F6DFD /* PwHashTests.swift in Sources */, - 30D3BC9029C603FE004F6DFD /* RainbowSlothTests.swift in Sources */, - 300DBA6429AE53A5007DA9A6 /* Hkdf.swift in Sources */, - 300DBA6629AE54F2007DA9A6 /* SecureEnclaveTests.swift in Sources */, - 30D3BC8E29C5FEEC004F6DFD /* Utils.swift in Sources */, - 30E01BB629B0F80E002D05DC /* ReHashToEc.swift in Sources */, - 3003F74429C5B6A6001D48FC /* RainbowSloth.swift in Sources */, - 30D3BC8929C5F8BA004F6DFD /* PwHash.swift in Sources */, - 30E01BB829B10758002D05DC /* ReHashToEcTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 3085055F296F1A6A00FFB481 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3085054C296F1A6800FFB481 /* SecureEnclaveBench */; - targetProxy = 3085055E296F1A6A00FFB481 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 3085056F296F1A6A00FFB481 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 30850570296F1A6A00FFB481 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SDKROOT = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 30850572296F1A6A00FFB481 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 8E36CE7BC39DE6058CD8F830 /* Pods-SecureEnclaveBench.debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_ASSET_PATHS = "\"SecureEnclaveBench/Preview Content\""; - DEVELOPMENT_TEAM = 48XKGWFXVN; - ENABLE_PREVIEWS = YES; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; - INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; - INFOPLIST_KEY_UILaunchScreen_Generation = YES; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.lambdapioneer.pdese.SecureEnclaveBench; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 30850573296F1A6A00FFB481 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = C7E2EFB1A1538986901492EC /* Pods-SecureEnclaveBench.release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_ASSET_PATHS = "\"SecureEnclaveBench/Preview Content\""; - DEVELOPMENT_TEAM = 48XKGWFXVN; - ENABLE_PREVIEWS = YES; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; - INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; - INFOPLIST_KEY_UILaunchScreen_Generation = YES; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.lambdapioneer.pdese.SecureEnclaveBench; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; - 30850575296F1A6A00FFB481 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = A8C6A422BF7C92F896CF025D /* Pods-SecureEnclaveBenchTests.debug.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 48XKGWFXVN; - GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.lambdapioneer.pdese.SecureEnclaveBenchTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SecureEnclaveBench.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/SecureEnclaveBench"; - }; - name = Debug; - }; - 30850576296F1A6A00FFB481 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 3056BB0DFF210673FF054D85 /* Pods-SecureEnclaveBenchTests.release.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 48XKGWFXVN; - GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.lambdapioneer.pdese.SecureEnclaveBenchTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SecureEnclaveBench.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/SecureEnclaveBench"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 30850548296F1A6800FFB481 /* Build configuration list for PBXProject "SecureEnclaveBench" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3085056F296F1A6A00FFB481 /* Debug */, - 30850570296F1A6A00FFB481 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 30850571296F1A6A00FFB481 /* Build configuration list for PBXNativeTarget "SecureEnclaveBench" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 30850572296F1A6A00FFB481 /* Debug */, - 30850573296F1A6A00FFB481 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 30850574296F1A6A00FFB481 /* Build configuration list for PBXNativeTarget "SecureEnclaveBenchTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 30850575296F1A6A00FFB481 /* Debug */, - 30850576296F1A6A00FFB481 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 30850545296F1A6800FFB481 /* Project object */; -} diff --git a/ios/SecureEnclaveBench/SecureEnclaveBench.xcworkspace/contents.xcworkspacedata b/ios/SecureEnclaveBench/SecureEnclaveBench.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index d57603f..0000000 --- a/ios/SecureEnclaveBench/SecureEnclaveBench.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/ios/SecureEnclaveBench/SecureEnclaveBench.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/SecureEnclaveBench/SecureEnclaveBench.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/ios/SecureEnclaveBench/SecureEnclaveBench.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/ios/SecureEnclaveBench/SecureEnclaveBench/PwHash.swift b/ios/SecureEnclaveBench/SecureEnclaveBench/PwHash.swift deleted file mode 100644 index 3a488b1..0000000 --- a/ios/SecureEnclaveBench/SecureEnclaveBench/PwHash.swift +++ /dev/null @@ -1,19 +0,0 @@ -import Argon2Swift -import Foundation - -public struct PwHash { - public static func derive(salt: Data, pw: String, l: Int) -> Data { - // OWASP: "Use Argon2id with a minimum configuration of 19 MiB of memory, an iteration count of 2, and 1 degree of parallelism." - let res = try! Argon2Swift.hashPasswordString( - password: pw, - salt: Salt(bytes: salt), - iterations: 2, - memory: 19*1024, // 19 MiB - parallelism: 1, - length: l, - type: Argon2Type.id - ) - - return res.hashData() - } -} diff --git a/ios/SecureEnclaveBench/SecureEnclaveBenchTests/PwHashTests.swift b/ios/SecureEnclaveBench/SecureEnclaveBenchTests/PwHashTests.swift deleted file mode 100644 index 7a9a1a8..0000000 --- a/ios/SecureEnclaveBench/SecureEnclaveBenchTests/PwHashTests.swift +++ /dev/null @@ -1,13 +0,0 @@ -import XCTest - -final class PwHashTests: XCTestCase { - - func testArgon2OutputLengthMatches() throws { - let pw = "test" - let salt = Data(hex: "0123456789ABCDEF0123456789ABCDEF") - - let res = PwHash.derive(salt: salt, pw: pw, l: 42) - - XCTAssertEqual(res.count, 42) - } -} diff --git a/ios/Sloth/.gitignore b/ios/Sloth/.gitignore new file mode 100644 index 0000000..0023a53 --- /dev/null +++ b/ios/Sloth/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/ios/Sloth/Sloth.xcodeproj/project.pbxproj b/ios/Sloth/Sloth.xcodeproj/project.pbxproj new file mode 100644 index 0000000..98c0bef --- /dev/null +++ b/ios/Sloth/Sloth.xcodeproj/project.pbxproj @@ -0,0 +1,511 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + 29AAF9C12B0B55A800E12423 /* SlothApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29AAF9C02B0B55A800E12423 /* SlothApp.swift */; }; + 29AAF9C32B0B55A800E12423 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29AAF9C22B0B55A800E12423 /* ContentView.swift */; }; + 29AAF9C52B0B55A900E12423 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 29AAF9C42B0B55A900E12423 /* Assets.xcassets */; }; + 29AAF9C82B0B55A900E12423 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 29AAF9C72B0B55A900E12423 /* Preview Assets.xcassets */; }; + 29AAF9EE2B0B5FA400E12423 /* RainbowSlothTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29AAF9ED2B0B5FA400E12423 /* RainbowSlothTests.swift */; }; + 29AAF9F02B0B5FF700E12423 /* SecureEnclaveTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29AAF9EF2B0B5FF700E12423 /* SecureEnclaveTests.swift */; }; + 29AAF9F22B0B618300E12423 /* UIDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29AAF9F12B0B618300E12423 /* UIDevice.swift */; }; + 29AAF9F52B0B61AC00E12423 /* RainbowSloth in Frameworks */ = {isa = PBXBuildFile; productRef = 29AAF9F42B0B61AC00E12423 /* RainbowSloth */; }; + 29AAF9F72B0B624200E12423 /* RainbowSloth in Frameworks */ = {isa = PBXBuildFile; productRef = 29AAF9F62B0B624200E12423 /* RainbowSloth */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 29AAF9CE2B0B55A900E12423 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29AAF9B52B0B55A800E12423 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 29AAF9BC2B0B55A800E12423; + remoteInfo = Sloth; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 29AAF9BD2B0B55A800E12423 /* Sloth.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sloth.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 29AAF9C02B0B55A800E12423 /* SlothApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SlothApp.swift; sourceTree = ""; }; + 29AAF9C22B0B55A800E12423 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + 29AAF9C42B0B55A900E12423 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 29AAF9C72B0B55A900E12423 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 29AAF9CD2B0B55A900E12423 /* SlothTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SlothTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 29AAF9EA2B0B55F300E12423 /* RainbowSloth */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = RainbowSloth; path = ../../RainbowSloth; sourceTree = ""; }; + 29AAF9ED2B0B5FA400E12423 /* RainbowSlothTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RainbowSlothTests.swift; sourceTree = ""; }; + 29AAF9EF2B0B5FF700E12423 /* SecureEnclaveTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureEnclaveTests.swift; sourceTree = ""; }; + 29AAF9F12B0B618300E12423 /* UIDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIDevice.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 29AAF9BA2B0B55A800E12423 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 29AAF9F52B0B61AC00E12423 /* RainbowSloth in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 29AAF9CA2B0B55A900E12423 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 29AAF9F72B0B624200E12423 /* RainbowSloth in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 29AAF9B42B0B55A800E12423 = { + isa = PBXGroup; + children = ( + 29AAF9BF2B0B55A800E12423 /* Sloth */, + 29AAF9D02B0B55A900E12423 /* SlothTests */, + 29AAF9BE2B0B55A800E12423 /* Products */, + 29AAF9F32B0B61AC00E12423 /* Frameworks */, + ); + sourceTree = ""; + }; + 29AAF9BE2B0B55A800E12423 /* Products */ = { + isa = PBXGroup; + children = ( + 29AAF9BD2B0B55A800E12423 /* Sloth.app */, + 29AAF9CD2B0B55A900E12423 /* SlothTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 29AAF9BF2B0B55A800E12423 /* Sloth */ = { + isa = PBXGroup; + children = ( + 29AAF9EA2B0B55F300E12423 /* RainbowSloth */, + 29AAF9C02B0B55A800E12423 /* SlothApp.swift */, + 29AAF9C22B0B55A800E12423 /* ContentView.swift */, + 29AAF9F12B0B618300E12423 /* UIDevice.swift */, + 29AAF9C42B0B55A900E12423 /* Assets.xcassets */, + 29AAF9C62B0B55A900E12423 /* Preview Content */, + ); + path = Sloth; + sourceTree = ""; + }; + 29AAF9C62B0B55A900E12423 /* Preview Content */ = { + isa = PBXGroup; + children = ( + 29AAF9C72B0B55A900E12423 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + 29AAF9D02B0B55A900E12423 /* SlothTests */ = { + isa = PBXGroup; + children = ( + 29AAF9ED2B0B5FA400E12423 /* RainbowSlothTests.swift */, + 29AAF9EF2B0B5FF700E12423 /* SecureEnclaveTests.swift */, + ); + path = SlothTests; + sourceTree = ""; + }; + 29AAF9F32B0B61AC00E12423 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 29AAF9BC2B0B55A800E12423 /* Sloth */ = { + isa = PBXNativeTarget; + buildConfigurationList = 29AAF9E12B0B55A900E12423 /* Build configuration list for PBXNativeTarget "Sloth" */; + buildPhases = ( + 29AAF9B92B0B55A800E12423 /* Sources */, + 29AAF9BA2B0B55A800E12423 /* Frameworks */, + 29AAF9BB2B0B55A800E12423 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Sloth; + packageProductDependencies = ( + 29AAF9F42B0B61AC00E12423 /* RainbowSloth */, + ); + productName = Sloth; + productReference = 29AAF9BD2B0B55A800E12423 /* Sloth.app */; + productType = "com.apple.product-type.application"; + }; + 29AAF9CC2B0B55A900E12423 /* SlothTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 29AAF9E42B0B55A900E12423 /* Build configuration list for PBXNativeTarget "SlothTests" */; + buildPhases = ( + 29AAF9C92B0B55A900E12423 /* Sources */, + 29AAF9CA2B0B55A900E12423 /* Frameworks */, + 29AAF9CB2B0B55A900E12423 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 29AAF9CF2B0B55A900E12423 /* PBXTargetDependency */, + ); + name = SlothTests; + packageProductDependencies = ( + 29AAF9F62B0B624200E12423 /* RainbowSloth */, + ); + productName = SlothTests; + productReference = 29AAF9CD2B0B55A900E12423 /* SlothTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29AAF9B52B0B55A800E12423 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1500; + LastUpgradeCheck = 1500; + TargetAttributes = { + 29AAF9BC2B0B55A800E12423 = { + CreatedOnToolsVersion = 15.0.1; + }; + 29AAF9CC2B0B55A900E12423 = { + CreatedOnToolsVersion = 15.0.1; + TestTargetID = 29AAF9BC2B0B55A800E12423; + }; + }; + }; + buildConfigurationList = 29AAF9B82B0B55A800E12423 /* Build configuration list for PBXProject "Sloth" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 29AAF9B42B0B55A800E12423; + productRefGroup = 29AAF9BE2B0B55A800E12423 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 29AAF9BC2B0B55A800E12423 /* Sloth */, + 29AAF9CC2B0B55A900E12423 /* SlothTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 29AAF9BB2B0B55A800E12423 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 29AAF9C82B0B55A900E12423 /* Preview Assets.xcassets in Resources */, + 29AAF9C52B0B55A900E12423 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 29AAF9CB2B0B55A900E12423 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 29AAF9B92B0B55A800E12423 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 29AAF9C32B0B55A800E12423 /* ContentView.swift in Sources */, + 29AAF9F22B0B618300E12423 /* UIDevice.swift in Sources */, + 29AAF9C12B0B55A800E12423 /* SlothApp.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 29AAF9C92B0B55A900E12423 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 29AAF9EE2B0B5FA400E12423 /* RainbowSlothTests.swift in Sources */, + 29AAF9F02B0B5FF700E12423 /* SecureEnclaveTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 29AAF9CF2B0B55A900E12423 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 29AAF9BC2B0B55A800E12423 /* Sloth */; + targetProxy = 29AAF9CE2B0B55A900E12423 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 29AAF9DF2B0B55A900E12423 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + 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; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 29AAF9E02B0B55A900E12423 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + 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; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 29AAF9E22B0B55A900E12423 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"Sloth/Preview Content\""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.lambdapioneer.Sloth; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 29AAF9E32B0B55A900E12423 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"Sloth/Preview Content\""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.lambdapioneer.Sloth; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 29AAF9E52B0B55A900E12423 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.lambdapioneer.SlothTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Sloth.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Sloth"; + }; + name = Debug; + }; + 29AAF9E62B0B55A900E12423 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.lambdapioneer.SlothTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Sloth.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Sloth"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 29AAF9B82B0B55A800E12423 /* Build configuration list for PBXProject "Sloth" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 29AAF9DF2B0B55A900E12423 /* Debug */, + 29AAF9E02B0B55A900E12423 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 29AAF9E12B0B55A900E12423 /* Build configuration list for PBXNativeTarget "Sloth" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 29AAF9E22B0B55A900E12423 /* Debug */, + 29AAF9E32B0B55A900E12423 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 29AAF9E42B0B55A900E12423 /* Build configuration list for PBXNativeTarget "SlothTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 29AAF9E52B0B55A900E12423 /* Debug */, + 29AAF9E62B0B55A900E12423 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCSwiftPackageProductDependency section */ + 29AAF9F42B0B61AC00E12423 /* RainbowSloth */ = { + isa = XCSwiftPackageProductDependency; + productName = RainbowSloth; + }; + 29AAF9F62B0B624200E12423 /* RainbowSloth */ = { + isa = XCSwiftPackageProductDependency; + productName = RainbowSloth; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 29AAF9B52B0B55A800E12423 /* Project object */; +} diff --git a/ios/SecureEnclaveBench/SecureEnclaveBench.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Sloth/Sloth.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from ios/SecureEnclaveBench/SecureEnclaveBench.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to ios/Sloth/Sloth.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/ios/SecureEnclaveBench/SecureEnclaveBench.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Sloth/Sloth.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from ios/SecureEnclaveBench/SecureEnclaveBench.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to ios/Sloth/Sloth.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/ios/Sloth/Sloth.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ios/Sloth/Sloth.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000..306373d --- /dev/null +++ b/ios/Sloth/Sloth.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,14 @@ +{ + "pins" : [ + { + "identity" : "swift-sodium", + "kind" : "remoteSourceControl", + "location" : "https://github.com/jedisct1/swift-sodium.git", + "state" : { + "revision" : "4f9164a0a2c9a6a7ff53a2833d54a5c79c957342", + "version" : "0.9.1" + } + } + ], + "version" : 2 +} diff --git a/ios/SecureEnclaveBench/SecureEnclaveBench/Assets.xcassets/AccentColor.colorset/Contents.json b/ios/Sloth/Sloth/Assets.xcassets/AccentColor.colorset/Contents.json similarity index 100% rename from ios/SecureEnclaveBench/SecureEnclaveBench/Assets.xcassets/AccentColor.colorset/Contents.json rename to ios/Sloth/Sloth/Assets.xcassets/AccentColor.colorset/Contents.json diff --git a/ios/SecureEnclaveBench/SecureEnclaveBench/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Sloth/Sloth/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from ios/SecureEnclaveBench/SecureEnclaveBench/Assets.xcassets/AppIcon.appiconset/Contents.json rename to ios/Sloth/Sloth/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/ios/SecureEnclaveBench/SecureEnclaveBench/Assets.xcassets/Contents.json b/ios/Sloth/Sloth/Assets.xcassets/Contents.json similarity index 100% rename from ios/SecureEnclaveBench/SecureEnclaveBench/Assets.xcassets/Contents.json rename to ios/Sloth/Sloth/Assets.xcassets/Contents.json diff --git a/ios/SecureEnclaveBench/SecureEnclaveBench/ContentView.swift b/ios/Sloth/Sloth/ContentView.swift similarity index 72% rename from ios/SecureEnclaveBench/SecureEnclaveBench/ContentView.swift rename to ios/Sloth/Sloth/ContentView.swift index 43e9482..2a50669 100644 --- a/ios/SecureEnclaveBench/SecureEnclaveBench/ContentView.swift +++ b/ios/Sloth/Sloth/ContentView.swift @@ -1,3 +1,4 @@ +import RainbowSloth import SwiftUI func runExperiment(experiment: String, n: Int, iterations: Int) throws -> [Double] { @@ -34,7 +35,9 @@ func backgroundWork(experiment: String, n: Int, iterations: Int) throws -> Strin let jsonData = try! JSONSerialization.data(withJSONObject: json) debugPrint("json", json) - // CHANGE THIS LINE TO YOUR SERVER! + // + // --> CHANGE ME <-- + // let url = URL(string: "http://127.0.0.1:8080/ios-report")! // upload @@ -62,27 +65,34 @@ struct ContentView: View { @State var taskOutput = "ready" var body: some View { - VStack { + VStack(alignment: .leading) { + Spacer() + Text("Rainbow Sloth 🦥").font(.title) + Spacer() + + Text("Experiment to run:").font(.headline) Picker("Experiment", selection: $taskSelection, content: { Text("SE-OP").tag("seop") Text("RainbowSloth").tag("sloth") }).disabled(isRunning) - - TextField("N", text:Binding( - get: { String(n) }, - set: { n = Int($0) ?? 1 } - )) - .keyboardType(.numberPad) - .disabled(taskSelection != "sloth") - - Picker("How many iterations", selection: $iterations, content: { - Text("Iterations: 1").tag(1) - Text("Iterations: 10").tag(10) - Text("Iterations: 100").tag(100) - Text("Iterations: 1000").tag(1000) + + Text("Rainbow parameter n:").font(.headline) + Picker("Rainbow parameter n", selection: $n, content: { + Text("1").tag(1) + Text("10").tag(10) + Text("100").tag(100) + Text("1000").tag(1000) + }).disabled(isRunning || taskSelection != "sloth") + + Text("Number of experiment iterations:").font(.headline) + Picker("Number of experiment iterations", selection: $iterations, content: { + Text("1").tag(1) + Text("10").tag(10) + Text("100").tag(100) + Text("1000").tag(1000) }).disabled(isRunning) - - Button("Action") { + + Button("Start run") { taskOutput = "started" isRunning = true let dispatchQueue = DispatchQueue.global(qos: .background) @@ -90,7 +100,7 @@ struct ContentView: View { do{ let output = try backgroundWork( experiment: taskSelection, - n: n, + n: Int(n), iterations: Int(iterations) ) DispatchQueue.main.async { @@ -104,18 +114,21 @@ struct ContentView: View { } } } - }.padding().disabled(isRunning) + } + .buttonStyle(.borderedProminent) + .padding().disabled(isRunning) + + Text("Status/output:").font(.headline) if isRunning { ProgressView() } - Text(taskOutput).padding() + Text(taskOutput) + Spacer() } .padding() } } -struct ContentView_Previews: PreviewProvider { - static var previews: some View { - ContentView() - } +#Preview { + ContentView() } diff --git a/ios/SecureEnclaveBench/SecureEnclaveBench/Preview Content/Preview Assets.xcassets/Contents.json b/ios/Sloth/Sloth/Preview Content/Preview Assets.xcassets/Contents.json similarity index 100% rename from ios/SecureEnclaveBench/SecureEnclaveBench/Preview Content/Preview Assets.xcassets/Contents.json rename to ios/Sloth/Sloth/Preview Content/Preview Assets.xcassets/Contents.json diff --git a/ios/SecureEnclaveBench/SecureEnclaveBench/SecureEnclaveBenchApp.swift b/ios/Sloth/Sloth/SlothApp.swift similarity index 76% rename from ios/SecureEnclaveBench/SecureEnclaveBench/SecureEnclaveBenchApp.swift rename to ios/Sloth/Sloth/SlothApp.swift index 063100e..6ac4c1c 100644 --- a/ios/SecureEnclaveBench/SecureEnclaveBench/SecureEnclaveBenchApp.swift +++ b/ios/Sloth/Sloth/SlothApp.swift @@ -1,7 +1,7 @@ import SwiftUI @main -struct SecureEnclaveBenchApp: App { +struct SlothApp: App { var body: some Scene { WindowGroup { ContentView() diff --git a/ios/SecureEnclaveBench/SecureEnclaveBench/UIDevice.swift b/ios/Sloth/Sloth/UIDevice.swift similarity index 100% rename from ios/SecureEnclaveBench/SecureEnclaveBench/UIDevice.swift rename to ios/Sloth/Sloth/UIDevice.swift diff --git a/ios/SecureEnclaveBench/SecureEnclaveBenchTests/RainbowSlothTests.swift b/ios/Sloth/SlothTests/RainbowSlothTests.swift similarity index 95% rename from ios/SecureEnclaveBench/SecureEnclaveBenchTests/RainbowSlothTests.swift rename to ios/Sloth/SlothTests/RainbowSlothTests.swift index 5b7c1e4..6f56fc8 100644 --- a/ios/SecureEnclaveBench/SecureEnclaveBenchTests/RainbowSlothTests.swift +++ b/ios/Sloth/SlothTests/RainbowSlothTests.swift @@ -1,5 +1,7 @@ +import RainbowSloth import XCTest +/// These tests must live in a target of an app to get the right entitlements to access the key chain / SecureEnclave. final class RainbowSlothTests: XCTestCase { func testWorksWithLargeN() throws { diff --git a/ios/SecureEnclaveBench/SecureEnclaveBenchTests/SecureEnclaveTests.swift b/ios/Sloth/SlothTests/SecureEnclaveTests.swift similarity index 92% rename from ios/SecureEnclaveBench/SecureEnclaveBenchTests/SecureEnclaveTests.swift rename to ios/Sloth/SlothTests/SecureEnclaveTests.swift index 76782d2..f8b36f6 100644 --- a/ios/SecureEnclaveBench/SecureEnclaveBenchTests/SecureEnclaveTests.swift +++ b/ios/Sloth/SlothTests/SecureEnclaveTests.swift @@ -1,5 +1,7 @@ +import RainbowSloth import XCTest +/// These tests must live in a target of an app to get the right entitlements to access the key chain / SecureEnclave. final class SecureEnclaveTests: XCTestCase { func testKeyGenAndEcdh() throws { diff --git a/ios/build_artifacts.sh b/ios/build_artifacts.sh deleted file mode 100755 index 8544d04..0000000 --- a/ios/build_artifacts.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -e - -mkdir -p Artifacts; -rm -rf Artifacts/*; - -cd SecureEnclaveBench; - -xcodebuild clean -workspace SecureEnclaveBench.xcworkspace -scheme SecureEnclaveBench; -xcodebuild build -workspace SecureEnclaveBench.xcworkspace -scheme SecureEnclaveBench; -xcodebuild archive -workspace SecureEnclaveBench.xcworkspace -scheme SecureEnclaveBench -archivePath ../Artifacts/SecureEnclaveBench.xcarchive; -xcodebuild -exportArchive -archivePath ../Artifacts/SecureEnclaveBench.xcarchive -exportOptionsPlist ../ExportOptions.plist -exportPath ../Artifacts; diff --git a/ios/docs/screenshot-framed.png b/ios/docs/screenshot-framed.png new file mode 100644 index 0000000000000000000000000000000000000000..cb2443be6953f96b3f554c2cd181c2ab92065cf5 GIT binary patch literal 98092 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

uV|nkkNcyBguoA;=wz!`f=@R_w?I6Q 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