1/*
2version 20140420
3D. J. Bernstein
4Public domain.
5*/
6
7#include <stdint.h>
8
9#include "crypto_core_salsa20.h"
10#include "crypto_stream_salsa20.h"
11#include "utils.h"
12
13#include "../stream_salsa20.h"
14#include "salsa20_ref.h"
15
16#ifndef HAVE_AMD64_ASM
17
18static int
19stream_ref(unsigned char *c, unsigned long long clen, const unsigned char *n,
20           const unsigned char *k)
21{
22    unsigned char in[16];
23    unsigned char block[64];
24    unsigned char kcopy[32];
25    unsigned int  i;
26    unsigned int  u;
27
28    if (!clen) {
29        return 0;
30    }
31    for (i = 0; i < 32; i++) {
32        kcopy[i] = k[i];
33    }
34    for (i = 0; i < 8; i++) {
35        in[i] = n[i];
36    }
37    for (i = 8; i < 16; i++) {
38        in[i] = 0;
39    }
40    while (clen >= 64) {
41        crypto_core_salsa20(c, in, kcopy, NULL);
42        u = 1;
43        for (i = 8; i < 16; i++) {
44            u += (unsigned int) in[i];
45            in[i] = u;
46            u >>= 8;
47        }
48        clen -= 64;
49        c += 64;
50    }
51    if (clen) {
52        crypto_core_salsa20(block, in, kcopy, NULL);
53        for (i = 0; i < (unsigned int) clen; i++) {
54            c[i] = block[i];
55        }
56    }
57    sodium_memzero(block, sizeof block);
58    sodium_memzero(kcopy, sizeof kcopy);
59
60    return 0;
61}
62
63static int
64stream_ref_xor_ic(unsigned char *c, const unsigned char *m,
65                  unsigned long long mlen, const unsigned char *n, uint64_t ic,
66                  const unsigned char *k)
67{
68    unsigned char in[16];
69    unsigned char block[64];
70    unsigned char kcopy[32];
71    unsigned int  i;
72    unsigned int  u;
73
74    if (!mlen) {
75        return 0;
76    }
77    for (i = 0; i < 32; i++) {
78        kcopy[i] = k[i];
79    }
80    for (i = 0; i < 8; i++) {
81        in[i] = n[i];
82    }
83    for (i = 8; i < 16; i++) {
84        in[i] = (unsigned char) (ic & 0xff);
85        ic >>= 8;
86    }
87    while (mlen >= 64) {
88        crypto_core_salsa20(block, in, kcopy, NULL);
89        for (i = 0; i < 64; i++) {
90            c[i] = m[i] ^ block[i];
91        }
92        u = 1;
93        for (i = 8; i < 16; i++) {
94            u += (unsigned int) in[i];
95            in[i] = u;
96            u >>= 8;
97        }
98        mlen -= 64;
99        c += 64;
100        m += 64;
101    }
102    if (mlen) {
103        crypto_core_salsa20(block, in, kcopy, NULL);
104        for (i = 0; i < (unsigned int) mlen; i++) {
105            c[i] = m[i] ^ block[i];
106        }
107    }
108    sodium_memzero(block, sizeof block);
109    sodium_memzero(kcopy, sizeof kcopy);
110
111    return 0;
112}
113
114struct crypto_stream_salsa20_implementation
115    crypto_stream_salsa20_ref_implementation = {
116        SODIUM_C99(.stream =) stream_ref,
117        SODIUM_C99(.stream_xor_ic =) stream_ref_xor_ic,
118    };
119
120#endif
121