forked from mirrors/linphone-iphone
VFS key generation & store/retrieve to/from keystore & pass on to factory if vfs enabled
This commit is contained in:
parent
765f449c94
commit
443152f867
3 changed files with 192 additions and 0 deletions
|
|
@ -33,6 +33,8 @@
|
|||
|
||||
#import <Intents/Intents.h>
|
||||
#import <IntentsUI/IntentsUI.h>
|
||||
#import "linphoneapp-Swift.h"
|
||||
|
||||
|
||||
#ifdef USE_CRASHLYTICS
|
||||
#include "FIRApp.h"
|
||||
|
|
@ -263,6 +265,12 @@
|
|||
#ifdef USE_CRASHLYTICS
|
||||
[FIRApp configure];
|
||||
#endif
|
||||
|
||||
|
||||
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"vfs_enabled"] && !VFSUtil.activateVFS) {
|
||||
[VFSUtil oslogWithLog:@"[VFS] Error unable to activate." level:OS_LOG_TYPE_ERROR];
|
||||
}
|
||||
|
||||
UIApplication *app = [UIApplication sharedApplication];
|
||||
UIApplicationState state = app.applicationState;
|
||||
|
||||
|
|
|
|||
180
Classes/VFSUtil.swift
Normal file
180
Classes/VFSUtil.swift
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2020 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-iphone
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import UIKit
|
||||
import Foundation
|
||||
import Security
|
||||
import CommonCrypto
|
||||
import linphonesw
|
||||
import os
|
||||
|
||||
|
||||
@objc class VFSUtil: NSObject {
|
||||
|
||||
@objc static let keyName = Bundle.main.bundleIdentifier!+".vfskey"
|
||||
@objc static let prefName = Bundle.main.bundleIdentifier!+".vfspref"
|
||||
|
||||
@objc static func generateKey(requiresBiometry: Bool = false) throws {
|
||||
|
||||
let flags: SecAccessControlCreateFlags
|
||||
if #available(iOS 11.3, *) {
|
||||
flags = requiresBiometry ?
|
||||
[.privateKeyUsage, .biometryCurrentSet] : .privateKeyUsage
|
||||
} else {
|
||||
flags = requiresBiometry ?
|
||||
[.privateKeyUsage, .touchIDCurrentSet] : .privateKeyUsage
|
||||
}
|
||||
let access =
|
||||
SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenUnlockedThisDeviceOnly,flags,nil)!
|
||||
let tag = keyName.data(using: .utf8)!
|
||||
let attributes: [String: Any] = [
|
||||
kSecAttrKeyType as String : kSecAttrKeyTypeECSECPrimeRandom,
|
||||
kSecAttrKeySizeInBits as String : 256,
|
||||
kSecAttrTokenID as String : kSecAttrTokenIDSecureEnclave,
|
||||
kSecPrivateKeyAttrs as String : [
|
||||
kSecAttrIsPermanent as String : true,
|
||||
kSecAttrApplicationTag as String : tag,
|
||||
kSecAttrAccessControl as String : access
|
||||
]
|
||||
]
|
||||
|
||||
var error: Unmanaged<CFError>?
|
||||
guard let _ = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
|
||||
throw error!.takeRetainedValue() as Error
|
||||
}
|
||||
}
|
||||
|
||||
@objc static func loadKey(name: String) -> SecKey? {
|
||||
let tag = name.data(using: .utf8)!
|
||||
let query: [String: Any] = [
|
||||
kSecClass as String : kSecClassKey,
|
||||
kSecAttrApplicationTag as String : tag,
|
||||
kSecAttrKeyType as String : kSecAttrKeyTypeEC,
|
||||
kSecReturnRef as String : true
|
||||
]
|
||||
|
||||
var item: CFTypeRef?
|
||||
let status = SecItemCopyMatching(query as CFDictionary, &item)
|
||||
guard status == errSecSuccess else {
|
||||
return nil
|
||||
}
|
||||
return (item as! SecKey)
|
||||
}
|
||||
|
||||
|
||||
@objc static func encrypt(clearText: String) -> String? {
|
||||
let algorithm: SecKeyAlgorithm = .eciesEncryptionCofactorX963SHA512AESGCM
|
||||
guard let privateKey = loadKey(name: keyName), let publicKey = SecKeyCopyPublicKey(privateKey), SecKeyIsAlgorithmSupported(publicKey, .encrypt, algorithm) else {
|
||||
return nil
|
||||
}
|
||||
var error: Unmanaged<CFError>?
|
||||
let clearTextData = clearText.data(using: .utf8)!
|
||||
guard let encryptedData = SecKeyCreateEncryptedData(publicKey, algorithm,clearTextData as CFData, &error) as Data? else {
|
||||
return nil
|
||||
}
|
||||
return encryptedData.base64EncodedString()
|
||||
}
|
||||
|
||||
@objc static func decrypt(encryptedText: String) -> String? {
|
||||
let algorithm: SecKeyAlgorithm = .eciesEncryptionCofactorX963SHA512AESGCM
|
||||
guard let key = loadKey(name: keyName), SecKeyIsAlgorithmSupported(key, .decrypt, algorithm) else {
|
||||
return nil
|
||||
}
|
||||
var error: Unmanaged<CFError>?
|
||||
guard let clearTextData = SecKeyCreateDecryptedData(key,algorithm,Data(base64Encoded: encryptedText)! as CFData,&error) as Data? else {
|
||||
print("[VFS] failed deciphering data \(String(describing: error))")
|
||||
return nil
|
||||
}
|
||||
return String(decoding: clearTextData, as: UTF8.self)
|
||||
}
|
||||
|
||||
|
||||
@objc static func addSecuredPreference(key:String, value:String) -> Bool {
|
||||
let delQuery: [String: Any] = [kSecClass as String: kSecClassGenericPassword,kSecAttrAccount as String: key.data(using: .utf8)!]
|
||||
SecItemDelete(delQuery as CFDictionary)
|
||||
|
||||
|
||||
let insertQUery: [String: Any] = [kSecClass as String: kSecClassGenericPassword,kSecAttrAccount as String: key.data(using: .utf8)!, kSecValueData as String:value.data(using: .utf8)!]
|
||||
let insertStatus = SecItemAdd(insertQUery as CFDictionary, nil)
|
||||
return insertStatus == errSecSuccess
|
||||
|
||||
}
|
||||
|
||||
@objc static func getSecuredPreference(key:String) -> String? {
|
||||
let query: [String:Any] = [
|
||||
kSecClass as String: kSecClassGenericPassword,
|
||||
kSecAttrAccount as String: key.data(using: .utf8)!,
|
||||
kSecReturnData as String: kCFBooleanTrue
|
||||
]
|
||||
|
||||
var result: AnyObject?
|
||||
let status: OSStatus = withUnsafeMutablePointer(to: &result) {
|
||||
SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
|
||||
}
|
||||
return status == errSecSuccess ? String(decoding: result as! Data , as: UTF8.self) : nil
|
||||
}
|
||||
|
||||
@objc static func randomSha512() -> String {
|
||||
let data = UUID.init().uuidString.data(using: .utf8)!
|
||||
var digest = [UInt8](repeating: 0, count: Int(CC_SHA512_DIGEST_LENGTH))
|
||||
data.withUnsafeBytes({
|
||||
_ = CC_SHA512($0, CC_LONG(data.count), &digest)
|
||||
})
|
||||
return digest.map({ String(format: "%02hhx", $0) }).joined(separator: "")
|
||||
}
|
||||
|
||||
|
||||
|
||||
@objc static func activateVFS() -> Bool {
|
||||
do {
|
||||
if (getSecuredPreference(key: prefName) == nil) {
|
||||
oslog(log: "[VFS] no secret key set, building one.", level: .info)
|
||||
try generateKey(requiresBiometry: false)
|
||||
guard let encryptedHash = encrypt(clearText: randomSha512()) else {
|
||||
return false
|
||||
}
|
||||
if (!addSecuredPreference(key: prefName, value: encryptedHash)) {
|
||||
oslog(log: "[VFS] Unable to save encrypted key in secured defaults.", level: .error)
|
||||
}
|
||||
}
|
||||
guard let encryptedKey = getSecuredPreference(key: prefName) else {
|
||||
oslog(log: "[VFS] Unable to retrieve encrypted key.", level: .error)
|
||||
return false
|
||||
}
|
||||
let secret = decrypt(encryptedText: encryptedKey)
|
||||
Factory.Instance.setVfsEncryption(encryptionModule: 2, secret: secret, secretSize: 32)
|
||||
oslog(log: "[VFS] activated", level: .info)
|
||||
return true
|
||||
} catch {
|
||||
oslog(log: "[VFS] Error setting up VFS: \(error)", level: .info)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@objc static func oslog(log:String, level: OSLogType) {
|
||||
if #available(iOS 10.0, *) {
|
||||
os_log("%{public}@", type: level,log)
|
||||
} else {
|
||||
NSLog(log)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -673,6 +673,7 @@
|
|||
8CF25D9E1F9F76BD00BEA0C1 /* chat_group_informations@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 8CF25D9C1F9F76BD00BEA0C1 /* chat_group_informations@2x.png */; };
|
||||
93566413F75DA69D2811A716 /* Pods_msgNotificationService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6F30EA7BEA39DA427CE0754E /* Pods_msgNotificationService.framework */; };
|
||||
A634ABAFCB39B6AAE4CA991D /* Pods_linphone.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65CEDD144CABFAA70A29AF27 /* Pods_linphone.framework */; };
|
||||
C6DA657C261C950C0020CB43 /* VFSUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6DA657B261C950C0020CB43 /* VFSUtil.swift */; };
|
||||
C90FAA7915AF54E6002091CB /* HistoryDetailsView.m in Sources */ = {isa = PBXBuildFile; fileRef = C90FAA7715AF54E6002091CB /* HistoryDetailsView.m */; };
|
||||
CF15F21E20E4F9A3008B1DE6 /* UIImageViewDeletable.m in Sources */ = {isa = PBXBuildFile; fileRef = CF15F21C20E4F9A3008B1DE6 /* UIImageViewDeletable.m */; };
|
||||
CF15F21F20E4F9A3008B1DE6 /* UIImageViewDeletable.xib in Resources */ = {isa = PBXBuildFile; fileRef = CF15F21D20E4F9A3008B1DE6 /* UIImageViewDeletable.xib */; };
|
||||
|
|
@ -1705,6 +1706,7 @@
|
|||
ADCA571A7CF61077747BFE53 /* Pods-msgNotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-msgNotificationService.debug.xcconfig"; path = "Pods/Target Support Files/Pods-msgNotificationService/Pods-msgNotificationService.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
BAD0A9494E833034EB559687 /* Pods-msgNotificationContent.distributionadhoc.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-msgNotificationContent.distributionadhoc.xcconfig"; path = "Pods/Target Support Files/Pods-msgNotificationContent/Pods-msgNotificationContent.distributionadhoc.xcconfig"; sourceTree = "<group>"; };
|
||||
BE06BDE664323B2A53469696 /* Pods-liblinphoneTesterTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-liblinphoneTesterTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-liblinphoneTesterTests/Pods-liblinphoneTesterTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
C6DA657B261C950C0020CB43 /* VFSUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VFSUtil.swift; sourceTree = "<group>"; };
|
||||
C90FAA7615AF54E6002091CB /* HistoryDetailsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HistoryDetailsView.h; sourceTree = "<group>"; };
|
||||
C90FAA7715AF54E6002091CB /* HistoryDetailsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HistoryDetailsView.m; sourceTree = "<group>"; };
|
||||
C9B3A6FD15B485DB006F52EE /* Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Utils.h; path = Utils/Utils.h; sourceTree = "<group>"; };
|
||||
|
|
@ -2126,6 +2128,7 @@
|
|||
D326483415887D4400930C67 /* Utils */,
|
||||
34216F3E1547EBCD00EA9777 /* VideoZoomHandler.h */,
|
||||
34216F3F1547EBCD00EA9777 /* VideoZoomHandler.m */,
|
||||
C6DA657B261C950C0020CB43 /* VFSUtil.swift */,
|
||||
614C087723D1A35F00217F80 /* ProviderDelegate.swift */,
|
||||
614C087923D1A37400217F80 /* CallManager.swift */,
|
||||
EA88F3B0241BDAA100E66528 /* CoreManager.swift */,
|
||||
|
|
@ -4235,6 +4238,7 @@
|
|||
D37DC6C11594AE1800B2A5EB /* LinphoneCoreSettingsStore.m in Sources */,
|
||||
63CD4B4F1A5AAC8C00B84282 /* DTAlertView.m in Sources */,
|
||||
D3EA53FD159850E80037DC6B /* LinphoneManager.m in Sources */,
|
||||
C6DA657C261C950C0020CB43 /* VFSUtil.swift in Sources */,
|
||||
63B81A0E1B57DA33009604A6 /* TPKeyboardAvoidingScrollView.m in Sources */,
|
||||
633888451BFB2C49001D5E7B /* HPGrowingTextView.m in Sources */,
|
||||
63F1DF441BCE618E00EDED90 /* UIAddressTextField.m in Sources */,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue