diff --git a/ChatSecureCore/Classes/Controllers/FileTransferManager.swift b/ChatSecureCore/Classes/Controllers/FileTransferManager.swift index 6b7cb47a1..6fa6aafcd 100644 --- a/ChatSecureCore/Classes/Controllers/FileTransferManager.swift +++ b/ChatSecureCore/Classes/Controllers/FileTransferManager.swift @@ -260,7 +260,7 @@ public class FileTransferManager: NSObject, OTRServerCapabilitiesDelegate { var outData = data var outKeyIv: Data? = nil if shouldEncrypt { - guard let key = OTRPasswordGenerator.randomData(withLength: 32), let iv = OTRPasswordGenerator.randomData(withLength: 16) else { + guard let key = OTRPasswordGenerator.randomData(withLength: 32), let iv = OTRSignalEncryptionHelper.generateIV() else { DDLogError("Could not generate key/iv") self.callbackQueue.async { completion(nil, FileTransferError.keyGenerationError) @@ -269,7 +269,7 @@ public class FileTransferManager: NSObject, OTRServerCapabilitiesDelegate { } outKeyIv = iv + key do { - let crypted = try OTRCryptoUtility.encryptAESGCMData(data, key: key, iv: iv) + let crypted = try OTRSignalEncryptionHelper.encryptData(data, key: key, iv: iv) outData = crypted.data + crypted.authTag } catch let error { outData = Data() diff --git a/ChatSecureCore/Classes/Controllers/OTROMEMOSignalCoordinator.swift b/ChatSecureCore/Classes/Controllers/OTROMEMOSignalCoordinator.swift index 519221aa2..047f4e621 100644 --- a/ChatSecureCore/Classes/Controllers/OTROMEMOSignalCoordinator.swift +++ b/ChatSecureCore/Classes/Controllers/OTROMEMOSignalCoordinator.swift @@ -310,10 +310,7 @@ import SignalProtocolObjC } do { //Create the encrypted payload - guard let gcmData = try OTRSignalEncryptionHelper.encryptData(messageBodyData, key: keyData, iv: ivData) else { - DDLogError("OMEMO Encryption error: Could not perform AES-GCM operation") - return - } + let gcmData = try OTRSignalEncryptionHelper.encryptData(messageBodyData, key: keyData, iv: ivData) // this does the signal encryption. If we fail it doesn't matter here. We end up trying the next device and fail later if no devices worked. let encryptClosure:(OMEMODevice) -> (OMEMOKeyData?) = { device in diff --git a/ChatSecureCore/Classes/Controllers/OTRSignalEncryptionHelper.swift b/ChatSecureCore/Classes/Controllers/OTRSignalEncryptionHelper.swift index 87743567e..c0867cbdf 100644 --- a/ChatSecureCore/Classes/Controllers/OTRSignalEncryptionHelper.swift +++ b/ChatSecureCore/Classes/Controllers/OTRSignalEncryptionHelper.swift @@ -8,6 +8,7 @@ import UIKit import OTRKit +import CryptoKit class OTRSignalEncryptionHelper { @@ -20,8 +21,15 @@ class OTRSignalEncryptionHelper { returns: The encrypted data */ - class func encryptData(_ data:Data, key:Data, iv:Data) throws -> OTRCryptoData? { - return try OTRCryptoUtility.encryptAESGCMData(data, key: key, iv: iv) + class func encryptData(_ data:Data, key:Data, iv:Data) throws -> OTRCryptoData { + if #available(iOS 13.0, *) { + let nonce = try AES.GCM.Nonce(data: iv) + let symmetricKey = SymmetricKey(data: key) + let sealedBox = try AES.GCM.seal(data, using: symmetricKey, nonce: nonce) + return OTRCryptoData(data: sealedBox.ciphertext, authTag: sealedBox.tag) + } else { + return try OTRCryptoUtility.encryptAESGCMData(data, key: key, iv: iv) + } } /** @@ -34,22 +42,30 @@ class OTRSignalEncryptionHelper { returns: The Decrypted data */ class func decryptData(_ data:Data, key:Data, iv:Data, authTag:Data) throws -> Data? { - let cryptoData = OTRCryptoData(data: data, authTag: authTag) - return try OTRCryptoUtility.decryptAESGCMData(cryptoData, key: key, iv: iv) - } - - /** Generates random data of length 16 bytes */ - fileprivate class func randomDataOfBlockLength() -> Data? { - return OTRPasswordGenerator.randomData(withLength: 16) + // CryptoKit only accepts 12-byte IVs + if #available(iOS 13.0, *), iv.count == 12 { + let nonce = try AES.GCM.Nonce(data: iv) + let sealedBox = try AES.GCM.SealedBox(nonce: nonce, ciphertext: data, tag: authTag) + let symmetricKey = SymmetricKey(data: key) + return try AES.GCM.open(sealedBox, using: symmetricKey) + } else { + let cryptoData = OTRCryptoData(data: data, authTag: authTag) + return try OTRCryptoUtility.decryptAESGCMData(cryptoData, key: key, iv: iv) + } } /** Generates random key of length 16 bytes*/ class func generateSymmetricKey() -> Data? { - return self.randomDataOfBlockLength() + return OTRPasswordGenerator.randomData(withLength: 16) } - /** Generates random iv of length 16 bytes */ + + /** Generates random iv of length 12 bytes */ class func generateIV() -> Data? { - return self.randomDataOfBlockLength() + if #available(iOS 13.0, *) { + return Data(AES.GCM.Nonce()) + } else { + return OTRPasswordGenerator.randomData(withLength: 12) + } } }