BlockMode.swift 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. //
  2. // BlockMode.swift
  3. // CryptoSwift
  4. //
  5. // Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
  6. // This software is provided 'as-is', without any express or implied warranty.
  7. //
  8. // In no event will the authors be held liable for any damages arising from the use of this software.
  9. //
  10. // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
  11. //
  12. // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
  13. // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  14. // - This notice may not be removed or altered from any source or binary distribution.
  15. //
  16. typealias CipherOperationOnBlock = (_ block: ArraySlice<UInt8>) -> Array<UInt8>?
  17. public enum BlockMode {
  18. case ECB, CBC(iv: Array<UInt8>), PCBC(iv: Array<UInt8>), CFB(iv: Array<UInt8>), OFB(iv: Array<UInt8>), CTR(iv: Array<UInt8>)
  19. public enum Error: Swift.Error {
  20. /// Invalid key or IV
  21. case invalidKeyOrInitializationVector
  22. /// Invalid IV
  23. case invalidInitializationVector
  24. }
  25. func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock) throws -> BlockModeWorker {
  26. switch self {
  27. case .ECB:
  28. return ECBModeWorker(cipherOperation: cipherOperation)
  29. case .CBC(let iv):
  30. if (iv.count != blockSize) {
  31. throw Error.invalidInitializationVector
  32. }
  33. return CBCModeWorker(iv: iv.slice, cipherOperation: cipherOperation)
  34. case .PCBC(let iv):
  35. if (iv.count != blockSize) {
  36. throw Error.invalidInitializationVector
  37. }
  38. return PCBCModeWorker(iv: iv.slice, cipherOperation: cipherOperation)
  39. case .CFB(let iv):
  40. if (iv.count != blockSize) {
  41. throw Error.invalidInitializationVector
  42. }
  43. return CFBModeWorker(iv: iv.slice, cipherOperation: cipherOperation)
  44. case .OFB(let iv):
  45. if (iv.count != blockSize) {
  46. throw Error.invalidInitializationVector
  47. }
  48. return OFBModeWorker(iv: iv.slice, cipherOperation: cipherOperation)
  49. case .CTR(let iv):
  50. if (iv.count != blockSize) {
  51. throw Error.invalidInitializationVector
  52. }
  53. return CTRModeWorker(iv: iv.slice, cipherOperation: cipherOperation)
  54. }
  55. }
  56. var options: BlockModeOptions {
  57. switch self {
  58. case .ECB:
  59. return .paddingRequired
  60. case .CBC:
  61. return [.initializationVectorRequired, .paddingRequired]
  62. case .CFB:
  63. return .initializationVectorRequired
  64. case .CTR:
  65. return .initializationVectorRequired
  66. case .OFB:
  67. return .initializationVectorRequired
  68. case .PCBC:
  69. return [.initializationVectorRequired, .paddingRequired]
  70. }
  71. }
  72. }