1 /*
2 version 20140420
3 D. J. Bernstein
4 Public 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 
18 static int
stream_ref(unsigned char * c,unsigned long long clen,const unsigned char * n,const unsigned char * k)19 stream_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 
63 static int
stream_ref_xor_ic(unsigned char * c,const unsigned char * m,unsigned long long mlen,const unsigned char * n,uint64_t ic,const unsigned char * k)64 stream_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 
114 struct 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