Poly1305.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /**
  2. This code is licensed under the MCGSI Public License
  3. Copyright 2018 Jeff Becker
  4. Kovri go write your own code
  5. */
  6. #ifndef LIBI2PD_POLY1305_H
  7. #define LIBI2PD_POLY1305_H
  8. #include <cstdint>
  9. #include <cstring>
  10. #include "Crypto.h"
  11. #if !OPENSSL_AEAD_CHACHA20_POLY1305
  12. namespace i2p
  13. {
  14. namespace crypto
  15. {
  16. const std::size_t POLY1305_DIGEST_BYTES = 16;
  17. const std::size_t POLY1305_DIGEST_DWORDS = 4;
  18. const std::size_t POLY1305_KEY_BYTES = 32;
  19. const std::size_t POLY1305_KEY_DWORDS = 8;
  20. const std::size_t POLY1305_BLOCK_BYTES = 16;
  21. namespace poly1305
  22. {
  23. struct LongBlock
  24. {
  25. unsigned long data[17];
  26. operator unsigned long * ()
  27. {
  28. return data;
  29. }
  30. };
  31. struct Block
  32. {
  33. unsigned char data[17];
  34. void Zero()
  35. {
  36. memset(data, 0, sizeof(data));
  37. }
  38. operator uint8_t * ()
  39. {
  40. return data;
  41. }
  42. Block & operator += (const Block & other)
  43. {
  44. unsigned short u;
  45. unsigned int i;
  46. for(u = 0, i = 0; i < 17; i++)
  47. {
  48. u += (unsigned short) data[i] + (unsigned short) other.data[i];
  49. data[i] = (unsigned char) u & 0xff;
  50. u >>= 8;
  51. }
  52. return *this;
  53. }
  54. Block & operator %=(const LongBlock & other)
  55. {
  56. unsigned long u;
  57. unsigned int i;
  58. u = 0;
  59. for (i = 0; i < 16; i++) {
  60. u += other.data[i];
  61. data[i] = (unsigned char)u & 0xff;
  62. u >>= 8;
  63. }
  64. u += other.data[16];
  65. data[16] = (unsigned char)u & 0x03;
  66. u >>= 2;
  67. u += (u << 2);
  68. for (i = 0; i < 16; i++) {
  69. u += data[i];
  70. data[i] = (unsigned char)u & 0xff;
  71. u >>= 8;
  72. }
  73. data[16] += (unsigned char)u;
  74. return *this;
  75. }
  76. Block & operator = (const Block & other)
  77. {
  78. memcpy(data, other.data, sizeof(data));
  79. return *this;
  80. }
  81. Block & operator ~ ()
  82. {
  83. static const Block minusp = {
  84. 0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  85. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  86. 0xfc
  87. };
  88. Block orig;
  89. unsigned char neg;
  90. unsigned int i;
  91. orig = *this;
  92. *this += minusp;
  93. neg = -(data[16] >> 7);
  94. for(i = 0; i < 17; i++)
  95. data[i] ^= neg & (orig.data[i] ^ data[i]);
  96. return *this;
  97. }
  98. void PutKey(const uint64_t * key_l)
  99. {
  100. const uint8_t * key = (const uint8_t*) key_l;
  101. data[0] = key[0] & 0xff;
  102. data[1] = key[1] & 0xff;
  103. data[2] = key[2] & 0xff;
  104. data[3] = key[3] & 0x0f;
  105. data[4] = key[4] & 0xfc;
  106. data[5] = key[5] & 0xff;
  107. data[6] = key[6] & 0xff;
  108. data[7] = key[7] & 0x0f;
  109. data[8] = key[8] & 0xfc;
  110. data[9] = key[9] & 0xff;
  111. data[10] = key[10] & 0xff;
  112. data[11] = key[11] & 0x0f;
  113. data[12] = key[12] & 0xfc;
  114. data[13] = key[13] & 0xff;
  115. data[14] = key[14] & 0xff;
  116. data[15] = key[15] & 0x0f;
  117. data[16] = 0;
  118. }
  119. template<typename Int_t>
  120. void Put(const Int_t * d, uint8_t last=0)
  121. {
  122. memcpy(data, d, 16);
  123. data[16] = last;
  124. }
  125. };
  126. struct Buffer
  127. {
  128. uint8_t data[POLY1305_BLOCK_BYTES];
  129. operator uint8_t * ()
  130. {
  131. return data;
  132. }
  133. };
  134. }
  135. struct Poly1305
  136. {
  137. Poly1305(const uint64_t * key)
  138. {
  139. m_Leftover = 0;
  140. m_H.Zero();
  141. m_Final = 0;
  142. m_R.PutKey(key);
  143. m_Pad.Put(key + 2);
  144. }
  145. void Update(const uint8_t * buf, size_t sz)
  146. {
  147. // process leftover
  148. if(m_Leftover)
  149. {
  150. size_t want = POLY1305_BLOCK_BYTES - m_Leftover;
  151. if(want > sz) want = sz;
  152. memcpy(m_Buffer + m_Leftover, buf, want);
  153. sz -= want;
  154. buf += want;
  155. m_Leftover += want;
  156. if(m_Leftover < POLY1305_BLOCK_BYTES) return;
  157. Blocks(m_Buffer, POLY1305_BLOCK_BYTES);
  158. m_Leftover = 0;
  159. }
  160. // process blocks
  161. if(sz >= POLY1305_BLOCK_BYTES)
  162. {
  163. size_t want = (sz & ~(POLY1305_BLOCK_BYTES - 1));
  164. Blocks(buf, want);
  165. buf += want;
  166. sz -= want;
  167. }
  168. // leftover
  169. if(sz)
  170. {
  171. memcpy(m_Buffer+m_Leftover, buf, sz);
  172. m_Leftover += sz;
  173. }
  174. }
  175. void Blocks(const uint8_t * buf, size_t sz)
  176. {
  177. const unsigned char hi = m_Final ^ 1;
  178. while (sz >= POLY1305_BLOCK_BYTES) {
  179. unsigned long u;
  180. unsigned int i, j;
  181. m_Msg.Put(buf, hi);
  182. /* h += m */
  183. m_H += m_Msg;
  184. /* h *= r */
  185. for (i = 0; i < 17; i++) {
  186. u = 0;
  187. for (j = 0; j <= i ; j++) {
  188. u += (unsigned short)m_H.data[j] * m_R.data[i - j];
  189. }
  190. for (j = i + 1; j < 17; j++) {
  191. unsigned long v = (unsigned short)m_H.data[j] * m_R.data[i + 17 - j];
  192. v = ((v << 8) + (v << 6)); /* v *= (5 << 6); */
  193. u += v;
  194. }
  195. m_HR[i] = u;
  196. }
  197. /* (partial) h %= p */
  198. m_H %= m_HR;
  199. buf += POLY1305_BLOCK_BYTES;
  200. sz -= POLY1305_BLOCK_BYTES;
  201. }
  202. }
  203. void Finish(uint64_t * out)
  204. {
  205. // process leftovers
  206. if(m_Leftover)
  207. {
  208. size_t idx = m_Leftover;
  209. m_Buffer[idx++] = 1;
  210. for(; idx < POLY1305_BLOCK_BYTES; idx++)
  211. m_Buffer[idx] = 0;
  212. m_Final = 1;
  213. Blocks(m_Buffer, POLY1305_BLOCK_BYTES);
  214. }
  215. // freeze H
  216. ~m_H;
  217. // add pad
  218. m_H += m_Pad;
  219. // copy digest
  220. memcpy(out, m_H, 16);
  221. }
  222. size_t m_Leftover;
  223. poly1305::Buffer m_Buffer;
  224. poly1305::Block m_H;
  225. poly1305::Block m_R;
  226. poly1305::Block m_Pad;
  227. poly1305::Block m_Msg;
  228. poly1305::LongBlock m_HR;
  229. uint8_t m_Final;
  230. };
  231. void Poly1305HMAC(uint64_t * out, const uint64_t * key, const uint8_t * buf, std::size_t sz);
  232. }
  233. }
  234. #endif
  235. #endif