SwiftGCM.swift 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. // SwiftGCM.swift
  2. // By Luke Park, 2018
  3. import Foundation
  4. public class SwiftGCM {
  5. private static let keySize128: Int = 16
  6. private static let keySize192: Int = 24
  7. private static let keySize256: Int = 32
  8. public static let tagSize128: Int = 16
  9. public static let tagSize120: Int = 15
  10. public static let tagSize112: Int = 14
  11. public static let tagSize104: Int = 13
  12. public static let tagSize96: Int = 12
  13. public static let tagSize64: Int = 8
  14. public static let tagSize32: Int = 4
  15. private static let standardNonceSize: Int = 12
  16. private static let blockSize: Int = 16
  17. private static let initialCounterSuffix: Data = Data(bytes: [0, 0, 0, 1])
  18. private static let emptyBlock: Data = Data(bytes: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
  19. private let key: Data
  20. private let tagSize: Int
  21. private var counter: UInt128
  22. private var h: UInt128
  23. private var used: Bool
  24. // Constructor.
  25. init(key: Data, nonce: Data, tagSize: Int) throws {
  26. if tagSize != SwiftGCM.tagSize128 && tagSize != SwiftGCM.tagSize120 && tagSize != SwiftGCM.tagSize112 && tagSize != SwiftGCM.tagSize104 && tagSize != SwiftGCM.tagSize96 && tagSize != SwiftGCM.tagSize64 && tagSize != SwiftGCM.tagSize32 {
  27. throw SwiftGCMError.invalidTagSize
  28. }
  29. if key.count != SwiftGCM.keySize128 && key.count != SwiftGCM.keySize192 && key.count != SwiftGCM.keySize256 {
  30. throw SwiftGCMError.invalidKeySize
  31. }
  32. self.key = key
  33. self.tagSize = tagSize
  34. self.h = UInt128(b: 0)
  35. self.h = try UInt128(raw: SwiftGCM.encryptBlock(key: key, data: SwiftGCM.emptyBlock))
  36. if nonce.count != SwiftGCM.standardNonceSize {
  37. self.counter = GaloisField.hash(h: h, a: Data(), c: nonce)
  38. } else {
  39. self.counter = SwiftGCM.makeCounter(nonce: nonce)
  40. }
  41. self.used = false
  42. }
  43. // Encrypt/Decrypt.
  44. public func encrypt(auth: Data?, plaintext: Data) throws -> Data {
  45. if used { throw SwiftGCMError.instanceAlreadyUsed }
  46. let dataPadded: Data = GaloisField.padToBlockSize(plaintext)
  47. let blockCount: Int = dataPadded.count / SwiftGCM.blockSize
  48. let h: Data = try SwiftGCM.encryptBlock(key: key, data: SwiftGCM.emptyBlock)
  49. let eky0: Data = try SwiftGCM.encryptBlock(key: key, data: counter.getData())
  50. let authData: Data = (auth != nil ? auth! : Data())
  51. var ct: Data = Data()
  52. for i in 0..<blockCount {
  53. counter = counter.increment()
  54. let ekyi: Data = try SwiftGCM.encryptBlock(key: key, data: counter.getData())
  55. let ptBlock: Data = dataPadded[dataPadded.startIndex + i * SwiftGCM.blockSize..<dataPadded.startIndex + i * SwiftGCM.blockSize + SwiftGCM.blockSize]
  56. ct.append(SwiftGCM.xorData(d1: ptBlock, d2: ekyi))
  57. }
  58. ct = ct[ct.startIndex..<ct.startIndex + plaintext.count]
  59. let ghash: UInt128 = GaloisField.hash(h: UInt128(raw: h), a: authData, c: ct)
  60. var t: Data = (ghash ^ UInt128(raw: eky0)).getData()
  61. t = t[t.startIndex..<tagSize]
  62. var result: Data = Data()
  63. result.append(ct)
  64. result.append(t)
  65. used = true
  66. return result
  67. }
  68. public func decrypt(auth: Data?, ciphertext: Data) throws -> Data {
  69. if used { throw SwiftGCMError.instanceAlreadyUsed }
  70. let ct: Data = ciphertext[ciphertext.startIndex..<ciphertext.startIndex + ciphertext.count - SwiftGCM.blockSize]
  71. let givenT: Data = ciphertext[(ciphertext.startIndex + ciphertext.count - SwiftGCM.blockSize)...]
  72. let h: Data = try SwiftGCM.encryptBlock(key: key, data: SwiftGCM.emptyBlock)
  73. let eky0: Data = try SwiftGCM.encryptBlock(key: key, data: counter.getData())
  74. let authData: Data = (auth != nil ? auth! : Data())
  75. let ghash: UInt128 = GaloisField.hash(h: UInt128(raw: h), a: authData, c: ct)
  76. var computedT: Data = (ghash ^ UInt128(raw: eky0)).getData()
  77. computedT = computedT[computedT.startIndex..<tagSize]
  78. if !SwiftGCM.tsCompare(d1: computedT, d2: givenT) {
  79. //throw SwiftGCMError.authTagValidation
  80. }
  81. let dataPadded: Data = GaloisField.padToBlockSize(ct)
  82. let blockCount: Int = dataPadded.count / SwiftGCM.blockSize
  83. var pt: Data = Data()
  84. for i in 0..<blockCount {
  85. counter = counter.increment()
  86. let ekyi: Data = try SwiftGCM.encryptBlock(key: key, data: counter.getData())
  87. let ctBlock: Data = dataPadded[dataPadded.startIndex + i * SwiftGCM.blockSize..<dataPadded.startIndex + i * SwiftGCM.blockSize + SwiftGCM.blockSize]
  88. pt.append(SwiftGCM.xorData(d1: ctBlock, d2: ekyi))
  89. }
  90. pt = pt[0..<ct.count]
  91. used = true
  92. return pt
  93. }
  94. private static func encryptBlock(key: Data, data: Data) throws -> Data {
  95. if data.count != SwiftGCM.blockSize {
  96. throw SwiftGCMError.invalidDataSize
  97. }
  98. var dataMutable: Data = data
  99. var keyMutable: Data = key
  100. let operation: UInt32 = CCOperation(kCCEncrypt)
  101. let algorithm: UInt32 = CCAlgorithm(kCCAlgorithmAES)
  102. let options: UInt32 = CCOptions(kCCOptionECBMode)
  103. var ct: Data = Data(count: data.count)
  104. let ctCount = ct.count
  105. var num: size_t = 0
  106. let status = ct.withUnsafeMutableBytes { ctRaw in
  107. dataMutable.withUnsafeMutableBytes { dataRaw in
  108. keyMutable.withUnsafeMutableBytes{ keyRaw in
  109. CCCrypt(operation, algorithm, options, keyRaw, key.count, nil, dataRaw, data.count, ctRaw, ctCount, &num)
  110. }
  111. }
  112. }
  113. if status != kCCSuccess {
  114. throw SwiftGCMError.commonCryptoError(err: status)
  115. }
  116. return ct
  117. }
  118. // Counter.
  119. private static func makeCounter(nonce: Data) -> UInt128 {
  120. var result = Data()
  121. result.append(nonce)
  122. result.append(SwiftGCM.initialCounterSuffix)
  123. return UInt128(raw: result)
  124. }
  125. // Misc.
  126. private static func xorData(d1: Data, d2: Data) -> Data {
  127. var d1a: [UInt8] = [UInt8](d1)
  128. var d2a: [UInt8] = [UInt8](d2)
  129. var result: Data = Data(count: d1.count)
  130. for i in 0..<d1.count {
  131. let n1: UInt8 = d1a[i]
  132. let n2: UInt8 = d2a[i]
  133. result[i] = n1 ^ n2
  134. }
  135. return result
  136. }
  137. private static func tsCompare(d1: Data, d2: Data) -> Bool {
  138. if d1.count != d2.count { return false }
  139. var d1a: [UInt8] = [UInt8](d1)
  140. var d2a: [UInt8] = [UInt8](d2)
  141. var result: UInt8 = 0
  142. for i in 0..<d1.count {
  143. result |= d1a[i] ^ d2a[i]
  144. }
  145. return result == 0
  146. }
  147. }
  148. public enum SwiftGCMError: Error {
  149. case invalidKeySize
  150. case invalidDataSize
  151. case invalidTagSize
  152. case instanceAlreadyUsed
  153. case commonCryptoError(err: Int32)
  154. case authTagValidation
  155. }
  156. public class GaloisField {
  157. private static let one: UInt128 = UInt128(b: 1)
  158. private static let r: UInt128 = UInt128(a: 0xE100000000000000, b: 0)
  159. private static let blockSize: Int = 16
  160. // Multiplication GF(2^128).
  161. public static func multiply(_ x: UInt128, _ y: UInt128) -> UInt128 {
  162. var z: UInt128 = UInt128(b: 0)
  163. var v: UInt128 = x
  164. var k: UInt128 = UInt128(a: 1 << 63, b: 0)
  165. for _ in 0...127 {
  166. if y & k == k {
  167. z = z ^ v
  168. }
  169. if v & GaloisField.one != GaloisField.one {
  170. v = UInt128.rightShift(v)
  171. } else {
  172. v = UInt128.rightShift(v) ^ r
  173. }
  174. k = UInt128.rightShift(k)
  175. }
  176. return z
  177. }
  178. public static func tableMultiply(_ x: UInt128, _ t: [[UInt128]]) -> UInt128 {
  179. var z: UInt128 = UInt128(b: 0)
  180. var xd: Data = x.getData()
  181. for i in 0..<16 {
  182. z = z ^ t[i][Int(xd[i])]
  183. }
  184. return z
  185. }
  186. // GHASH.
  187. public static func hash(h: UInt128, a: Data, c: Data) -> UInt128 {
  188. let ap: Data = padToBlockSize(a)
  189. let cp: Data = padToBlockSize(c)
  190. let m: Int = ap.count / blockSize
  191. let n: Int = cp.count / blockSize
  192. var apos: Int = 0
  193. var cpos: Int = 0
  194. var x: UInt128 = UInt128(b: 0)
  195. for _ in 0...m - 1 {
  196. let k: UInt128 = x ^ UInt128(raw: ap[ap.startIndex + apos..<ap.startIndex + apos + blockSize])
  197. x = multiply(k, h)
  198. apos += blockSize
  199. }
  200. for _ in 0...n - 1 {
  201. let k: UInt128 = x ^ UInt128(raw: cp[cp.startIndex + cpos..<cp.startIndex + cpos + blockSize])
  202. x = multiply(k, h)
  203. cpos += blockSize
  204. }
  205. let len: UInt128 = UInt128(a: UInt64(a.count * 8), b: UInt64(c.count * 8))
  206. x = multiply((x ^ len), h)
  207. return x
  208. }
  209. public static func tableHash(t: [[UInt128]], a: Data, c: Data) -> UInt128 {
  210. let ap: Data = padToBlockSize(a)
  211. let cp: Data = padToBlockSize(c)
  212. let m: Int = ap.count / blockSize
  213. let n: Int = cp.count / blockSize
  214. var apos: Int = 0
  215. var cpos: Int = 0
  216. var x: UInt128 = UInt128(b: 0)
  217. for _ in 0...m - 1 {
  218. let k: UInt128 = x ^ UInt128(raw: ap[ap.startIndex + apos..<ap.startIndex + apos + blockSize])
  219. x = tableMultiply(k, t)
  220. apos += blockSize
  221. }
  222. for _ in 0...n - 1 {
  223. let k: UInt128 = x ^ UInt128(raw: cp[cp.startIndex + cpos..<cp.startIndex + cpos + blockSize])
  224. x = tableMultiply(k, t)
  225. cpos += blockSize
  226. }
  227. let len: UInt128 = UInt128(a: UInt64(a.count * 8), b: UInt64(c.count * 8))
  228. x = tableMultiply((x ^ len), t)
  229. return x
  230. }
  231. // Padding.
  232. public static func padToBlockSize(_ x: Data) -> Data {
  233. let count: Int = blockSize - x.count % blockSize
  234. var result: Data = Data()
  235. result.append(x)
  236. for _ in 1...count {
  237. result.append(0)
  238. }
  239. return result
  240. }
  241. }
  242. public struct UInt128 {
  243. var a: UInt64
  244. var b: UInt64
  245. // Constructors.
  246. init(raw: Data) {
  247. let ar: Data = raw[raw.startIndex..<raw.startIndex + 8]
  248. let br: Data = raw[raw.startIndex + 8..<raw.startIndex + 16]
  249. a = ar.withUnsafeBytes { (p: UnsafePointer<UInt64>) -> UInt64 in
  250. return p.pointee
  251. }
  252. b = br.withUnsafeBytes { (p: UnsafePointer<UInt64>) -> UInt64 in
  253. return p.pointee
  254. }
  255. a = a.bigEndian
  256. b = b.bigEndian
  257. }
  258. init (a: UInt64, b: UInt64) {
  259. self.a = a
  260. self.b = b
  261. }
  262. init (b: UInt64) {
  263. self.a = 0
  264. self.b = b
  265. }
  266. // Data.
  267. public func getData() -> Data {
  268. var at: UInt64 = self.a.bigEndian
  269. var bt: UInt64 = self.b.bigEndian
  270. let ar: Data = Data(bytes: &at, count: MemoryLayout.size(ofValue: at))
  271. let br: Data = Data(bytes: &bt, count: MemoryLayout.size(ofValue: bt))
  272. var result: Data = Data()
  273. result.append(ar)
  274. result.append(br)
  275. return result
  276. }
  277. // Increment.
  278. public func increment() -> UInt128 {
  279. let bn: UInt64 = b + 1
  280. let an: UInt64 = (bn == 0 ? a + 1 : a)
  281. return UInt128(a: an, b: bn)
  282. }
  283. // XOR.
  284. public static func ^(n1: UInt128, n2: UInt128) -> UInt128 {
  285. let aX: UInt64 = n1.a ^ n2.a
  286. let bX: UInt64 = n1.b ^ n2.b
  287. return UInt128(a: aX, b: bX)
  288. }
  289. // AND.
  290. public static func &(n1: UInt128, n2: UInt128) -> UInt128 {
  291. let aX: UInt64 = n1.a & n2.a
  292. let bX: UInt64 = n1.b & n2.b
  293. return UInt128(a: aX, b: bX)
  294. }
  295. // Right Shift.
  296. public static func rightShift(_ n: UInt128) -> UInt128 {
  297. let aX: UInt64 = n.a >> 1
  298. let bX: UInt64 = n.b >> 1 + ((n.a & 1) << 63)
  299. return UInt128(a: aX, b: bX)
  300. }
  301. // Left Shift.
  302. public static func leftShift(_ n: UInt128, _ x: UInt64) -> UInt128 {
  303. if x < 64 {
  304. let d: UInt64 = (1 << (x + 1)) - 1
  305. let aXt: UInt64 = (n.b >> (64 as UInt64 - x)) & d
  306. let aX: UInt64 = n.a << x + aXt
  307. let bX: UInt64 = n.b << x
  308. return UInt128(a: aX, b: bX)
  309. }
  310. let aX: UInt64 = n.b << (x - 64)
  311. let bX: UInt64 = 0
  312. return UInt128(a: aX, b: bX)
  313. }
  314. // Equality.
  315. public static func ==(lhs: UInt128, rhs: UInt128) -> Bool {
  316. return lhs.a == rhs.a && lhs.b == rhs.b
  317. }
  318. public static func !=(lhs: UInt128, rhs: UInt128) -> Bool {
  319. return !(lhs == rhs)
  320. }
  321. }