Commit 443152f8 authored by Christophe Deschamps's avatar Christophe Deschamps Committed by DanmeiChen
Browse files

VFS key generation & store/retrieve to/from keystore & pass on to factory if vfs enabled

parent 765f449c
Pipeline #27490 failed with stage
in 12 seconds
......@@ -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;
......
/*
* 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 */,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment