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