2 * loosely based on djb's reference implementation. modified
3 * to xor things in-place. this file is hereby placed in public domain.
7 #define SNUFFLE_WORDS (SNUFFLE_LEN/sizeof(u32))
10 #define ROTL32(v,c) ((v<<c)|(v>>(32-c)))
13 #define ROTATE(v,c) (ROTL32(v,c))
14 #define XOR(v,w) ((v) ^ (w))
15 #define PLUS(v,w) ((u32)((v) + (w)))
18 /* basic salsa transformation */
19 static inline void salsa_transform(const int rounds
, const u32
*input
, u32
*x
)
26 for (i
= rounds
;i
> 0;i
-= 2) {
27 x
[ 4] = XOR(x
[ 4],ROTATE(PLUS(x
[ 0],x
[12]), 7));
28 x
[ 8] = XOR(x
[ 8],ROTATE(PLUS(x
[ 4],x
[ 0]), 9));
29 x
[12] = XOR(x
[12],ROTATE(PLUS(x
[ 8],x
[ 4]),13));
30 x
[ 0] = XOR(x
[ 0],ROTATE(PLUS(x
[12],x
[ 8]),18));
32 x
[ 9] = XOR(x
[ 9],ROTATE(PLUS(x
[ 5],x
[ 1]), 7));
33 x
[13] = XOR(x
[13],ROTATE(PLUS(x
[ 9],x
[ 5]), 9));
34 x
[ 1] = XOR(x
[ 1],ROTATE(PLUS(x
[13],x
[ 9]),13));
35 x
[ 5] = XOR(x
[ 5],ROTATE(PLUS(x
[ 1],x
[13]),18));
37 x
[14] = XOR(x
[14],ROTATE(PLUS(x
[10],x
[ 6]), 7));
38 x
[ 2] = XOR(x
[ 2],ROTATE(PLUS(x
[14],x
[10]), 9));
39 x
[ 6] = XOR(x
[ 6],ROTATE(PLUS(x
[ 2],x
[14]),13));
40 x
[10] = XOR(x
[10],ROTATE(PLUS(x
[ 6],x
[ 2]),18));
42 x
[ 3] = XOR(x
[ 3],ROTATE(PLUS(x
[15],x
[11]), 7));
43 x
[ 7] = XOR(x
[ 7],ROTATE(PLUS(x
[ 3],x
[15]), 9));
44 x
[11] = XOR(x
[11],ROTATE(PLUS(x
[ 7],x
[ 3]),13));
45 x
[15] = XOR(x
[15],ROTATE(PLUS(x
[11],x
[ 7]),18));
47 x
[ 1] = XOR(x
[ 1],ROTATE(PLUS(x
[ 0],x
[ 3]), 7));
48 x
[ 2] = XOR(x
[ 2],ROTATE(PLUS(x
[ 1],x
[ 0]), 9));
49 x
[ 3] = XOR(x
[ 3],ROTATE(PLUS(x
[ 2],x
[ 1]),13));
50 x
[ 0] = XOR(x
[ 0],ROTATE(PLUS(x
[ 3],x
[ 2]),18));
52 x
[ 6] = XOR(x
[ 6],ROTATE(PLUS(x
[ 5],x
[ 4]), 7));
53 x
[ 7] = XOR(x
[ 7],ROTATE(PLUS(x
[ 6],x
[ 5]), 9));
54 x
[ 4] = XOR(x
[ 4],ROTATE(PLUS(x
[ 7],x
[ 6]),13));
55 x
[ 5] = XOR(x
[ 5],ROTATE(PLUS(x
[ 4],x
[ 7]),18));
57 x
[11] = XOR(x
[11],ROTATE(PLUS(x
[10],x
[ 9]), 7));
58 x
[ 8] = XOR(x
[ 8],ROTATE(PLUS(x
[11],x
[10]), 9));
59 x
[ 9] = XOR(x
[ 9],ROTATE(PLUS(x
[ 8],x
[11]),13));
60 x
[10] = XOR(x
[10],ROTATE(PLUS(x
[ 9],x
[ 8]),18));
62 x
[12] = XOR(x
[12],ROTATE(PLUS(x
[15],x
[14]), 7));
63 x
[13] = XOR(x
[13],ROTATE(PLUS(x
[12],x
[15]), 9));
64 x
[14] = XOR(x
[14],ROTATE(PLUS(x
[13],x
[12]),13));
65 x
[15] = XOR(x
[15],ROTATE(PLUS(x
[14],x
[13]),18));
69 /* encrypt stream of arbitrary length, in-place. count is number of SNUFFLE_LEN blocks */
70 static inline void salsa_crypt_inplace(const int rounds
, void *data
, const int count
, const void *inkey
, const u64 iv
)
74 u32 wkey
[SNUFFLE_WORDS
];
75 u32 hash
[SNUFFLE_WORDS
];
77 /* compute first key */
78 memcpy(wkey
, inkey
, SNUFFLE_LEN
);
79 *(u64
*) (&wkey
[SNUFFLE_WORDS
-2]) += iv
;
82 salsa_transform(rounds
, wkey
, hash
);
83 for (j
= 0; j
< SNUFFLE_WORDS
; ++j
)
84 ptr
[j
] ^= PLUS(hash
[j
], wkey
[j
]);
86 (*(u64
*) (&wkey
[SNUFFLE_WORDS
-2]))++;
90 /* encrypt stream of arbitrary length, in-place. count is number of SNUFFLE_LEN blocks */
91 static inline void salsa_crypt(const int rounds
, const void *data
, void *dest
, const int count
, const void *inkey
, const u64 iv
)
94 const u32
*ptr
= data
;
96 u32 wkey
[SNUFFLE_WORDS
];
97 u32 hash
[SNUFFLE_WORDS
];
99 /* compute first key */
100 memcpy(wkey
, inkey
, SNUFFLE_LEN
);
101 *(u64
*) (&wkey
[SNUFFLE_WORDS
-2]) += iv
;
104 salsa_transform(rounds
, wkey
, hash
);
105 for (j
= 0; j
< SNUFFLE_WORDS
; ++j
)
106 dptr
[j
] = ptr
[j
] ^ PLUS(hash
[j
], wkey
[j
]);
107 ptr
+= SNUFFLE_WORDS
;
108 dptr
+= SNUFFLE_WORDS
;
109 (*(u64
*) (&wkey
[SNUFFLE_WORDS
-2]))++;