Poly1305.swift 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. //
  2. // Poly1305.swift
  3. // CryptoSwift
  4. //
  5. // Created by Marcin Krzyzanowski on 30/08/14.
  6. // Copyright (c) 2014 Marcin Krzyzanowski. All rights reserved.
  7. //
  8. // http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-4
  9. //
  10. // Poly1305 takes a 32-byte, one-time key and a message and produces a 16-byte tag that authenticates the
  11. // message such that an attacker has a negligible chance of producing a valid tag for an inauthentic message.
  12. import Foundation
  13. public class Poly1305 {
  14. let blockSize = 16
  15. var buffer:[Byte] = [Byte](count: 16, repeatedValue: 0)
  16. var r:[Byte] = [Byte](count: 17, repeatedValue: 0)
  17. var h:[Byte] = [Byte](count: 17, repeatedValue: 0)
  18. var pad:[Byte] = [Byte](count: 17, repeatedValue: 0)
  19. var final:Byte = 0
  20. var leftover:Int = 0
  21. public init (key: [Byte]) {
  22. if (key.count != 32) {
  23. return;
  24. }
  25. for i in 0..<17 {
  26. h[i] = 0
  27. }
  28. for i in 0..<16 {
  29. r[i] = key[i] & 0x0f
  30. pad[i] = key[i + 16]
  31. }
  32. h[16] = 0
  33. r[16] = 0
  34. pad[16] = 0
  35. leftover = 0
  36. final = 0
  37. }
  38. deinit {
  39. for i in 0..<(r.count) {
  40. r[i] = 0
  41. h[i] = 0
  42. pad[i] = 0
  43. final = 0
  44. leftover = 0
  45. }
  46. }
  47. func add(inout h:[Byte], c:[Byte]) -> Bool {
  48. if (h.count != 17 && c.count != 17) {
  49. return false
  50. }
  51. var u:UInt16 = 0
  52. for i in 0..<h.count {
  53. u = u &+ UInt16(h[i]) &+ UInt16(c[i])
  54. h[0] = Byte.withValue(u)
  55. u = u &>> 8 // u = u >> 8
  56. }
  57. return true
  58. }
  59. func squeeze(inout h:[Byte], hr:[UInt32]) -> Bool {
  60. if (h.count != 17 && hr.count != 17) {
  61. return false
  62. }
  63. var u:UInt32 = 0
  64. for i in 0..<16 {
  65. u = u &+ hr[i];
  66. h[i] = Byte.withValue(u) // crash! h[i] = UInt8(u) & 0xff
  67. u = u >> 8;
  68. }
  69. u = u &+ hr[16]
  70. h[16] = Byte.withValue(u) & 0x03
  71. u = u >> 2
  72. u += (u << 2); /* u *= 5; */
  73. for i in 0..<16 {
  74. u = u &+ UInt32(h[i])
  75. h[i] = Byte.withValue(u) // crash! h[i] = UInt8(u) & 0xff
  76. u = u >> 8
  77. }
  78. h[16] = h[16] &+ Byte.withValue(u);
  79. return true
  80. }
  81. func freeze(inout h:[Byte]) -> Bool {
  82. if (h.count != 17) {
  83. return false
  84. }
  85. let minusp:[Byte] = [0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc]
  86. var horig:[Byte] = [Byte](count: 17, repeatedValue: 0)
  87. /* compute h + -p */
  88. for i in 0..<17 {
  89. horig[i] = h[i]
  90. }
  91. add(&h, c: minusp)
  92. /* select h if h < p, or h + -p if h >= p */
  93. let bits:[Bit] = (h[16] >> 7).bits()
  94. let invertedBits = bits.map({ (bit) -> Bit in
  95. return bit.inverted()
  96. })
  97. let negative = Byte(bits: invertedBits)
  98. for i in 0..<17 {
  99. h[i] ^= negative & (horig[i] ^ h[i]);
  100. }
  101. return true;
  102. }
  103. func blocks(m:[Byte], startPos:Int = 0) -> Int {
  104. var bytes = m.count
  105. let hibit = final ^ 1 // 1 <<128
  106. var mPos = startPos
  107. while (bytes >= Int(blockSize)) {
  108. var hr:[UInt32] = [UInt32](count: 17, repeatedValue: 0)
  109. var u:UInt32 = 0
  110. var c:[Byte] = [Byte](count: 17, repeatedValue: 0)
  111. /* h += m */
  112. for i in 0..<16 {
  113. c[i] = m[mPos + i]
  114. }
  115. c[16] = hibit
  116. add(&h,c: c)
  117. /* h *= r */
  118. for i in 0..<17 {
  119. u = 0
  120. for j in 0...i {
  121. u = u + UInt32(UInt16(h[j])) * UInt32(r[i - j]) // u += (unsigned short)st->h[j] * st->r[i - j];
  122. }
  123. for j in (i+1)..<17 {
  124. var v:UInt32 = UInt32(UInt16(h[j])) * UInt32(r[i + 17 - j]) // unsigned long v = (unsigned short)st->h[j] * st->r[i + 17 - j];
  125. v = ((v &<< 8) &+ (v &<< 6))
  126. u = u &+ v
  127. }
  128. hr[i] = u
  129. }
  130. squeeze(&h, hr: hr)
  131. mPos += blockSize //m = m + blockSize
  132. bytes -= blockSize
  133. }
  134. return mPos
  135. }
  136. public func finish(inout mac:[Byte]) -> Bool {
  137. if (mac.count != 16) {
  138. return false
  139. }
  140. /* process the remaining block */
  141. if (leftover > 0) {
  142. var i = leftover
  143. buffer[i++] = 1
  144. for (; i < blockSize; i++) {
  145. buffer[i] = 0
  146. }
  147. final = 1
  148. blocks(buffer)
  149. }
  150. /* fully reduce h */
  151. freeze(&h)
  152. /* h = (h + pad) % (1 << 128) */
  153. add(&h, c: pad)
  154. for i in 0..<16 {
  155. mac[i] = h[i]
  156. }
  157. return true
  158. }
  159. public func update(m:[Byte]) {
  160. var bytes = m.count
  161. var mPos = 0
  162. /* handle leftover */
  163. if (leftover > 0) {
  164. var want = blockSize - leftover
  165. if (want > bytes) {
  166. want = bytes
  167. }
  168. for i in 0..<want {
  169. buffer[leftover + i] = m[mPos + i]
  170. }
  171. bytes -= want
  172. mPos += want
  173. leftover += want
  174. if (leftover < blockSize) {
  175. return
  176. }
  177. blocks(buffer)
  178. leftover = 0
  179. }
  180. /* process full blocks */
  181. if (bytes >= blockSize) {
  182. var want = bytes & ~(blockSize - 1)
  183. blocks(m, startPos: mPos)
  184. mPos += want
  185. bytes -= want;
  186. }
  187. /* store leftover */
  188. if (bytes > 0) {
  189. for i in 0..<bytes {
  190. buffer[leftover + 1] = m[i]
  191. }
  192. leftover += bytes
  193. }
  194. }
  195. public func auth(inout mac:[Byte], m:[Byte]) {
  196. update(m)
  197. finish(&mac)
  198. }
  199. }