Salsa20.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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 "common.h"
  28. #include "endianess.h"
  29. FAKE_INIT(Salsa20)
  30. #define ROUNDS 20
  31. #define MAX_KEY_SIZE 32
  32. static const uint8_t sigma[16] = "expand 32-byte k";
  33. static const uint8_t tau[16] = "expand 16-byte k";
  34. #define ROTL32(v, c) (((v) << (c)) | ((v) >> (32 - (c))))
  35. #define XOR(v,w) ((v) ^ (w))
  36. typedef struct {
  37. uint32_t input[16];
  38. uint8_t block[64];
  39. uint8_t blockindex;
  40. } stream_state;
  41. static void _salsa20_block(unsigned rounds, uint32_t *input, uint8_t *output)
  42. {
  43. unsigned x0, x1, x2, x3, x4, x5, x6, x7;
  44. unsigned x8, x9, x10, x11, x12, x13, x14, x15;
  45. unsigned i;
  46. x0 = input[0];
  47. x1 = input[1];
  48. x2 = input[2];
  49. x3 = input[3];
  50. x4 = input[4];
  51. x5 = input[5];
  52. x6 = input[6];
  53. x7 = input[7];
  54. x8 = input[8];
  55. x9 = input[9];
  56. x10 = input[10];
  57. x11 = input[11];
  58. x12 = input[12];
  59. x13 = input[13];
  60. x14 = input[14];
  61. x15 = input[15];
  62. for (i = rounds; i > 0; i -= 2) {
  63. /* Column round */
  64. x4 = XOR( x4, ROTL32( x0 + x12, 7));
  65. x8 = XOR( x8, ROTL32( x4 + x0, 9));
  66. x12 = XOR(x12, ROTL32( x8 + x4, 13));
  67. x0 = XOR( x0, ROTL32(x12 + x8, 18));
  68. x9 = XOR( x9, ROTL32( x5 + x1, 7));
  69. x13 = XOR(x13, ROTL32( x9 + x5, 9));
  70. x1 = XOR( x1, ROTL32(x13 + x9, 13));
  71. x5 = XOR( x5, ROTL32( x1 + x13, 18));
  72. x14 = XOR(x14, ROTL32(x10 + x6, 7));
  73. x2 = XOR( x2, ROTL32(x14 + x10, 9));
  74. x6 = XOR( x6, ROTL32( x2 + x14, 13));
  75. x10 = XOR(x10, ROTL32( x6 + x2, 18));
  76. x3 = XOR( x3, ROTL32(x15 + x11, 7));
  77. x7 = XOR( x7, ROTL32( x3 + x15, 9));
  78. x11 = XOR(x11, ROTL32( x7 + x3, 13));
  79. x15 = XOR(x15, ROTL32(x11 + x7, 18));
  80. /* Row round */
  81. x1 = XOR( x1, ROTL32( x0 + x3, 7));
  82. x2 = XOR( x2, ROTL32( x1 + x0, 9));
  83. x3 = XOR( x3, ROTL32( x2 + x1, 13));
  84. x0 = XOR( x0, ROTL32( x3 + x2, 18));
  85. x6 = XOR( x6, ROTL32( x5 + x4, 7));
  86. x7 = XOR( x7, ROTL32( x6 + x5, 9));
  87. x4 = XOR( x4, ROTL32( x7 + x6, 13));
  88. x5 = XOR( x5, ROTL32( x4 + x7, 18));
  89. x11 = XOR(x11, ROTL32(x10 + x9, 7));
  90. x8 = XOR( x8, ROTL32(x11 + x10, 9));
  91. x9 = XOR( x9, ROTL32( x8 + x11, 13));
  92. x10 = XOR(x10, ROTL32( x9 + x8, 18));
  93. x12 = XOR(x12, ROTL32(x15 + x14, 7));
  94. x13 = XOR(x13, ROTL32(x12 + x15, 9));
  95. x14 = XOR(x14, ROTL32(x13 + x12, 13));
  96. x15 = XOR(x15, ROTL32(x14 + x13, 18));
  97. }
  98. x0 = x0 + input[0];
  99. x1 = x1 + input[1];
  100. x2 = x2 + input[2];
  101. x3 = x3 + input[3];
  102. x4 = x4 + input[4];
  103. x5 = x5 + input[5];
  104. x6 = x6 + input[6];
  105. x7 = x7 + input[7];
  106. x8 = x8 + input[8];
  107. x9 = x9 + input[9];
  108. x10 = x10 + input[10];
  109. x11 = x11 + input[11];
  110. x12 = x12 + input[12];
  111. x13 = x13 + input[13];
  112. x14 = x14 + input[14];
  113. x15 = x15 + input[15];
  114. STORE_U32_LITTLE (output + 0, x0);
  115. STORE_U32_LITTLE (output + 4, x1);
  116. STORE_U32_LITTLE (output + 8, x2);
  117. STORE_U32_LITTLE (output + 12, x3);
  118. STORE_U32_LITTLE (output + 16, x4);
  119. STORE_U32_LITTLE (output + 20, x5);
  120. STORE_U32_LITTLE (output + 24, x6);
  121. STORE_U32_LITTLE (output + 28, x7);
  122. STORE_U32_LITTLE (output + 32, x8);
  123. STORE_U32_LITTLE (output + 36, x9);
  124. STORE_U32_LITTLE (output + 40, x10);
  125. STORE_U32_LITTLE (output + 44, x11);
  126. STORE_U32_LITTLE (output + 48, x12);
  127. STORE_U32_LITTLE (output + 52, x13);
  128. STORE_U32_LITTLE (output + 56, x14);
  129. STORE_U32_LITTLE (output + 60, x15);
  130. /* Increment block counter */
  131. input[8] = input[8] + 1;
  132. if (!input[8]) {
  133. input[9] = input[9] + 1;
  134. /* stopping at 2^70 bytes per nonce is user's responsibility */
  135. }
  136. }
  137. /*
  138. * Salsa20/8 Core function (combined with XOR)
  139. *
  140. * This function accepts two 64-byte Python byte strings (x and y).
  141. * It creates a new 64-byte Python byte string with the result
  142. * of the expression salsa20_8(xor(x,y)).
  143. */
  144. EXPORT_SYM int Salsa20_8_core(const uint8_t *x, const uint8_t *y, uint8_t *out)
  145. {
  146. uint32_t input_32[16];
  147. int i;
  148. if (NULL==x || NULL==y || NULL==out)
  149. return ERR_NULL;
  150. for (i=0; i<16; i++) {
  151. uint32_t tmp;
  152. tmp = LOAD_U32_LITTLE(&x[i*4]);
  153. input_32[i] = LOAD_U32_LITTLE(&y[i*4]);
  154. input_32[i] ^= tmp;
  155. }
  156. _salsa20_block(8, input_32, out);
  157. return 0;
  158. }
  159. EXPORT_SYM int Salsa20_stream_init(uint8_t *key, size_t keylen,
  160. uint8_t *nonce, size_t nonce_len,
  161. stream_state **pSalsaState)
  162. {
  163. const uint8_t *constants;
  164. uint32_t *input;
  165. stream_state *salsaState;
  166. unsigned i;
  167. if (NULL == pSalsaState || NULL == key || NULL == nonce)
  168. return ERR_NULL;
  169. if (keylen != 16 && keylen != 32)
  170. return ERR_KEY_SIZE;
  171. constants = keylen == 32 ? sigma : tau;
  172. if (nonce_len != 8)
  173. return ERR_NONCE_SIZE;
  174. *pSalsaState = salsaState = calloc(1, sizeof(stream_state));
  175. if (NULL == salsaState)
  176. return ERR_MEMORY;
  177. input = salsaState->input;
  178. input[0] = LOAD_U32_LITTLE(constants + 0);
  179. /** Set input[1..4] **/
  180. for (i=0; i<4; i++)
  181. input[i+1] = LOAD_U32_LITTLE(key + 4*i);
  182. input[5] = LOAD_U32_LITTLE(constants + 4);
  183. input[6] = LOAD_U32_LITTLE(nonce + 0);
  184. input[7] = LOAD_U32_LITTLE(nonce + 4);
  185. /* Block counter setup*/
  186. input[8] = 0;
  187. input[9] = 0;
  188. input[10] = LOAD_U32_LITTLE(constants + 8);
  189. /** Set input[11..14] **/
  190. if (keylen == 32) {
  191. key += 16;
  192. }
  193. for (i=0; i<4; i++)
  194. input[i+11] = LOAD_U32_LITTLE(key + 4*i);
  195. input[15] = LOAD_U32_LITTLE(constants + 12);
  196. salsaState->blockindex = 64;
  197. return 0;
  198. }
  199. EXPORT_SYM int Salsa20_stream_destroy(stream_state *salsaState)
  200. {
  201. free(salsaState);
  202. return 0;
  203. }
  204. EXPORT_SYM int Salsa20_stream_encrypt(stream_state *salsaState, const uint8_t in[],
  205. uint8_t out[], size_t len)
  206. {
  207. unsigned i;
  208. for (i = 0; i < len; ++i) {
  209. if (salsaState->blockindex == 64) {
  210. salsaState->blockindex = 0;
  211. _salsa20_block(ROUNDS, salsaState->input, salsaState->block);
  212. }
  213. out[i] = in[i] ^ salsaState->block[salsaState->blockindex];
  214. salsaState->blockindex++;
  215. }
  216. return 0;
  217. }