RNCryptor.swift 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  1. //
  2. // RNCryptor.swift
  3. //
  4. // Copyright © 2015 Rob Napier. All rights reserved.
  5. //
  6. // This code is licensed under the MIT License:
  7. //
  8. // Permission is hereby granted, free of charge, to any person obtaining a
  9. // copy of this software and associated documentation files (the "Software"),
  10. // to deal in the Software without restriction, including without limitation
  11. // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  12. // and/or sell copies of the Software, and to permit persons to whom the
  13. // Software is furnished to do so, subject to the following conditions:
  14. //
  15. // The above copyright notice and this permission notice shall be included in
  16. // all copies or substantial portions of the Software.
  17. //
  18. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
  21. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  23. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  24. // DEALINGS IN THE SOFTWARE.
  25. //
  26. import Foundation
  27. /// The `RNCryptorType` protocol defines generic API to a mutable,
  28. /// incremental, password-based encryptor or decryptor. Its generic
  29. /// usage is as follows:
  30. ///
  31. /// let cryptor = Encryptor(password: "mypassword")
  32. /// // or Decryptor()
  33. ///
  34. /// var result NSMutableData
  35. /// for data in datas {
  36. /// result.appendData(try cryptor.update(data))
  37. /// }
  38. /// result.appendData(try cryptor.final())
  39. ///
  40. /// After calling `finalData()`, the cryptor is no longer valid.
  41. public protocol RNCryptorType {
  42. /// Creates and returns a cryptor.
  43. ///
  44. /// - parameter password: Non-empty password string. This will be interpretted as UTF-8.
  45. init(password: String)
  46. /// Updates cryptor with data and returns processed data.
  47. ///
  48. /// - parameter data: Data to process. May be empty.
  49. /// - throws: `Error`
  50. /// - returns: Processed data. May be empty.
  51. func updateWithData(data: NSData) throws -> NSData
  52. /// Returns trailing data and invalidates the cryptor.
  53. ///
  54. /// - throws: `Error`
  55. /// - returns: Trailing data
  56. func finalData() throws -> NSData
  57. }
  58. public extension RNCryptorType {
  59. /// Simplified, generic interface to `RNCryptorType`. Takes a data,
  60. /// returns a processed data. Generally you should use
  61. /// `RNCryptor.encryptData(password:)`, or
  62. /// `RNCryptor.decryptData(password:)` instead, but this is useful
  63. /// for code that is neutral on whether it is encrypting or decrypting.
  64. ///
  65. /// - throws: `Error`
  66. private func oneshot(data: NSData) throws -> NSData {
  67. let result = NSMutableData(data: try updateWithData(data))
  68. result.appendData(try finalData())
  69. return result
  70. }
  71. }
  72. // FIXME: Move this to RNCryptor.Error if @objc can rename it correctly.
  73. /// Errors thrown by `RNCryptorType`.
  74. @objc public enum RNCryptorError: Int, ErrorType {
  75. /// Ciphertext was corrupt or password was incorrect.
  76. /// It is not possible to distinguish between these cases in the v3 data format.
  77. case HMACMismatch = 1
  78. /// Unrecognized data format. Usually this means the data is corrupt.
  79. case UnknownHeader = 2
  80. /// `final()` was called before sufficient data was passed to `updateWithData()`
  81. case MessageTooShort
  82. /// Memory allocation failure. This should never happen.
  83. case MemoryFailure
  84. /// A password-based decryptor was used on a key-based ciphertext, or vice-versa.
  85. case InvalidCredentialType
  86. }
  87. /// RNCryptor encryption/decryption interface.
  88. public class RNCryptor: NSObject {
  89. /// Encrypt data using password and return encrypted data.
  90. public static func encryptData(data: NSData, password: String) -> NSData {
  91. return Encryptor(password: password).encryptData(data)
  92. }
  93. /// Decrypt data using password and return decrypted data. Throws if
  94. /// password is incorrect or ciphertext is in the wrong format.
  95. /// - throws `Error`
  96. public static func decryptData(data: NSData, password: String) throws -> NSData {
  97. return try Decryptor(password: password).decryptData(data)
  98. }
  99. /// Generates random NSData of given length
  100. /// Crashes if `length` is larger than allocatable memory, or if the system random number generator is not available.
  101. public static func randomDataOfLength(length: Int) -> NSData {
  102. let data = NSMutableData(length: length)!
  103. let result = SecRandomCopyBytes(kSecRandomDefault, length, UnsafeMutablePointer<UInt8>(data.mutableBytes))
  104. guard result == errSecSuccess else {
  105. fatalError("SECURITY FAILURE: Could not generate secure random numbers: \(result).")
  106. }
  107. return data
  108. }
  109. /// A encryptor for the latest data format. If compatibility with other RNCryptor
  110. /// implementations is required, you may wish to use the specific encryptor version rather
  111. /// than accepting "latest."
  112. ///
  113. @objc(RNEncryptor)
  114. public final class Encryptor: NSObject, RNCryptorType {
  115. private let encryptor: EncryptorV3
  116. /// Creates and returns a cryptor.
  117. ///
  118. /// - parameter password: Non-empty password string. This will be interpretted as UTF-8.
  119. public init(password: String) {
  120. precondition(password != "")
  121. encryptor = EncryptorV3(password: password)
  122. }
  123. /// Updates cryptor with data and returns processed data.
  124. ///
  125. /// - parameter data: Data to process. May be empty.
  126. /// - returns: Processed data. May be empty.
  127. public func updateWithData(data: NSData) -> NSData {
  128. return encryptor.updateWithData(data)
  129. }
  130. /// Returns trailing data and invalidates the cryptor.
  131. ///
  132. /// - returns: Trailing data
  133. public func finalData() -> NSData {
  134. return encryptor.finalData()
  135. }
  136. /// Simplified, generic interface to `RNCryptorType`. Takes a data,
  137. /// returns a processed data, and invalidates the cryptor.
  138. public func encryptData(data: NSData) -> NSData {
  139. return encryptor.encryptData(data)
  140. }
  141. }
  142. /// Password-based decryptor that can handle any supported format.
  143. @objc(RNDecryptor)
  144. public final class Decryptor : NSObject, RNCryptorType {
  145. private var decryptors: [VersionedDecryptorType.Type] = [DecryptorV3.self]
  146. private var buffer = NSMutableData()
  147. private var decryptor: RNCryptorType?
  148. private let password: String
  149. /// Creates and returns a cryptor.
  150. ///
  151. /// - parameter password: Non-empty password string. This will be interpretted as UTF-8.
  152. public init(password: String) {
  153. assert(password != "")
  154. self.password = password
  155. }
  156. /// Decrypt data using password and return decrypted data, invalidating decryptor. Throws if
  157. /// password is incorrect or ciphertext is in the wrong format.
  158. /// - throws `Error`
  159. public func decryptData(data: NSData) throws -> NSData {
  160. return try oneshot(data)
  161. }
  162. /// Updates cryptor with data and returns processed data.
  163. ///
  164. /// - parameter data: Data to process. May be empty.
  165. /// - throws: `Error`
  166. /// - returns: Processed data. May be empty.
  167. public func updateWithData(data: NSData) throws -> NSData {
  168. if let d = decryptor {
  169. return try d.updateWithData(data)
  170. }
  171. buffer.appendData(data)
  172. let toCheck:[VersionedDecryptorType.Type]
  173. (toCheck, decryptors) = decryptors.splitPassFail{ self.buffer.length >= $0.preambleSize }
  174. for decryptorType in toCheck {
  175. if decryptorType.canDecrypt(buffer.bytesView[0..<decryptorType.preambleSize]) {
  176. let d = decryptorType.init(password: password)
  177. decryptor = d
  178. let result = try d.updateWithData(buffer)
  179. buffer.length = 0
  180. return result
  181. }
  182. }
  183. guard !decryptors.isEmpty else { throw RNCryptorError.UnknownHeader }
  184. return NSData()
  185. }
  186. /// Returns trailing data and invalidates the cryptor.
  187. ///
  188. /// - throws: `Error`
  189. /// - returns: Trailing data
  190. public func finalData() throws -> NSData {
  191. guard let d = decryptor else {
  192. throw RNCryptorError.UnknownHeader
  193. }
  194. return try d.finalData()
  195. }
  196. }
  197. }
  198. // V3 implementaion
  199. public extension RNCryptor {
  200. /// V3 format settings
  201. @objc(RNCryptorFormatV3)
  202. public final class FormatV3: NSObject {
  203. /// Size of AES and HMAC keys
  204. public static let keySize = kCCKeySizeAES256
  205. /// Size of PBKDF2 salt
  206. public static let saltSize = 8
  207. /// Generate a key from a password and salt
  208. /// - parameters:
  209. /// - password: Password to convert
  210. /// - salt: Salt. Generally constructed with RNCryptor.randomDataOfLength(FormatV3.saltSize)
  211. /// - returns: Key of length FormatV3.keySize
  212. public static func keyForPassword(password: String, salt: NSData) -> NSData {
  213. let derivedKey = NSMutableData(length: keySize)!
  214. let derivedKeyPtr = UnsafeMutablePointer<UInt8>(derivedKey.mutableBytes)
  215. let passwordData = password.dataUsingEncoding(NSUTF8StringEncoding)!
  216. let passwordPtr = UnsafePointer<Int8>(passwordData.bytes)
  217. let saltPtr = UnsafePointer<UInt8>(salt.bytes)
  218. // All the crazy casting because CommonCryptor hates Swift
  219. let algorithm = CCPBKDFAlgorithm(kCCPBKDF2)
  220. let prf = CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA1)
  221. let pbkdf2Rounds = UInt32(10000)
  222. let result = CCKeyDerivationPBKDF(
  223. algorithm,
  224. passwordPtr, passwordData.length,
  225. saltPtr, salt.length,
  226. prf, pbkdf2Rounds,
  227. derivedKeyPtr, derivedKey.length)
  228. guard result == CCCryptorStatus(kCCSuccess) else {
  229. fatalError("SECURITY FAILURE: Could not derive secure password (\(result)): \(derivedKey).")
  230. }
  231. return derivedKey
  232. }
  233. static let formatVersion = UInt8(3)
  234. static let ivSize = kCCBlockSizeAES128
  235. static let hmacSize = Int(CC_SHA256_DIGEST_LENGTH)
  236. static let keyHeaderSize = 1 + 1 + kCCBlockSizeAES128
  237. static let passwordHeaderSize = 1 + 1 + 8 + 8 + kCCBlockSizeAES128
  238. }
  239. /// Format version 3 encryptor. Use this to ensure a specific format verison
  240. /// or when using keys (which are inherrently versions-specific). To use
  241. /// "the latest encryptor" with a password, use `Encryptor` instead.
  242. @objc(RNEncryptorV3)
  243. public final class EncryptorV3 : NSObject, RNCryptorType {
  244. private var engine: Engine
  245. private var hmac: HMACV3
  246. private var pendingHeader: NSData?
  247. /// Creates and returns an encryptor.
  248. ///
  249. /// - parameter password: Non-empty password string. This will be interpretted as UTF-8.
  250. public convenience init(password: String) {
  251. self.init(
  252. password: password,
  253. encryptionSalt: RNCryptor.randomDataOfLength(V3.saltSize),
  254. hmacSalt: RNCryptor.randomDataOfLength(V3.saltSize),
  255. iv: RNCryptor.randomDataOfLength(V3.ivSize))
  256. }
  257. /// Creates and returns an encryptor using keys.
  258. ///
  259. /// - Attention: This method requires some expertise to use correctly.
  260. /// Most users should use `init(password:)` which is simpler
  261. /// to use securely.
  262. ///
  263. /// Keys should not be generated directly from strings (`.dataUsingEncoding()` or similar).
  264. /// Ideally, keys should be random (`Cryptor.randomDataOfLength()` or some other high-quality
  265. /// random generator. If keys must be generated from strings, then use `FormatV3.keyForPassword(salt:)`
  266. /// with a random salt, or just use password-based encryption (that's what it's for).
  267. ///
  268. /// - parameters:
  269. /// - encryptionKey: AES-256 key. Must be exactly FormatV3.keySize (kCCKeySizeAES256, 32 bytes)
  270. /// - hmacKey: HMAC key. Must be exactly FormatV3.keySize (kCCKeySizeAES256, 32 bytes)
  271. public convenience init(encryptionKey: NSData, hmacKey: NSData) {
  272. self.init(encryptionKey: encryptionKey, hmacKey: hmacKey, iv: RNCryptor.randomDataOfLength(V3.ivSize))
  273. }
  274. /// Takes a data, returns a processed data, and invalidates the cryptor.
  275. public func encryptData(data: NSData) -> NSData {
  276. return try! oneshot(data)
  277. }
  278. /// Updates cryptor with data and returns encrypted data.
  279. ///
  280. /// - parameter data: Data to process. May be empty.
  281. /// - returns: Processed data. May be empty.
  282. public func updateWithData(data: NSData) -> NSData {
  283. // It should not be possible for this to fail during encryption
  284. return try! handle(engine.updateWithData(data))
  285. }
  286. /// Returns trailing data and invalidates the cryptor.
  287. ///
  288. /// - returns: Trailing data
  289. public func finalData() -> NSData {
  290. let result = NSMutableData(data: try! handle(engine.finalData()))
  291. result.appendData(hmac.finalData())
  292. return result
  293. }
  294. // Expose random numbers for testing
  295. internal convenience init(encryptionKey: NSData, hmacKey: NSData, iv: NSData) {
  296. let preamble = [V3.formatVersion, UInt8(0)]
  297. let header = NSMutableData(bytes: preamble, length: preamble.count)
  298. header.appendData(iv)
  299. self.init(encryptionKey: encryptionKey, hmacKey: hmacKey, iv: iv, header: header)
  300. }
  301. // Expose random numbers for testing
  302. internal convenience init(password: String, encryptionSalt: NSData, hmacSalt: NSData, iv: NSData) {
  303. let encryptionKey = V3.keyForPassword(password, salt: encryptionSalt)
  304. let hmacKey = V3.keyForPassword(password, salt: hmacSalt)
  305. // TODO: This chained-+ is very slow to compile in Swift 2b5 (http://www.openradar.me/21842206)
  306. // let header = [V3.version, UInt8(1)] + encryptionSalt + hmacSalt + iv
  307. let preamble = [V3.formatVersion, UInt8(1)]
  308. let header = NSMutableData(bytes: preamble, length: preamble.count)
  309. header.appendData(encryptionSalt)
  310. header.appendData(hmacSalt)
  311. header.appendData(iv)
  312. self.init(encryptionKey: encryptionKey, hmacKey: hmacKey, iv: iv, header: header)
  313. }
  314. private init(encryptionKey: NSData, hmacKey: NSData, iv: NSData, header: NSData) {
  315. precondition(encryptionKey.length == V3.keySize)
  316. precondition(hmacKey.length == V3.keySize)
  317. precondition(iv.length == V3.ivSize)
  318. hmac = HMACV3(key: hmacKey)
  319. engine = Engine(operation: .Encrypt, key: encryptionKey, iv: iv)
  320. pendingHeader = header
  321. }
  322. private func handle(data: NSData) -> NSData {
  323. var result: NSData
  324. if let ph = pendingHeader {
  325. let accum = NSMutableData(data: ph)
  326. pendingHeader = nil
  327. accum.appendData(data)
  328. result = accum
  329. } else {
  330. result = data
  331. }
  332. hmac.updateWithData(result)
  333. return result
  334. }
  335. }
  336. /// Format version 3 decryptor. This is required in order to decrypt
  337. /// using keys (since key configuration is version-specific). For password
  338. /// decryption, `Decryptor` is generally preferred, and will call this
  339. /// if appropriate.
  340. @objc(RNDecryptorV3)
  341. public final class DecryptorV3: NSObject, VersionedDecryptorType {
  342. //
  343. // Static methods
  344. //
  345. private static let preambleSize = 1
  346. private static func canDecrypt(preamble: NSData) -> Bool {
  347. assert(preamble.length >= 1)
  348. return preamble.bytesView[0] == 3
  349. }
  350. //
  351. // Private properties
  352. //
  353. private var buffer = NSMutableData()
  354. private var decryptorEngine: DecryptorEngineV3?
  355. private let credential: Credential
  356. /// Creates and returns a decryptor.
  357. ///
  358. /// - parameter password: Non-empty password string. This will be interpretted as UTF-8.
  359. public init(password: String) {
  360. credential = .Password(password)
  361. }
  362. /// Creates and returns a decryptor using keys.
  363. ///
  364. /// - parameters:
  365. /// - encryptionKey: AES-256 key. Must be exactly FormatV3.keySize (kCCKeySizeAES256, 32 bytes)
  366. /// - hmacKey: HMAC key. Must be exactly FormatV3.keySize (kCCKeySizeAES256, 32 bytes)
  367. public init(encryptionKey: NSData, hmacKey: NSData) {
  368. precondition(encryptionKey.length == V3.keySize)
  369. precondition(hmacKey.length == V3.hmacSize)
  370. credential = .Keys(encryptionKey: encryptionKey, hmacKey: hmacKey)
  371. }
  372. /// Decrypt data using password and return decrypted data. Throws if
  373. /// password is incorrect or ciphertext is in the wrong format.
  374. /// - throws `Error`
  375. public func decryptData(data: NSData) throws -> NSData {
  376. return try oneshot(data)
  377. }
  378. /// Updates cryptor with data and returns encrypted data.
  379. ///
  380. /// - parameter data: Data to process. May be empty.
  381. /// - returns: Processed data. May be empty.
  382. public func updateWithData(data: NSData) throws -> NSData {
  383. if let e = decryptorEngine {
  384. return try e.updateWithData(data)
  385. }
  386. buffer.appendData(data)
  387. guard buffer.length >= requiredHeaderSize else {
  388. return NSData()
  389. }
  390. let e = try createEngineWithCredential(credential, header: buffer.bytesView[0..<requiredHeaderSize])
  391. decryptorEngine = e
  392. let body = buffer.bytesView[requiredHeaderSize..<buffer.length]
  393. buffer.length = 0
  394. return try e.updateWithData(body)
  395. }
  396. /// Returns trailing data and invalidates the cryptor.
  397. ///
  398. /// - returns: Trailing data
  399. public func finalData() throws -> NSData {
  400. guard let result = try decryptorEngine?.finalData() else {
  401. throw RNCryptorError.MessageTooShort
  402. }
  403. return result
  404. }
  405. //
  406. // Private functions
  407. //
  408. private var requiredHeaderSize: Int {
  409. switch credential {
  410. case .Password(_): return V3.passwordHeaderSize
  411. case .Keys(_, _): return V3.keyHeaderSize
  412. }
  413. }
  414. private func createEngineWithCredential(credential: Credential, header: NSData) throws -> DecryptorEngineV3 {
  415. switch credential {
  416. case let .Password(password):
  417. return try createEngineWithPassword(password, header: header)
  418. case let .Keys(encryptionKey, hmacKey):
  419. return try createEngineWithKeys(encryptionKey: encryptionKey, hmacKey: hmacKey, header: header)
  420. }
  421. }
  422. private func createEngineWithPassword(password: String, header: NSData) throws -> DecryptorEngineV3 {
  423. assert(password != "")
  424. precondition(header.length == V3.passwordHeaderSize)
  425. guard DecryptorV3.canDecrypt(header) else {
  426. throw RNCryptorError.UnknownHeader
  427. }
  428. guard header.bytesView[1] == 1 else {
  429. throw RNCryptorError.InvalidCredentialType
  430. }
  431. let encryptionSalt = header.bytesView[2...9]
  432. let hmacSalt = header.bytesView[10...17]
  433. let iv = header.bytesView[18...33]
  434. let encryptionKey = V3.keyForPassword(password, salt: encryptionSalt)
  435. let hmacKey = V3.keyForPassword(password, salt: hmacSalt)
  436. return DecryptorEngineV3(encryptionKey: encryptionKey, hmacKey: hmacKey, iv: iv, header: header)
  437. }
  438. private func createEngineWithKeys(encryptionKey encryptionKey: NSData, hmacKey: NSData, header: NSData) throws -> DecryptorEngineV3 {
  439. precondition(header.length == V3.keyHeaderSize)
  440. precondition(encryptionKey.length == V3.keySize)
  441. precondition(hmacKey.length == V3.keySize)
  442. guard DecryptorV3.canDecrypt(header) else {
  443. throw RNCryptorError.UnknownHeader
  444. }
  445. guard header.bytesView[1] == 0 else {
  446. throw RNCryptorError.InvalidCredentialType
  447. }
  448. let iv = header.bytesView[2..<18]
  449. return DecryptorEngineV3(encryptionKey: encryptionKey, hmacKey: hmacKey, iv: iv, header: header)
  450. }
  451. }
  452. }
  453. private let CCErrorDomain = "com.apple.CommonCrypto"
  454. internal enum CryptorOperation: CCOperation {
  455. case Encrypt = 0 // CCOperation(kCCEncrypt)
  456. case Decrypt = 1 // CCOperation(kCCDecrypt)
  457. }
  458. internal final class Engine {
  459. private let cryptor: CCCryptorRef
  460. private var buffer = NSMutableData()
  461. init(operation: CryptorOperation, key: NSData, iv: NSData) {
  462. var cryptorOut = CCCryptorRef()
  463. let result = CCCryptorCreate(
  464. operation.rawValue,
  465. CCAlgorithm(kCCAlgorithmAES128), CCOptions(kCCOptionPKCS7Padding),
  466. key.bytes, key.length,
  467. iv.bytes,
  468. &cryptorOut
  469. )
  470. cryptor = cryptorOut
  471. // It is a programming error to create us with illegal values
  472. // This is an internal class, so we can constrain what is sent to us.
  473. // If this is ever made public, it should throw instead of asserting.
  474. assert(result == CCCryptorStatus(kCCSuccess))
  475. }
  476. deinit {
  477. if cryptor != CCCryptorRef() {
  478. CCCryptorRelease(cryptor)
  479. }
  480. }
  481. func sizeBufferForDataOfLength(length: Int) -> Int {
  482. let size = CCCryptorGetOutputLength(cryptor, length, true)
  483. buffer.length = size
  484. return size
  485. }
  486. func updateWithData(data: NSData) throws -> NSData {
  487. let outputLength = sizeBufferForDataOfLength(data.length)
  488. var dataOutMoved: Int = 0
  489. var result: CCCryptorStatus = CCCryptorStatus(kCCUnimplemented)
  490. result = CCCryptorUpdate(
  491. cryptor,
  492. data.bytes, data.length,
  493. buffer.mutableBytes, outputLength,
  494. &dataOutMoved)
  495. // The only error returned by CCCryptorUpdate is kCCBufferTooSmall, which would be a programming error
  496. assert(result == CCCryptorStatus(kCCSuccess))
  497. buffer.length = dataOutMoved
  498. return buffer
  499. }
  500. func finalData() throws -> NSData {
  501. let outputLength = sizeBufferForDataOfLength(0)
  502. var dataOutMoved: Int = 0
  503. let result = CCCryptorFinal(
  504. cryptor,
  505. buffer.mutableBytes, outputLength,
  506. &dataOutMoved
  507. )
  508. guard result == CCCryptorStatus(kCCSuccess) else {
  509. throw NSError(domain: CCErrorDomain, code: Int(result), userInfo: nil)
  510. }
  511. buffer.length = dataOutMoved
  512. return buffer
  513. }
  514. }
  515. internal typealias V3 = RNCryptor.FormatV3
  516. private enum Credential {
  517. case Password(String)
  518. case Keys(encryptionKey: NSData, hmacKey: NSData)
  519. }
  520. private final class DecryptorEngineV3 {
  521. private let buffer = OverflowingBuffer(capacity: V3.hmacSize)
  522. private var hmac: HMACV3
  523. private var engine: Engine
  524. init(encryptionKey: NSData, hmacKey: NSData, iv: NSData, header: NSData) {
  525. precondition(encryptionKey.length == V3.keySize)
  526. precondition(hmacKey.length == V3.hmacSize)
  527. precondition(iv.length == V3.ivSize)
  528. hmac = HMACV3(key: hmacKey)
  529. hmac.updateWithData(header)
  530. engine = Engine(operation: .Decrypt, key: encryptionKey, iv: iv)
  531. }
  532. func updateWithData(data: NSData) throws -> NSData {
  533. let overflow = buffer.updateWithData(data)
  534. hmac.updateWithData(overflow)
  535. return try engine.updateWithData(overflow)
  536. }
  537. func finalData() throws -> NSData {
  538. let result = try engine.finalData()
  539. let hash = hmac.finalData()
  540. if !isEqualInConsistentTime(trusted: hash, untrusted: buffer.finalData()) {
  541. throw RNCryptorError.HMACMismatch
  542. }
  543. return result
  544. }
  545. }
  546. private final class HMACV3 {
  547. var context: CCHmacContext = CCHmacContext()
  548. init(key: NSData) {
  549. CCHmacInit(
  550. &context,
  551. CCHmacAlgorithm(kCCHmacAlgSHA256),
  552. key.bytes,
  553. key.length
  554. )
  555. }
  556. func updateWithData(data: NSData) {
  557. CCHmacUpdate(&context, data.bytes, data.length)
  558. }
  559. func finalData() -> NSData {
  560. let hmac = NSMutableData(length: V3.hmacSize)!
  561. CCHmacFinal(&context, hmac.mutableBytes)
  562. return hmac
  563. }
  564. }
  565. // Internal protocol for version-specific decryptors.
  566. private protocol VersionedDecryptorType: RNCryptorType {
  567. static var preambleSize: Int { get }
  568. static func canDecrypt(preamble: NSData) -> Bool
  569. init(password: String)
  570. }
  571. private extension CollectionType {
  572. // Split collection into ([pass], [fail]) based on predicate.
  573. func splitPassFail(pred: Generator.Element -> Bool) -> ([Generator.Element], [Generator.Element]) {
  574. var pass: [Generator.Element] = []
  575. var fail: [Generator.Element] = []
  576. for e in self {
  577. if pred(e) {
  578. pass.append(e)
  579. } else {
  580. fail.append(e)
  581. }
  582. }
  583. return (pass, fail)
  584. }
  585. }
  586. internal class OverflowingBuffer {
  587. private var buffer = NSMutableData()
  588. let capacity: Int
  589. init(capacity: Int) {
  590. self.capacity = capacity
  591. }
  592. @warn_unused_result
  593. func updateWithData(data: NSData) -> NSData {
  594. if data.length >= capacity {
  595. return sendAllArray(data)
  596. } else if buffer.length + data.length <= capacity {
  597. buffer.appendData(data)
  598. return NSData()
  599. } else {
  600. return sendSomeArray(data)
  601. }
  602. }
  603. func finalData() -> NSData {
  604. let result = buffer
  605. buffer = NSMutableData() // Data belongs to caller now.
  606. return result
  607. }
  608. private func sendAllArray(data: NSData) -> NSData {
  609. let toSend = data.length - capacity
  610. assert(toSend >= 0)
  611. assert(data.length - toSend <= capacity)
  612. let result = NSMutableData(data: buffer)
  613. result.appendData(data.bytesView[0..<toSend])
  614. buffer.length = 0
  615. buffer.appendData(data.bytesView[toSend..<data.length])
  616. return result
  617. }
  618. private func sendSomeArray(data: NSData) -> NSData {
  619. let toSend = (buffer.length + data.length) - capacity
  620. assert(toSend > 0) // If it were <= 0, we would have extended the array
  621. assert(toSend < buffer.length) // If we would have sent everything, replaceBuffer should have been called
  622. let result = buffer.bytesView[0..<toSend]
  623. buffer.replaceBytesInRange(NSRange(0..<toSend), withBytes: nil, length: 0)
  624. buffer.appendData(data)
  625. return result
  626. }
  627. }
  628. private extension NSData {
  629. var bytesView: BytesView { return BytesView(self) }
  630. }
  631. private struct BytesView: CollectionType {
  632. let data: NSData
  633. init(_ data: NSData) { self.data = data }
  634. subscript (position: Int) -> UInt8 {
  635. return UnsafePointer<UInt8>(data.bytes)[position]
  636. }
  637. subscript (bounds: Range<Int>) -> NSData {
  638. return data.subdataWithRange(NSRange(bounds))
  639. }
  640. var startIndex: Int = 0
  641. var endIndex: Int { return data.length }
  642. }
  643. /** Compare two NSData in time proportional to the untrusted data
  644. Equatable-based comparisons genreally stop comparing at the first difference.
  645. This can be used by attackers, in some situations,
  646. to determine a secret value by considering the time required to compare the values.
  647. We enumerate over the untrusted values so that the time is proportaional to the attacker's data,
  648. which provides the attack no informatoin about the length of the secret.
  649. */
  650. private func isEqualInConsistentTime(trusted trusted: NSData, untrusted: NSData) -> Bool {
  651. // The point of this routine is XOR the bytes of each data and accumulate the results with OR.
  652. // If any bytes are different, then the OR will accumulate some non-0 value.
  653. var result: UInt8 = untrusted.length == trusted.length ? 0 : 1 // Start with 0 (equal) only if our lengths are equal
  654. for (i, untrustedByte) in untrusted.bytesView.enumerate() {
  655. // Use mod to wrap around ourselves if they are longer than we are.
  656. // Remember, we already broke equality if our lengths are different.
  657. result |= trusted.bytesView[i % trusted.length] ^ untrustedByte
  658. }
  659. return result == 0
  660. }