1 // SPDX-License-Identifier: BSD-2-Clause
2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 *
4 * LibTomCrypt is a library that provides various cryptographic
5 * algorithms in a highly modular and flexible manner.
6 *
7 * The library is free for all purposes without any express
8 * guarantee it works.
9 */
10
11 /* The implementation is based on:
12 * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf
13 * and salsa20-ref.c version 20051118
14 * Public domain from D. J. Bernstein
15 */
16
17 #include "tomcrypt_private.h"
18
19 #ifdef LTC_SALSA20
20
21 #define QUARTERROUND(a,b,c,d) \
22 x[b] ^= (ROL((x[a] + x[d]), 7)); \
23 x[c] ^= (ROL((x[b] + x[a]), 9)); \
24 x[d] ^= (ROL((x[c] + x[b]), 13)); \
25 x[a] ^= (ROL((x[d] + x[c]), 18));
26
_salsa20_block(unsigned char * output,const ulong32 * input,int rounds)27 static void _salsa20_block(unsigned char *output, const ulong32 *input, int rounds)
28 {
29 ulong32 x[16];
30 int i;
31 XMEMCPY(x, input, sizeof(x));
32 for (i = rounds; i > 0; i -= 2) {
33 QUARTERROUND( 0, 4, 8,12)
34 QUARTERROUND( 5, 9,13, 1)
35 QUARTERROUND(10,14, 2, 6)
36 QUARTERROUND(15, 3, 7,11)
37 QUARTERROUND( 0, 1, 2, 3)
38 QUARTERROUND( 5, 6, 7, 4)
39 QUARTERROUND(10,11, 8, 9)
40 QUARTERROUND(15,12,13,14)
41 }
42 for (i = 0; i < 16; ++i) {
43 x[i] += input[i];
44 STORE32L(x[i], output + 4 * i);
45 }
46 }
47
48 /**
49 Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Salsa20
50 @param st The Salsa20 state
51 @param in The plaintext (or ciphertext)
52 @param inlen The length of the input (octets)
53 @param out [out] The ciphertext (or plaintext), length inlen
54 @return CRYPT_OK if successful
55 */
salsa20_crypt(salsa20_state * st,const unsigned char * in,unsigned long inlen,unsigned char * out)56 int salsa20_crypt(salsa20_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out)
57 {
58 unsigned char buf[64];
59 unsigned long i, j;
60
61 if (inlen == 0) return CRYPT_OK; /* nothing to do */
62
63 LTC_ARGCHK(st != NULL);
64 LTC_ARGCHK(in != NULL);
65 LTC_ARGCHK(out != NULL);
66 LTC_ARGCHK(st->ivlen == 8 || st->ivlen == 24);
67
68 if (st->ksleft > 0) {
69 j = MIN(st->ksleft, inlen);
70 for (i = 0; i < j; ++i, st->ksleft--) out[i] = in[i] ^ st->kstream[64 - st->ksleft];
71 inlen -= j;
72 if (inlen == 0) return CRYPT_OK;
73 out += j;
74 in += j;
75 }
76 for (;;) {
77 _salsa20_block(buf, st->input, st->rounds);
78 /* Salsa20: 64-bit IV, increment 64-bit counter */
79 if (0 == ++st->input[8] && 0 == ++st->input[9]) return CRYPT_OVERFLOW;
80 if (inlen <= 64) {
81 for (i = 0; i < inlen; ++i) out[i] = in[i] ^ buf[i];
82 st->ksleft = 64 - inlen;
83 for (i = inlen; i < 64; ++i) st->kstream[i] = buf[i];
84 return CRYPT_OK;
85 }
86 for (i = 0; i < 64; ++i) out[i] = in[i] ^ buf[i];
87 inlen -= 64;
88 out += 64;
89 in += 64;
90 }
91 }
92
93 #endif
94
95 /* ref: $Format:%D$ */
96 /* git commit: $Format:%H$ */
97 /* commit time: $Format:%ai$ */
98