From c2617aa79408bb83bfb17d5f1bcce797a1b8b248 Mon Sep 17 00:00:00 2001 From: Yannick Spreen Date: Tue, 27 Apr 2021 17:53:29 +0200 Subject: [PATCH] Add secure backgrounding. --- DGCAVerifier.xcodeproj/project.pbxproj | 4 ++ DGCAVerifier/Services/SecureBackground.swift | 52 ++++++++++++++++++ .../SupportingFiles/AppDelegate.swift | 8 +++ .../hea_dgf_icons-2.png | Bin 4155 -> 2918 bytes .../hea_dgf_icons-3.imageset/Contents.json | 21 +++++++ .../hea_dgf_icons-2.png | Bin 0 -> 4155 bytes .../SupportingFiles/SceneDelegate.swift | 10 ++++ DGCAVerifier/ViewControllers/Home.swift | 9 ++- 8 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 DGCAVerifier/Services/SecureBackground.swift create mode 100644 DGCAVerifier/SupportingFiles/Assets.xcassets/hea_dgf_icons-3.imageset/Contents.json create mode 100644 DGCAVerifier/SupportingFiles/Assets.xcassets/hea_dgf_icons-3.imageset/hea_dgf_icons-2.png diff --git a/DGCAVerifier.xcodeproj/project.pbxproj b/DGCAVerifier.xcodeproj/project.pbxproj index 8a2b616..59b78c6 100644 --- a/DGCAVerifier.xcodeproj/project.pbxproj +++ b/DGCAVerifier.xcodeproj/project.pbxproj @@ -18,6 +18,7 @@ CE157F9B262E2A9F00FE4821 /* SwiftCBOR.CBOR.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE157F9A262E2A9F00FE4821 /* SwiftCBOR.CBOR.swift */; }; CE1BDF99262A4CD600766F97 /* X509.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE1BDF98262A4CD600766F97 /* X509.swift */; }; CE1D1EF6263597A2004C8919 /* LocalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE1D1EF5263597A2004C8919 /* LocalData.swift */; }; + CE37B643263867D700DEE13D /* SecureBackground.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE37B642263867D700DEE13D /* SecureBackground.swift */; }; CE3CC93C2628A7820079FB78 /* ASN1.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE3CC93B2628A7820079FB78 /* ASN1.swift */; }; CE3CC9442628C2130079FB78 /* CBOR.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE3CC9432628C2130079FB78 /* CBOR.swift */; }; CE44798D26304D8F009A836B /* JSONSchema in Frameworks */ = {isa = PBXBuildFile; productRef = CE44798C26304D8F009A836B /* JSONSchema */; }; @@ -80,6 +81,7 @@ CE157F9A262E2A9F00FE4821 /* SwiftCBOR.CBOR.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftCBOR.CBOR.swift; sourceTree = ""; }; CE1BDF98262A4CD600766F97 /* X509.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = X509.swift; sourceTree = ""; }; CE1D1EF5263597A2004C8919 /* LocalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalData.swift; sourceTree = ""; }; + CE37B642263867D700DEE13D /* SecureBackground.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackground.swift; sourceTree = ""; }; CE3CC93B2628A7820079FB78 /* ASN1.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASN1.swift; sourceTree = ""; }; CE3CC9432628C2130079FB78 /* CBOR.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CBOR.swift; sourceTree = ""; }; CE44799126306C86009A836B /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = ""; }; @@ -171,6 +173,7 @@ CE1BDF98262A4CD600766F97 /* X509.swift */, CE8912E426321AA500CB92AF /* KID.swift */, CE8912E926321DAA00CB92AF /* SHA256.swift */, + CE37B642263867D700DEE13D /* SecureBackground.swift */, CE8912F42634C60E00CB92AF /* GatewayConnection.swift */, CE8912FF263570CF00CB92AF /* Enclave.swift */, CE582DC02635AE5F008F35D7 /* SecureStorage.swift */, @@ -449,6 +452,7 @@ CE8912EA26321DAA00CB92AF /* SHA256.swift in Sources */, CE3CC9442628C2130079FB78 /* CBOR.swift in Sources */, CE44799226306C86009A836B /* String.swift in Sources */, + CE37B643263867D700DEE13D /* SecureBackground.swift in Sources */, CE8912F52634C60E00CB92AF /* GatewayConnection.swift in Sources */, CE582DC12635AE5F008F35D7 /* SecureStorage.swift in Sources */, CE44799726306C9B009A836B /* Data+Base45.swift in Sources */, diff --git a/DGCAVerifier/Services/SecureBackground.swift b/DGCAVerifier/Services/SecureBackground.swift new file mode 100644 index 0000000..ed655cf --- /dev/null +++ b/DGCAVerifier/Services/SecureBackground.swift @@ -0,0 +1,52 @@ +// +/*- + * ---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 + */ +// +// SecureBackground.swift +// DGCAVerifier +// +// Created by Yannick Spreen on 4/27/21. +// + + +import Foundation +import UIKit + +struct SecureBackground { + static var imageView: UIImageView? + public static var image: UIImage? + + public static func enable() { + disable() + guard let image = image else { + return + } + let imageView = UIImageView(image: image) + UIApplication.shared.windows[0].addSubview(imageView) + Self.imageView = imageView + } + + public static func disable() { + if imageView != nil { + imageView?.removeFromSuperview() + imageView = nil + } + } +} diff --git a/DGCAVerifier/SupportingFiles/AppDelegate.swift b/DGCAVerifier/SupportingFiles/AppDelegate.swift index 5ea636f..ad67e04 100644 --- a/DGCAVerifier/SupportingFiles/AppDelegate.swift +++ b/DGCAVerifier/SupportingFiles/AppDelegate.swift @@ -34,5 +34,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate { return true } + func applicationWillResignActive(_ application: UIApplication) { + SecureBackground.enable() + } + + func applicationDidBecomeActive(_ application: UIApplication) { + SecureBackground.disable() + } + } diff --git a/DGCAVerifier/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 index 2fd98158e609e8e330fa885f9fb50356a41f095c..a76cb349b77ebfd5c070a1692b38ddeddeaeba29 100644 GIT binary patch literal 2918 zcmbVO3se(V8jgTMc+@Sv5oAclRgcY^SEfV~5_BR4C}Oo1v0*ZSS&~dh0^z9wwUvX? zkfMU9tZjE)wPIyOU4av~2c@yK$ckD)qzgWZysB0r2bI0yb&SVucbosrojdn__kVo% z|NoPs*yvSW?mq4m3dKu`O5(uVYJc2jfU)S}-09#&)uQj|DHM-c_GcPp-~Ra&%5)zh zeuH6yYz=~uYNlL4CgIFXwHBZ$l(6tjtsG0m4NwxEOlSnO!8!{KA`}AJ`XCuwrWNBU z1e&eG*Jek@W7(+~UqK6B0fl8EK!F-J$e~QNN~1?I1++1}2$XKO;KA&&b!R0alf}zjS8047@jh;TKL4xZs9icT4 zqz1BUlqZqt1_2FtIv#>rJEc~mpP&g4#>$jySsW(Y9?}?4flcAG={nVzaRtW0Rk#}0 z81w+knZjyQNCT-)A%8{n)V6~GK&?zRW#hHJsMS*@^oGa`5XJ-{uSM(Qv$QxX4%d_E zIt-7@0B+Ll(P$B|4woB9T|7yuCNC;>(q)JXB7v65Be+Cvzy&mLZyW|Y zkiiX!=Y$}E!3dYPoXthp>~W}!R1nIn*Fl3gND$ir3X(=4H^_eztiTW@sZ+~A$b?#+ zjI*?wWEwO@BqAnNqz)Jc-tk^umx{%)I#Nlfz=l3b*o;ER45ztt|AacxJ2m%^r&j4IO zn^-1(Hv{8pjVU-#`d{*59Hu9g2BTbui;@9b|3l`nfcq?a(T+#LdNs(gy_X7n5)QhC zeLB^yz{ga>!!@AG=|DT<9H8ZcF8N3*5yfY=^>-XPaYy2N{^7d6MKMK(24=g9+?*o+ zu(WkqEA{Km+k~e50slPY_J->t7we~?+9jd@RkhK}MX- z8|-iY<#9%P&v(B2{>n!mG#5i6nxjy?9YtzF9i>3>s(8bWVunf`<}*PvaltYFR(@p*sJWR5*&>^Zek>5$>259@Q|U1LX=M`oO>gwp9^j)%Xdn8v{A=Ai=$dl{4mjY+M%c(&g!{D~ zN&g3z+|5clvL1!38`(LYW#!v{un7)-7oDJQ(RwJwT(>)2L%UjB(^Z$X)Wz?9)||V3 zqu-_HWf*#T7yNEk%&lW(9UoeT8a8AP?A_OTZ0}6v=%!T-GfeSe5KK&~*0P zy48a9t!*BZO(TI9M|+W9 zmcpjlXWRQPG=154qn_gzQv3E-`~j0n;2|1gV`8v=WNO^KfBwu3M_ZMjJscEo4o|wD zh(b4i*^%>T+v+t(S4UrZg|B69)-T>P0`}dd50W!F>ZViS+5n%Kl&qE%TI$-ss_t23tPJI4|qh)E$1SydnSiJPl`EaB6#g$+wo1Hwmx3TL%x%7S|NXa@(AF zD;_jHZ9Kk^A9~{;kMS_~`cHj9+ayPqvkF{_90f*S5yv(vqB*uv``2%_(m4H7e~*^A Ua1{nWwEq*9Mn+4jBR(kj4?$T$MgRZ+ delta 4150 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 AGynhq diff --git a/DGCAVerifier/SupportingFiles/Assets.xcassets/hea_dgf_icons-3.imageset/Contents.json b/DGCAVerifier/SupportingFiles/Assets.xcassets/hea_dgf_icons-3.imageset/Contents.json new file mode 100644 index 0000000..7d903a7 --- /dev/null +++ b/DGCAVerifier/SupportingFiles/Assets.xcassets/hea_dgf_icons-3.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/DGCAVerifier/SupportingFiles/Assets.xcassets/hea_dgf_icons-3.imageset/hea_dgf_icons-2.png b/DGCAVerifier/SupportingFiles/Assets.xcassets/hea_dgf_icons-3.imageset/hea_dgf_icons-2.png new file mode 100644 index 0000000000000000000000000000000000000000..2fd98158e609e8e330fa885f9fb50356a41f095c GIT binary patch literal 4155 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