Salsa20.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /*
  2. * Salsa20.c : Source for the Salsa20 stream cipher.
  3. *
  4. * Part of the Python Cryptography Toolkit
  5. *
  6. * Contributed by Fabrizio Tarizzo <fabrizio@fabriziotarizzo.org>.
  7. * Based on the reference implementation by D. J. Bernstein
  8. * <http://cr.yp.to/snuffle/salsa20/regs/salsa20.c>
  9. *
  10. * =======================================================================
  11. * The contents of this file are dedicated to the public domain. To the
  12. * extent that dedication to the public domain is not available, everyone
  13. * is granted a worldwide, perpetual, royalty-free, non-exclusive license
  14. * to exercise all rights associated with the contents of this file for
  15. * any purpose whatsoever. No rights are reserved.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  21. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  22. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  23. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  24. * SOFTWARE.
  25. * =======================================================================
  26. */
  27. #include "pycrypto_common.h"
  28. FAKE_INIT(Salsa20)
  29. #include "libtom/tomcrypt_cfg.h"
  30. #include "libtom/tomcrypt_custom.h"
  31. #include "libtom/tomcrypt_macros.h"
  32. #define ROUNDS 20
  33. #define MAX_KEY_SIZE 32
  34. static const char sigma[16] = "expand 32-byte k";
  35. static const char tau[16] = "expand 16-byte k";
  36. #define U32TO8_LITTLE(p,w) STORE32L(w, p)
  37. #define U8TO32_LITTLE(w,p) LOAD32L(w, p)
  38. #define ROTATE(v,c) (ROL(v,c))
  39. #define U32V(v) ((uint32_t)(v) & 0xFFFFFFFFUL)
  40. #define XOR(v,w) ((v) ^ (w))
  41. #define PLUS(v,w) (U32V((v) + (w)))
  42. #define PLUSONE(v) (PLUS((v),1))
  43. typedef struct
  44. {
  45. uint32_t input[16];
  46. uint8_t block[64];
  47. uint8_t blockindex;
  48. } stream_state;
  49. static void
  50. _salsa20_block(int rounds, uint32_t *input, uint8_t *output)
  51. {
  52. uint32_t x0, x1, x2, x3, x4, x5, x6, x7;
  53. uint32_t x8, x9, x10, x11, x12, x13, x14, x15;
  54. uint8_t i;
  55. x0 = input[0];
  56. x1 = input[1];
  57. x2 = input[2];
  58. x3 = input[3];
  59. x4 = input[4];
  60. x5 = input[5];
  61. x6 = input[6];
  62. x7 = input[7];
  63. x8 = input[8];
  64. x9 = input[9];
  65. x10 = input[10];
  66. x11 = input[11];
  67. x12 = input[12];
  68. x13 = input[13];
  69. x14 = input[14];
  70. x15 = input[15];
  71. for (i = rounds; i > 0; i -= 2) {
  72. /* Column round */
  73. x4 = XOR ( x4, ROTATE (PLUS ( x0,x12), 7));
  74. x8 = XOR ( x8, ROTATE (PLUS ( x4, x0), 9));
  75. x12 = XOR (x12, ROTATE (PLUS ( x8, x4),13));
  76. x0 = XOR ( x0, ROTATE (PLUS (x12, x8),18));
  77. x9 = XOR ( x9, ROTATE (PLUS ( x5, x1), 7));
  78. x13 = XOR (x13, ROTATE (PLUS ( x9, x5), 9));
  79. x1 = XOR ( x1, ROTATE (PLUS (x13, x9),13));
  80. x5 = XOR ( x5, ROTATE (PLUS ( x1,x13),18));
  81. x14 = XOR (x14, ROTATE (PLUS (x10, x6), 7));
  82. x2 = XOR ( x2, ROTATE (PLUS (x14,x10), 9));
  83. x6 = XOR ( x6, ROTATE (PLUS ( x2,x14),13));
  84. x10 = XOR (x10, ROTATE (PLUS ( x6, x2),18));
  85. x3 = XOR ( x3, ROTATE (PLUS (x15,x11), 7));
  86. x7 = XOR ( x7, ROTATE (PLUS ( x3,x15), 9));
  87. x11 = XOR (x11, ROTATE (PLUS ( x7, x3),13));
  88. x15 = XOR (x15, ROTATE (PLUS (x11, x7),18));
  89. /* Row round */
  90. x1 = XOR ( x1, ROTATE (PLUS ( x0, x3), 7));
  91. x2 = XOR ( x2, ROTATE (PLUS ( x1, x0), 9));
  92. x3 = XOR ( x3, ROTATE (PLUS ( x2, x1),13));
  93. x0 = XOR ( x0, ROTATE (PLUS ( x3, x2),18));
  94. x6 = XOR ( x6, ROTATE (PLUS ( x5, x4), 7));
  95. x7 = XOR ( x7, ROTATE (PLUS ( x6, x5), 9));
  96. x4 = XOR ( x4, ROTATE (PLUS ( x7, x6),13));
  97. x5 = XOR ( x5, ROTATE (PLUS ( x4, x7),18));
  98. x11 = XOR (x11, ROTATE (PLUS (x10, x9), 7));
  99. x8 = XOR ( x8, ROTATE (PLUS (x11,x10), 9));
  100. x9 = XOR ( x9, ROTATE (PLUS ( x8,x11),13));
  101. x10 = XOR (x10, ROTATE (PLUS ( x9, x8),18));
  102. x12 = XOR (x12, ROTATE (PLUS (x15,x14), 7));
  103. x13 = XOR (x13, ROTATE (PLUS (x12,x15), 9));
  104. x14 = XOR (x14, ROTATE (PLUS (x13,x12),13));
  105. x15 = XOR (x15, ROTATE (PLUS (x14,x13),18));
  106. }
  107. x0 = PLUS (x0, input[0]);
  108. x1 = PLUS (x1, input[1]);
  109. x2 = PLUS (x2, input[2]);
  110. x3 = PLUS (x3, input[3]);
  111. x4 = PLUS (x4, input[4]);
  112. x5 = PLUS (x5, input[5]);
  113. x6 = PLUS (x6, input[6]);
  114. x7 = PLUS (x7, input[7]);
  115. x8 = PLUS (x8, input[8]);
  116. x9 = PLUS (x9, input[9]);
  117. x10 = PLUS (x10, input[10]);
  118. x11 = PLUS (x11, input[11]);
  119. x12 = PLUS (x12, input[12]);
  120. x13 = PLUS (x13, input[13]);
  121. x14 = PLUS (x14, input[14]);
  122. x15 = PLUS (x15, input[15]);
  123. U32TO8_LITTLE (output + 0, x0);
  124. U32TO8_LITTLE (output + 4, x1);
  125. U32TO8_LITTLE (output + 8, x2);
  126. U32TO8_LITTLE (output + 12, x3);
  127. U32TO8_LITTLE (output + 16, x4);
  128. U32TO8_LITTLE (output + 20, x5);
  129. U32TO8_LITTLE (output + 24, x6);
  130. U32TO8_LITTLE (output + 28, x7);
  131. U32TO8_LITTLE (output + 32, x8);
  132. U32TO8_LITTLE (output + 36, x9);
  133. U32TO8_LITTLE (output + 40, x10);
  134. U32TO8_LITTLE (output + 44, x11);
  135. U32TO8_LITTLE (output + 48, x12);
  136. U32TO8_LITTLE (output + 52, x13);
  137. U32TO8_LITTLE (output + 56, x14);
  138. U32TO8_LITTLE (output + 60, x15);
  139. /* Increment block counter */
  140. input[8] = PLUSONE (input[8]);
  141. if (!input[8]) {
  142. input[9] = PLUSONE (input[9]);
  143. /* stopping at 2^70 bytes per nonce is user's responsibility */
  144. }
  145. }
  146. /*
  147. * Salsa20/8 Core function (combined with XOR)
  148. *
  149. * This function accepts two 64-byte Python byte strings (x and y).
  150. * It creates a new 64-byte Python byte string with the result
  151. * of the expression salsa20_8(xor(x,y)).
  152. */
  153. EXPORT_SYM int Salsa20_8_core(const uint8_t *x, const uint8_t *y, uint8_t *out)
  154. {
  155. uint32_t input_32[16];
  156. int i;
  157. if (NULL==x || NULL==y || NULL==out)
  158. return ERR_NULL;
  159. for (i=0; i<16; i++) {
  160. uint32_t tmp;
  161. U8TO32_LITTLE(tmp, &x[i*4]);
  162. U8TO32_LITTLE(input_32[i], &y[i*4]);
  163. input_32[i] ^= tmp;
  164. }
  165. _salsa20_block(8, input_32, out);
  166. return 0;
  167. }
  168. EXPORT_SYM int Salsa20_stream_init(uint8_t *key, size_t keylen,
  169. uint8_t *nonce, size_t nonce_len,
  170. stream_state **pSalsaState)
  171. {
  172. const char *constants;
  173. uint32_t *input;
  174. stream_state *salsaState;
  175. if (NULL == pSalsaState || NULL == key || NULL == nonce)
  176. return ERR_NULL;
  177. if (keylen != 16 && keylen != 32)
  178. return ERR_KEY_SIZE;
  179. if (nonce_len != 8)
  180. return ERR_NONCE_SIZE;
  181. *pSalsaState = salsaState = calloc(1, sizeof(stream_state));
  182. if (NULL == salsaState)
  183. return ERR_MEMORY;
  184. input = salsaState->input;
  185. U8TO32_LITTLE (input[1], key);
  186. U8TO32_LITTLE (input[2], key + 4);
  187. U8TO32_LITTLE (input[3], key + 8);
  188. U8TO32_LITTLE (input[4], key + 12);
  189. if (keylen == 32) {
  190. key += 16;
  191. constants = sigma;
  192. } else {
  193. constants = tau;
  194. }
  195. U8TO32_LITTLE (input[11], key + 0);
  196. U8TO32_LITTLE (input[12], key + 4);
  197. U8TO32_LITTLE (input[13], key + 8);
  198. U8TO32_LITTLE (input[14], key + 12);
  199. U8TO32_LITTLE (input[0], constants);
  200. U8TO32_LITTLE (input[5], constants + 4);
  201. U8TO32_LITTLE (input[10], constants + 8);
  202. U8TO32_LITTLE (input[15], constants + 12);
  203. /* nonce setup */
  204. U8TO32_LITTLE (input[6], nonce);
  205. U8TO32_LITTLE (input[7], nonce + 4);
  206. /* Block counter setup*/
  207. input[8] = 0;
  208. input[9] = 0;
  209. salsaState->blockindex = 64;
  210. return 0;
  211. }
  212. EXPORT_SYM int Salsa20_stream_destroy(stream_state *salsaState)
  213. {
  214. free(salsaState);
  215. return 0;
  216. }
  217. EXPORT_SYM int Salsa20_stream_encrypt(stream_state *salsaState, const uint8_t in[],
  218. uint8_t out[], size_t len)
  219. {
  220. unsigned i;
  221. for (i = 0; i < len; ++i) {
  222. if (salsaState->blockindex == 64) {
  223. salsaState->blockindex = 0;
  224. _salsa20_block(ROUNDS, salsaState->input, salsaState->block);
  225. }
  226. out[i] = in[i] ^ salsaState->block[salsaState->blockindex];
  227. salsaState->blockindex++;
  228. }
  229. return 0;
  230. }