Skip to content

Commit

Permalink
Use CryptoKit on iOS 13 for 12-byte IVs
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisballinger committed Feb 28, 2020
1 parent 0a54c68 commit 666c6dc
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 18 deletions.
4 changes: 2 additions & 2 deletions ChatSecureCore/Classes/Controllers/FileTransferManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
40 changes: 28 additions & 12 deletions ChatSecureCore/Classes/Controllers/OTRSignalEncryptionHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import UIKit
import OTRKit
import CryptoKit

class OTRSignalEncryptionHelper {

Expand All @@ -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)
}
}

/**
Expand All @@ -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)
}
}

}

0 comments on commit 666c6dc

Please sign in to comment.