From 57a1a023b47eb971201ef1ad9ddcee034b91770c Mon Sep 17 00:00:00 2001 From: Yannick Spreen Date: Sat, 24 Apr 2021 23:56:54 +0200 Subject: [PATCH 01/12] Add Alamofire; Start adding Gateway Service. --- DGCAVerifier.xcodeproj/project.pbxproj | 21 +++++++ .../xcshareddata/swiftpm/Package.resolved | 9 +++ DGCAVerifier/Services/KID.swift | 2 +- DGCAVerifier/ViewControllers/Scan.swift | 2 + DGCAVerifierTests/EHNTests.swift | 4 +- .../Services/GatewayConnection.swift | 57 +++++++++++++++++++ 6 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 PatientScannerDemo/Services/GatewayConnection.swift diff --git a/DGCAVerifier.xcodeproj/project.pbxproj b/DGCAVerifier.xcodeproj/project.pbxproj index d332b17..8a49018 100644 --- a/DGCAVerifier.xcodeproj/project.pbxproj +++ b/DGCAVerifier.xcodeproj/project.pbxproj @@ -25,6 +25,8 @@ CE7DE7FA2625EF18007E6694 /* SwiftCBOR in Frameworks */ = {isa = PBXBuildFile; productRef = CE7DE7F92625EF18007E6694 /* SwiftCBOR */; }; CE8912E526321AA500CB92AF /* KID.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE8912E426321AA500CB92AF /* KID.swift */; }; CE8912EA26321DAA00CB92AF /* SHA256.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE8912E926321DAA00CB92AF /* SHA256.swift */; }; + CE8912F52634C60E00CB92AF /* GatewayConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE8912F42634C60E00CB92AF /* GatewayConnection.swift */; }; + CE8912FB2634C6B900CB92AF /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = CE8912FA2634C6B900CB92AF /* Alamofire */; }; CEA1555D262F63B30024B7AC /* EuDgcSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEA1555C262F63B30024B7AC /* EuDgcSchema.swift */; }; CEA15563262F6DAB0024B7AC /* ChildDismissedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEA15562262F6DAB0024B7AC /* ChildDismissedDelegate.swift */; }; CEA1556B262F784E0024B7AC /* SelfSizedTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEA1556A262F784E0024B7AC /* SelfSizedTableView.swift */; }; @@ -79,6 +81,7 @@ CE44799626306C9B009A836B /* Data+Base45.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Data+Base45.swift"; sourceTree = ""; }; CE8912E426321AA500CB92AF /* KID.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KID.swift; sourceTree = ""; }; CE8912E926321DAA00CB92AF /* SHA256.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SHA256.swift; sourceTree = ""; }; + CE8912F42634C60E00CB92AF /* GatewayConnection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GatewayConnection.swift; sourceTree = ""; }; CEA1555C262F63B30024B7AC /* EuDgcSchema.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EuDgcSchema.swift; sourceTree = ""; }; CEA15562262F6DAB0024B7AC /* ChildDismissedDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChildDismissedDelegate.swift; sourceTree = ""; }; CEA1556A262F784E0024B7AC /* SelfSizedTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelfSizedTableView.swift; sourceTree = ""; }; @@ -112,6 +115,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CE8912FB2634C6B900CB92AF /* Alamofire in Frameworks */, CE157F87262E24DE00FE4821 /* SwiftyJSON in Frameworks */, CE44798D26304D8F009A836B /* JSONSchema in Frameworks */, CE7DE7FA2625EF18007E6694 /* SwiftCBOR in Frameworks */, @@ -159,6 +163,7 @@ CE1BDF98262A4CD600766F97 /* X509.swift */, CE8912E426321AA500CB92AF /* KID.swift */, CE8912E926321DAA00CB92AF /* SHA256.swift */, + CE8912F42634C60E00CB92AF /* GatewayConnection.swift */, ); path = Services; sourceTree = ""; @@ -299,6 +304,7 @@ CE13CEFF262DCC180070C80E /* FloatingPanel */, CE157F86262E24DE00FE4821 /* SwiftyJSON */, CE44798C26304D8F009A836B /* JSONSchema */, + CE8912FA2634C6B900CB92AF /* Alamofire */, ); productName = DGCAVerifier; productReference = CEA6D6E8261F8D2700715333 /* DGCAVerifier.app */; @@ -376,6 +382,7 @@ CE13CEFE262DCC180070C80E /* XCRemoteSwiftPackageReference "FloatingPanel" */, CE157F85262E24DE00FE4821 /* XCRemoteSwiftPackageReference "SwiftyJSON" */, CE44798B26304D8F009A836B /* XCRemoteSwiftPackageReference "JSONSchema" */, + CE8912F92634C6B900CB92AF /* XCRemoteSwiftPackageReference "Alamofire" */, ); productRefGroup = CEA6D6E9261F8D2700715333 /* Products */; projectDirPath = ""; @@ -429,6 +436,7 @@ CE8912EA26321DAA00CB92AF /* SHA256.swift in Sources */, CE3CC9442628C2130079FB78 /* CBOR.swift in Sources */, CE44799226306C86009A836B /* String.swift in Sources */, + CE8912F52634C60E00CB92AF /* GatewayConnection.swift in Sources */, CE44799726306C9B009A836B /* Data+Base45.swift in Sources */, CE13CF0F262DD0D80070C80E /* FullFloatingPanelLayout.swift in Sources */, CEA1556B262F784E0024B7AC /* SelfSizedTableView.swift in Sources */, @@ -817,6 +825,14 @@ minimumVersion = 0.4.3; }; }; + CE8912F92634C6B900CB92AF /* XCRemoteSwiftPackageReference "Alamofire" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/Alamofire/Alamofire"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 5.4.3; + }; + }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ @@ -840,6 +856,11 @@ package = CE7DE7F82625EF18007E6694 /* XCRemoteSwiftPackageReference "SwiftCBOR" */; productName = SwiftCBOR; }; + CE8912FA2634C6B900CB92AF /* Alamofire */ = { + isa = XCSwiftPackageProductDependency; + package = CE8912F92634C6B900CB92AF /* XCRemoteSwiftPackageReference "Alamofire" */; + productName = Alamofire; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = CEA6D6E0261F8D2700715333 /* Project object */; diff --git a/DGCAVerifier.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DGCAVerifier.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index f915462..a3ac02e 100644 --- a/DGCAVerifier.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DGCAVerifier.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,6 +1,15 @@ { "object": { "pins": [ + { + "package": "Alamofire", + "repositoryURL": "https://github.com/Alamofire/Alamofire", + "state": { + "branch": null, + "revision": "f96b619bcb2383b43d898402283924b80e2c4bae", + "version": "5.4.3" + } + }, { "package": "FloatingPanel", "repositoryURL": "https://github.com/SCENEE/FloatingPanel", diff --git a/DGCAVerifier/Services/KID.swift b/DGCAVerifier/Services/KID.swift index 905d62d..c6da198 100644 --- a/DGCAVerifier/Services/KID.swift +++ b/DGCAVerifier/Services/KID.swift @@ -31,7 +31,7 @@ import Foundation typealias KidBytes = [UInt8] struct KID { - public static func stringFrom(kidBytes: KidBytes) -> String { + public static func string(from kidBytes: KidBytes) -> String { return Data(kidBytes.prefix(8)).base64EncodedString() } public static func from(_ encodedCert: String) -> KidBytes { diff --git a/DGCAVerifier/ViewControllers/Scan.swift b/DGCAVerifier/ViewControllers/Scan.swift index ecc7ad7..84acea2 100644 --- a/DGCAVerifier/ViewControllers/Scan.swift +++ b/DGCAVerifier/ViewControllers/Scan.swift @@ -220,6 +220,8 @@ extension ScanVC { // print(CBOR.payload(from: data)?.toString() ?? "") // print(CBOR.header(from: data)?.toString() ?? "") presentViewer(for: HCert(from: data)) + + GatewayConnection.fetchCert() } } diff --git a/DGCAVerifierTests/EHNTests.swift b/DGCAVerifierTests/EHNTests.swift index 79675ed..ef22027 100644 --- a/DGCAVerifierTests/EHNTests.swift +++ b/DGCAVerifierTests/EHNTests.swift @@ -103,7 +103,7 @@ class EHNTests: XCTestCase { XCTAssert(false) return } - let kid = KID.stringFrom(kidBytes: kidBytes) + let kid = KID.string(from: kidBytes) guard let url = URL(string: "https://dgc.a-sit.at/ehn/cert/\(kid)") else { @@ -122,7 +122,7 @@ class EHNTests: XCTestCase { return } let encodedCert = body.base64EncodedString() - XCTAssert(KID.stringFrom(kidBytes: KID.from(encodedCert)) == kid) + XCTAssert(KID.string(from: KID.from(encodedCert)) == kid) if COSE.verify(data, with: encodedCert) { expectation.fulfill() } else { diff --git a/PatientScannerDemo/Services/GatewayConnection.swift b/PatientScannerDemo/Services/GatewayConnection.swift new file mode 100644 index 0000000..6bee524 --- /dev/null +++ b/PatientScannerDemo/Services/GatewayConnection.swift @@ -0,0 +1,57 @@ +// +/*- + * ---license-start + * eu-digital-green-certificates / dgca-verifier-app-ios + * --- + * Copyright (C) 2021 T-Systems International GmbH and all other contributors + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ +// +// GatewayConnection.swift +// PatientScannerDemo +// +// Created by Yannick Spreen on 4/24/21. +// + + +import Foundation +import Alamofire + +struct GatewayConnection { + static let serverURI = "https://dgca-verifier-service.cfapps.eu10.hana.ondemand.com/" + static let updateEndpoint = "signercertificateUpdate" + static let statusEndpoint = "signercertificateStatus" + + public static func fetchCert(resume resumeToken: String? = nil) { + AF.request(serverURI + updateEndpoint).response { + guard + case let .success(result) = $0.result, + let response = result, + let responseStr = String(data: response, encoding: .utf8), + let pubKey = X509.pubKey(from: responseStr), + let headers = $0.response?.headers, + let responseKid = headers["x-kid"] + else { + return + } + let kid = KID.from(responseStr) + let kidStr = KID.string(from: kid) + if kidStr != responseKid { + return + } + print(pubKey) + } + } +} From 3a72cbb56b62efb277c7e30d3ad22e7d582b038d Mon Sep 17 00:00:00 2001 From: Yannick Spreen Date: Sun, 25 Apr 2021 14:00:46 +0200 Subject: [PATCH 02/12] Start local encrypted db. --- DGCAVerifier.xcodeproj/project.pbxproj | 8 + .../Base.lproj/LaunchScreen.storyboard | 49 ++++-- .../Storyboards/Base.lproj/Main.storyboard | 61 +++++++- DGCAVerifier/ViewControllers/Scan.swift | 5 +- PatientScannerDemo/Services/Enclave.swift | 147 ++++++++++++++++++ .../hea_dgf_icons-2.imageset/Contents.json | 21 +++ .../hea_dgf_icons-2.png | Bin 0 -> 4155 bytes PatientScannerDemo/ViewControllers/Home.swift | 38 +++++ 8 files changed, 311 insertions(+), 18 deletions(-) create mode 100644 PatientScannerDemo/Services/Enclave.swift create mode 100644 PatientScannerDemo/SupportingFiles/Assets.xcassets/hea_dgf_icons-2.imageset/Contents.json create mode 100644 PatientScannerDemo/SupportingFiles/Assets.xcassets/hea_dgf_icons-2.imageset/hea_dgf_icons-2.png create mode 100644 PatientScannerDemo/ViewControllers/Home.swift diff --git a/DGCAVerifier.xcodeproj/project.pbxproj b/DGCAVerifier.xcodeproj/project.pbxproj index 8a49018..7adaf54 100644 --- a/DGCAVerifier.xcodeproj/project.pbxproj +++ b/DGCAVerifier.xcodeproj/project.pbxproj @@ -27,6 +27,8 @@ CE8912EA26321DAA00CB92AF /* SHA256.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE8912E926321DAA00CB92AF /* SHA256.swift */; }; CE8912F52634C60E00CB92AF /* GatewayConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE8912F42634C60E00CB92AF /* GatewayConnection.swift */; }; CE8912FB2634C6B900CB92AF /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = CE8912FA2634C6B900CB92AF /* Alamofire */; }; + CE891300263570CF00CB92AF /* Enclave.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE8912FF263570CF00CB92AF /* Enclave.swift */; }; + CE891305263581D900CB92AF /* Home.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE891304263581D900CB92AF /* Home.swift */; }; CEA1555D262F63B30024B7AC /* EuDgcSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEA1555C262F63B30024B7AC /* EuDgcSchema.swift */; }; CEA15563262F6DAB0024B7AC /* ChildDismissedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEA15562262F6DAB0024B7AC /* ChildDismissedDelegate.swift */; }; CEA1556B262F784E0024B7AC /* SelfSizedTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEA1556A262F784E0024B7AC /* SelfSizedTableView.swift */; }; @@ -82,6 +84,8 @@ CE8912E426321AA500CB92AF /* KID.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KID.swift; sourceTree = ""; }; CE8912E926321DAA00CB92AF /* SHA256.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SHA256.swift; sourceTree = ""; }; CE8912F42634C60E00CB92AF /* GatewayConnection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GatewayConnection.swift; sourceTree = ""; }; + CE8912FF263570CF00CB92AF /* Enclave.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Enclave.swift; sourceTree = ""; }; + CE891304263581D900CB92AF /* Home.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Home.swift; sourceTree = ""; }; CEA1555C262F63B30024B7AC /* EuDgcSchema.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EuDgcSchema.swift; sourceTree = ""; }; CEA15562262F6DAB0024B7AC /* ChildDismissedDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChildDismissedDelegate.swift; sourceTree = ""; }; CEA1556A262F784E0024B7AC /* SelfSizedTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelfSizedTableView.swift; sourceTree = ""; }; @@ -164,6 +168,7 @@ CE8912E426321AA500CB92AF /* KID.swift */, CE8912E926321DAA00CB92AF /* SHA256.swift */, CE8912F42634C60E00CB92AF /* GatewayConnection.swift */, + CE8912FF263570CF00CB92AF /* Enclave.swift */, ); path = Services; sourceTree = ""; @@ -186,6 +191,7 @@ children = ( CE13CF09262DCDDA0070C80E /* CertificateViewer.swift */, CEA6D6EF261F8D2700715333 /* Scan.swift */, + CE891304263581D900CB92AF /* Home.swift */, ); path = ViewControllers; sourceTree = ""; @@ -433,6 +439,7 @@ CE13CF0A262DCDDA0070C80E /* CertificateViewer.swift in Sources */, CEC2C4C32625ED030056E406 /* JWK.swift in Sources */, CEC2C4C42625ED030056E406 /* Base45.swift in Sources */, + CE891300263570CF00CB92AF /* Enclave.swift in Sources */, CE8912EA26321DAA00CB92AF /* SHA256.swift in Sources */, CE3CC9442628C2130079FB78 /* CBOR.swift in Sources */, CE44799226306C86009A836B /* String.swift in Sources */, @@ -449,6 +456,7 @@ CEFAD86D2625F164009AFEF9 /* Signature.swift in Sources */, CE13CF23262DDF810070C80E /* RoundedButton.swift in Sources */, CEA6D6EC261F8D2700715333 /* AppDelegate.swift in Sources */, + CE891305263581D900CB92AF /* Home.swift in Sources */, CEA15563262F6DAB0024B7AC /* ChildDismissedDelegate.swift in Sources */, CEFAD8722625F29E009AFEF9 /* String+JSON.swift in Sources */, CEC2C4C22625ED030056E406 /* ZLib.swift in Sources */, diff --git a/DGCAVerifier/Storyboards/Base.lproj/LaunchScreen.storyboard b/DGCAVerifier/Storyboards/Base.lproj/LaunchScreen.storyboard index 0b64f64..a3d9091 100644 --- a/DGCAVerifier/Storyboards/Base.lproj/LaunchScreen.storyboard +++ b/DGCAVerifier/Storyboards/Base.lproj/LaunchScreen.storyboard @@ -1,12 +1,12 @@ - + - - - - - + + + + + @@ -14,20 +14,39 @@ - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - + diff --git a/DGCAVerifier/Storyboards/Base.lproj/Main.storyboard b/DGCAVerifier/Storyboards/Base.lproj/Main.storyboard index 71e66d0..e29862b 100644 --- a/DGCAVerifier/Storyboards/Base.lproj/Main.storyboard +++ b/DGCAVerifier/Storyboards/Base.lproj/Main.storyboard @@ -1,5 +1,5 @@ - + @@ -17,10 +17,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DGCAVerifier/ViewControllers/Scan.swift b/DGCAVerifier/ViewControllers/Scan.swift index 84acea2..f9b243a 100644 --- a/DGCAVerifier/ViewControllers/Scan.swift +++ b/DGCAVerifier/ViewControllers/Scan.swift @@ -47,8 +47,9 @@ class ScanVC: UIViewController { override func viewDidLoad() { super.viewDidLoad() -// checkPermissions() -// setupCameraLiveView() + checkPermissions() + setupCameraLiveView() + return; DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { self.observationHandler(payloadS: nil) // let reason = "Log in to your account" diff --git a/PatientScannerDemo/Services/Enclave.swift b/PatientScannerDemo/Services/Enclave.swift new file mode 100644 index 0000000..374206f --- /dev/null +++ b/PatientScannerDemo/Services/Enclave.swift @@ -0,0 +1,147 @@ +// +/*- + * ---license-start + * eu-digital-green-certificates / dgca-verifier-app-ios + * --- + * Copyright (C) 2021 T-Systems International GmbH and all other contributors + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ +// +// Enclave.swift +// PatientScannerDemo +// +// Created by Yannick Spreen on 4/25/21. +// + + +import Foundation + +struct Enclave { + static let algorithm = SecKeyAlgorithm.eciesEncryptionCofactorVariableIVX963SHA256AESGCM + static let symmetricKey = generateOrLoadKey(with: "symmetricKey") + + static func tag(for name: String) -> Data { + "\(Bundle.main.bundleIdentifier ?? "app").\(name)".data(using: .utf8)! + } + + static func generateKey(with name: String? = nil) -> (SecKey?, String?) { + let name = name ?? UUID().uuidString + let tag = Enclave.tag(for: name) + var error: Unmanaged? + guard + let access = + SecAccessControlCreateWithFlags( + kCFAllocatorDefault, + kSecAttrAccessibleWhenUnlockedThisDeviceOnly, + [.privateKeyUsage, .biometryCurrentSet], + &error + ) + else { + return (nil, error?.takeRetainedValue().localizedDescription) + } + let attributes: [String: Any] = [ + kSecAttrKeyType as String: kSecAttrKeyTypeEC, + kSecAttrKeySizeInBits as String: 256, + kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave, + kSecPrivateKeyAttrs as String: [ + kSecAttrIsPermanent as String: true, + kSecAttrApplicationTag as String: tag, + kSecAttrAccessControl as String: access + ] + ] + guard + let privateKey = SecKeyCreateRandomKey( + attributes as CFDictionary, + &error + ) + else { + return (nil, error?.takeRetainedValue().localizedDescription) + } + error?.release() + return (privateKey, nil) + } + + static func loadKey(with name: String) -> SecKey? { + let tag = Enclave.tag(for: name) + let query: [String: Any] = [ + kSecClass as String : kSecClassKey, + kSecAttrKeyType as String : kSecAttrKeyTypeEC, + kSecAttrApplicationTag as String : tag, + kSecReturnRef as String : true + ] + + var item: CFTypeRef? + let status = SecItemCopyMatching(query as CFDictionary, &item) + guard + status == errSecSuccess + else { + return nil + } + return (item as! SecKey) + } + + static func generateOrLoadKey(with name: String) -> SecKey? { + if let key = loadKey(with: name) { + return key + } + return generateKey(with: name).0 + } + + static func encrypt(data: Data, with key: SecKey) -> (Data?, String?) { + guard let publicKey = SecKeyCopyPublicKey(key) else { + return (nil, "Cannot retrieve public key.") + } + guard SecKeyIsAlgorithmSupported(publicKey, .encrypt, algorithm) else { + return (nil, "Algorithm not supported.") + } + var error: Unmanaged? + let cipherData = SecKeyCreateEncryptedData( + publicKey, + algorithm, + data as CFData, + &error + ) as Data? + guard cipherData != nil else { + return (nil, error?.takeRetainedValue().localizedDescription) + } + error?.release() + return (cipherData, nil) + } + + static func decrypt(data: Data, with key: SecKey, completion: @escaping (Data?, String?) -> Void) { + DispatchQueue.global(qos: .userInitiated).async { + let (result, error) = syncDecrypt(data: data, with: key) + completion(result, error) + } + } + + static func syncDecrypt(data: Data, with key: SecKey) -> (Data?, String?) { + guard SecKeyIsAlgorithmSupported(key, .decrypt, algorithm) else { + return (nil, "Algorithm not supported.") + } + var error: Unmanaged? + let clearData = SecKeyCreateDecryptedData( + key, + algorithm, + data as CFData, + &error + ) as Data? + guard clearData != nil else { + return (nil, error?.takeRetainedValue().localizedDescription) + } + error?.release() + return (clearData, nil) + } +} diff --git a/PatientScannerDemo/SupportingFiles/Assets.xcassets/hea_dgf_icons-2.imageset/Contents.json b/PatientScannerDemo/SupportingFiles/Assets.xcassets/hea_dgf_icons-2.imageset/Contents.json new file mode 100644 index 0000000..7d903a7 --- /dev/null +++ b/PatientScannerDemo/SupportingFiles/Assets.xcassets/hea_dgf_icons-2.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "hea_dgf_icons-2.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PatientScannerDemo/SupportingFiles/Assets.xcassets/hea_dgf_icons-2.imageset/hea_dgf_icons-2.png b/PatientScannerDemo/SupportingFiles/Assets.xcassets/hea_dgf_icons-2.imageset/hea_dgf_icons-2.png new file mode 100644 index 0000000000000000000000000000000000000000..2fd98158e609e8e330fa885f9fb50356a41f095c GIT binary patch literal 4155 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 Date: Sun, 25 Apr 2021 14:16:56 +0200 Subject: [PATCH 03/12] Complete rebase. --- .../Services/Enclave.swift | 0 .../Services/GatewayConnection.swift | 0 .../hea_dgf_icons-2.imageset/Contents.json | 0 .../hea_dgf_icons-2.imageset/hea_dgf_icons-2.png | Bin .../ViewControllers/Home.swift | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename {PatientScannerDemo => DGCAVerifier}/Services/Enclave.swift (100%) rename {PatientScannerDemo => DGCAVerifier}/Services/GatewayConnection.swift (100%) rename {PatientScannerDemo => DGCAVerifier}/SupportingFiles/Assets.xcassets/hea_dgf_icons-2.imageset/Contents.json (100%) rename {PatientScannerDemo => DGCAVerifier}/SupportingFiles/Assets.xcassets/hea_dgf_icons-2.imageset/hea_dgf_icons-2.png (100%) rename {PatientScannerDemo => DGCAVerifier}/ViewControllers/Home.swift (100%) diff --git a/PatientScannerDemo/Services/Enclave.swift b/DGCAVerifier/Services/Enclave.swift similarity index 100% rename from PatientScannerDemo/Services/Enclave.swift rename to DGCAVerifier/Services/Enclave.swift diff --git a/PatientScannerDemo/Services/GatewayConnection.swift b/DGCAVerifier/Services/GatewayConnection.swift similarity index 100% rename from PatientScannerDemo/Services/GatewayConnection.swift rename to DGCAVerifier/Services/GatewayConnection.swift diff --git a/PatientScannerDemo/SupportingFiles/Assets.xcassets/hea_dgf_icons-2.imageset/Contents.json b/DGCAVerifier/SupportingFiles/Assets.xcassets/hea_dgf_icons-2.imageset/Contents.json similarity index 100% rename from PatientScannerDemo/SupportingFiles/Assets.xcassets/hea_dgf_icons-2.imageset/Contents.json rename to DGCAVerifier/SupportingFiles/Assets.xcassets/hea_dgf_icons-2.imageset/Contents.json diff --git a/PatientScannerDemo/SupportingFiles/Assets.xcassets/hea_dgf_icons-2.imageset/hea_dgf_icons-2.png b/DGCAVerifier/SupportingFiles/Assets.xcassets/hea_dgf_icons-2.imageset/hea_dgf_icons-2.png similarity index 100% rename from PatientScannerDemo/SupportingFiles/Assets.xcassets/hea_dgf_icons-2.imageset/hea_dgf_icons-2.png rename to DGCAVerifier/SupportingFiles/Assets.xcassets/hea_dgf_icons-2.imageset/hea_dgf_icons-2.png diff --git a/PatientScannerDemo/ViewControllers/Home.swift b/DGCAVerifier/ViewControllers/Home.swift similarity index 100% rename from PatientScannerDemo/ViewControllers/Home.swift rename to DGCAVerifier/ViewControllers/Home.swift From c01eb8959cf22a3312362a227e8fb640b7acc720 Mon Sep 17 00:00:00 2001 From: Yannick Spreen Date: Sun, 25 Apr 2021 14:18:57 +0200 Subject: [PATCH 04/12] Give dead VC an identifier. --- .../Storyboards/CertificateViewer.storyboard | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/DGCAVerifier/Storyboards/CertificateViewer.storyboard b/DGCAVerifier/Storyboards/CertificateViewer.storyboard index f258f03..3828909 100644 --- a/DGCAVerifier/Storyboards/CertificateViewer.storyboard +++ b/DGCAVerifier/Storyboards/CertificateViewer.storyboard @@ -28,7 +28,7 @@