From 4cab1601566c95d5d6297bfcc4f3dd59df5e3006 Mon Sep 17 00:00:00 2001 From: paw Date: Fri, 9 Aug 2024 14:05:21 +0200 Subject: [PATCH] [ios] Use tutasdk for argon2id Removes libargon2.a dependency --- app-ios/project.yml | 29 ----------- app-ios/tutanota/Sources/Crypto/Argon2.swift | 49 ------------------- .../Crypto/IosNativeCryptoFacade.swift | 14 +----- .../tutanota/Sources/Crypto/phc-winner-argon2 | 1 - .../Sources/tutanota-Bridging-Header.h | 1 - .../CompatibilityTestSwift.swift | 25 +++------- 6 files changed, 8 insertions(+), 111 deletions(-) delete mode 100644 app-ios/tutanota/Sources/Crypto/Argon2.swift delete mode 120000 app-ios/tutanota/Sources/Crypto/phc-winner-argon2 diff --git a/app-ios/project.yml b/app-ios/project.yml index 516ce2f53b9a..52ed412cfe40 100644 --- a/app-ios/project.yml +++ b/app-ios/project.yml @@ -43,10 +43,8 @@ targets: excludes: [ "tutanota-web", - "Sources/Crypto/phc-winner-argon2", "Sources/sdktest.swift", ] - compilerFlags: ["-Itutanota/Sources/Crypto/phc-winner-argon2/include"] # XCode will not resolve symbolic links when adding a folder reference, so we will just use a relative path - path: "../build" name: "build" @@ -63,7 +61,6 @@ targets: HEADER_SEARCH_PATHS: [ "${PROJECT_DIR}/tutanota/include", - "tutanota/Sources/Crypto/phc-winner-argon2/include", ] CLANG_CXX_LANGUAGE_STANDARD: "gnu++14" GCC_PREPROCESSOR_DEFINITIONS: ["SQLITE_HAS_CODEC=1", "$(inherited)"] @@ -111,31 +108,6 @@ targets: embed: false - framework: StoreKit.framework embed: false - - target: argon2 - argon2: - type: "library.static" - settings: - PRODUCT_NAME: "argon2" - # Don't show warnings for vendored code - WARNING_CFLAGS: "-w" - sources: - - path: "tutanota/Sources/Crypto/phc-winner-argon2" - includes: - [ - "src/argon2.c", - "src/core.c", - "src/encoding.c", - "src/genkat.c", - "src/ref.c", - "src/blake2/blake2b.c", - ] - compilerFlags: - [ - "-Itutanota/Sources/Crypto/phc-winner-argon2/include", - "-DARGON2_NO_THREADS", - "-O3", - ] - platform: "iOS" tutanotaTests: templates: ["formatAndLint"] type: "bundle.unit-test" @@ -156,7 +128,6 @@ targets: HEADER_SEARCH_PATHS: [ "${PROJECT_DIR}/tutanota/include", - "tutanota/Sources/Crypto/phc-winner-argon2/include", ] TEST_HOST: "$(BUILT_PRODUCTS_DIR)/Tuta D.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Tuta D" SWIFT_OBJC_BRIDGING_HEADER: "tutanotaTests/tutanotaTests-Bridging-Header.h" diff --git a/app-ios/tutanota/Sources/Crypto/Argon2.swift b/app-ios/tutanota/Sources/Crypto/Argon2.swift deleted file mode 100644 index 20a42c49762c..000000000000 --- a/app-ios/tutanota/Sources/Crypto/Argon2.swift +++ /dev/null @@ -1,49 +0,0 @@ -import Foundation - -/// Generate a hash using Argon2id with the given parameters -/// -/// - parameters: -/// - password: password bytes (NOTE: will be zeroed out upon completion) -/// - length: desired hash length -/// - salt: salt bytes -/// - iterations: time cost (# of iterations) -/// - parallelism: degrees of parallelism -/// - memoryCostInKibibytes: memory cost in KiB (1024 bytes = 1 KiB) -func generateArgon2idHash( - ofPassword password: DataWrapper, - ofHashLength length: Int, - withSalt salt: Data, - withIterations iterations: UInt, - withParallelism parallelism: UInt, - withMemoryCost memoryCostInKibibytes: UInt -) throws -> Data { - var hashOutput = [UInt8](repeating: 0, count: length) - - // We need to pass pointers directly to C, of which they have a limited lifetime (hence why we have two closures here!) - let errorCode = password.data.withUnsafeMutableBytes { (passwordBytePtr: UnsafeMutableRawBufferPointer) in - salt.withUnsafeBytes { (saltBytePtr: UnsafeRawBufferPointer) in - let result = argon2id_hash_raw( - UInt32(iterations), - UInt32(memoryCostInKibibytes), - UInt32(parallelism), - passwordBytePtr.baseAddress, - passwordBytePtr.count, - saltBytePtr.baseAddress, - salt.count, - &hashOutput, - hashOutput.count - ) - // Erase the password once finished regardless of result - passwordBytePtr.initializeMemory(as: UInt8.self, repeating: 0) - return result - } - } - - // handle error case - switch Argon2_ErrorCodes(errorCode) { - case ARGON2_OK: return Data(hashOutput) - default: - let errorMessage = argon2_error_message(errorCode)! - throw TUTErrorFactory.createError(withDomain: TUT_CRYPTO_ERROR, message: "argon2id_hash_raw returned \(errorCode): \(errorMessage)") - } -} diff --git a/app-ios/tutanota/Sources/Crypto/IosNativeCryptoFacade.swift b/app-ios/tutanota/Sources/Crypto/IosNativeCryptoFacade.swift index 5d3cf26592f2..a80556622627 100644 --- a/app-ios/tutanota/Sources/Crypto/IosNativeCryptoFacade.swift +++ b/app-ios/tutanota/Sources/Crypto/IosNativeCryptoFacade.swift @@ -57,18 +57,8 @@ public actor IosNativeCryptoFacade: NativeCryptoFacade { .wrap() } - public func argon2idHashRaw(_ password: DataWrapper, _ salt: DataWrapper, _ timeCost: Int, _ memoryCost: Int, _ parallelism: Int, _ hashLength: Int) - async throws -> DataWrapper - { - try generateArgon2idHash( - ofPassword: password, - ofHashLength: hashLength, - withSalt: salt.data, - withIterations: UInt(timeCost), - withParallelism: UInt(parallelism), - withMemoryCost: UInt(memoryCost) - ) - .wrap() + public func argon2idGeneratePassphraseKey(_ passphrase: String, _ salt: DataWrapper) async throws -> DataWrapper { + try tutasdk.argon2idGenerateKeyFromPassphrase(passphrase: passphrase, salt: salt.data).wrap() } public func generateKyberKeypair(_ seed: DataWrapper) async throws -> TutanotaSharedFramework.KyberKeyPair { diff --git a/app-ios/tutanota/Sources/Crypto/phc-winner-argon2 b/app-ios/tutanota/Sources/Crypto/phc-winner-argon2 deleted file mode 120000 index aa2e4efe3341..000000000000 --- a/app-ios/tutanota/Sources/Crypto/phc-winner-argon2 +++ /dev/null @@ -1 +0,0 @@ -../../../../libs/webassembly/phc-winner-argon2 \ No newline at end of file diff --git a/app-ios/tutanota/Sources/tutanota-Bridging-Header.h b/app-ios/tutanota/Sources/tutanota-Bridging-Header.h index 68b54c29f954..d18ced8ce9eb 100644 --- a/app-ios/tutanota/Sources/tutanota-Bridging-Header.h +++ b/app-ios/tutanota/Sources/tutanota-Bridging-Header.h @@ -7,4 +7,3 @@ #import #import #import "Utils/WebviewHacks.h" -#import "argon2.h" diff --git a/app-ios/tutanotaTests/CompatibilityTestSwift.swift b/app-ios/tutanotaTests/CompatibilityTestSwift.swift index 5828b623754c..d1c8040051ba 100644 --- a/app-ios/tutanotaTests/CompatibilityTestSwift.swift +++ b/app-ios/tutanotaTests/CompatibilityTestSwift.swift @@ -15,32 +15,20 @@ class CompatibilityTestSwift: XCTestCase { self.testData = try JSONSerialization.jsonObject(with: jsonData) as? [String: Any] } - func testArgon2id() { - // same parameters we use everywhere else - let ARGON2ID_HASH_LENGTH: Int = 32 - let ARGON2ID_ITERATIONS: UInt = 4 - let ARGON2ID_PARALLELISM: UInt = 1 - let ARGON2ID_MEMORY_COST: UInt = 32 * 1024 - + func testArgon2id() async throws { + let facade = IosNativeCryptoFacade() let tests = (testData!["argon2idTests"] as? [[String: String]])! for test in tests { - let password = DataWrapper(data: TUTEncodingConverter.string(toBytes: test["password"]!)) + let passphrase = test["password"]! let expectedHash = TUTEncodingConverter.hex(toBytes: test["keyHex"]!) let salt = TUTEncodingConverter.hex(toBytes: test["saltHex"]!) - let result = try! generateArgon2idHash( - ofPassword: password, - ofHashLength: ARGON2ID_HASH_LENGTH, - withSalt: salt, - withIterations: ARGON2ID_ITERATIONS, - withParallelism: ARGON2ID_PARALLELISM, - withMemoryCost: ARGON2ID_MEMORY_COST - ) - XCTAssert(password.data.allSatisfy { $0 == 0 }) - XCTAssertEqual(expectedHash, result) + let result = try! await facade.argon2idGeneratePassphraseKey(passphrase, salt.wrap()) + XCTAssertEqual(expectedHash, result.data) } } func testRsa() async throws { + let facade = IosNativeCryptoFacade() let tests = (testData!["rsaEncryptionTests"] as? [[String: String]])! for test in tests { let publicKey = try hexToRsaPublicKey(test["publicKey"]!) @@ -49,7 +37,6 @@ class CompatibilityTestSwift: XCTestCase { let encResult = TUTEncodingConverter.hex(toBytes: test["result"]!) let seed = TUTEncodingConverter.hex(toBytes: test["seed"]!) - let facade = IosNativeCryptoFacade() let encrypted = try await facade.rsaEncrypt(publicKey, plainText.wrap(), seed.wrap()) XCTAssertEqual(encResult, encrypted.data) let decrypted = try await facade.rsaDecrypt(privateKey, encResult.wrap())