10ac341f1SConrad Meyer /*
20ac341f1SConrad Meyer version 20140420
30ac341f1SConrad Meyer D. J. Bernstein
40ac341f1SConrad Meyer Public domain.
50ac341f1SConrad Meyer */
60ac341f1SConrad Meyer
70ac341f1SConrad Meyer #include <stdint.h>
80ac341f1SConrad Meyer
90ac341f1SConrad Meyer #include "crypto_core_salsa20.h"
100ac341f1SConrad Meyer #include "crypto_stream_salsa20.h"
110ac341f1SConrad Meyer #include "utils.h"
120ac341f1SConrad Meyer
130ac341f1SConrad Meyer #include "../stream_salsa20.h"
140ac341f1SConrad Meyer #include "salsa20_ref.h"
150ac341f1SConrad Meyer
160ac341f1SConrad Meyer #ifndef HAVE_AMD64_ASM
170ac341f1SConrad Meyer
180ac341f1SConrad Meyer static int
stream_ref(unsigned char * c,unsigned long long clen,const unsigned char * n,const unsigned char * k)190ac341f1SConrad Meyer stream_ref(unsigned char *c, unsigned long long clen, const unsigned char *n,
200ac341f1SConrad Meyer const unsigned char *k)
210ac341f1SConrad Meyer {
220ac341f1SConrad Meyer unsigned char in[16];
230ac341f1SConrad Meyer unsigned char block[64];
240ac341f1SConrad Meyer unsigned char kcopy[32];
250ac341f1SConrad Meyer unsigned int i;
260ac341f1SConrad Meyer unsigned int u;
270ac341f1SConrad Meyer
280ac341f1SConrad Meyer if (!clen) {
290ac341f1SConrad Meyer return 0;
300ac341f1SConrad Meyer }
310ac341f1SConrad Meyer for (i = 0; i < 32; i++) {
320ac341f1SConrad Meyer kcopy[i] = k[i];
330ac341f1SConrad Meyer }
340ac341f1SConrad Meyer for (i = 0; i < 8; i++) {
350ac341f1SConrad Meyer in[i] = n[i];
360ac341f1SConrad Meyer }
370ac341f1SConrad Meyer for (i = 8; i < 16; i++) {
380ac341f1SConrad Meyer in[i] = 0;
390ac341f1SConrad Meyer }
400ac341f1SConrad Meyer while (clen >= 64) {
410ac341f1SConrad Meyer crypto_core_salsa20(c, in, kcopy, NULL);
420ac341f1SConrad Meyer u = 1;
430ac341f1SConrad Meyer for (i = 8; i < 16; i++) {
440ac341f1SConrad Meyer u += (unsigned int) in[i];
450ac341f1SConrad Meyer in[i] = u;
460ac341f1SConrad Meyer u >>= 8;
470ac341f1SConrad Meyer }
480ac341f1SConrad Meyer clen -= 64;
490ac341f1SConrad Meyer c += 64;
500ac341f1SConrad Meyer }
510ac341f1SConrad Meyer if (clen) {
520ac341f1SConrad Meyer crypto_core_salsa20(block, in, kcopy, NULL);
530ac341f1SConrad Meyer for (i = 0; i < (unsigned int) clen; i++) {
540ac341f1SConrad Meyer c[i] = block[i];
550ac341f1SConrad Meyer }
560ac341f1SConrad Meyer }
570ac341f1SConrad Meyer sodium_memzero(block, sizeof block);
580ac341f1SConrad Meyer sodium_memzero(kcopy, sizeof kcopy);
590ac341f1SConrad Meyer
600ac341f1SConrad Meyer return 0;
610ac341f1SConrad Meyer }
620ac341f1SConrad Meyer
630ac341f1SConrad Meyer 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)640ac341f1SConrad Meyer stream_ref_xor_ic(unsigned char *c, const unsigned char *m,
650ac341f1SConrad Meyer unsigned long long mlen, const unsigned char *n, uint64_t ic,
660ac341f1SConrad Meyer const unsigned char *k)
670ac341f1SConrad Meyer {
680ac341f1SConrad Meyer unsigned char in[16];
690ac341f1SConrad Meyer unsigned char block[64];
700ac341f1SConrad Meyer unsigned char kcopy[32];
710ac341f1SConrad Meyer unsigned int i;
720ac341f1SConrad Meyer unsigned int u;
730ac341f1SConrad Meyer
740ac341f1SConrad Meyer if (!mlen) {
750ac341f1SConrad Meyer return 0;
760ac341f1SConrad Meyer }
770ac341f1SConrad Meyer for (i = 0; i < 32; i++) {
780ac341f1SConrad Meyer kcopy[i] = k[i];
790ac341f1SConrad Meyer }
800ac341f1SConrad Meyer for (i = 0; i < 8; i++) {
810ac341f1SConrad Meyer in[i] = n[i];
820ac341f1SConrad Meyer }
830ac341f1SConrad Meyer for (i = 8; i < 16; i++) {
840ac341f1SConrad Meyer in[i] = (unsigned char) (ic & 0xff);
850ac341f1SConrad Meyer ic >>= 8;
860ac341f1SConrad Meyer }
870ac341f1SConrad Meyer while (mlen >= 64) {
880ac341f1SConrad Meyer crypto_core_salsa20(block, in, kcopy, NULL);
890ac341f1SConrad Meyer for (i = 0; i < 64; i++) {
900ac341f1SConrad Meyer c[i] = m[i] ^ block[i];
910ac341f1SConrad Meyer }
920ac341f1SConrad Meyer u = 1;
930ac341f1SConrad Meyer for (i = 8; i < 16; i++) {
940ac341f1SConrad Meyer u += (unsigned int) in[i];
950ac341f1SConrad Meyer in[i] = u;
960ac341f1SConrad Meyer u >>= 8;
970ac341f1SConrad Meyer }
980ac341f1SConrad Meyer mlen -= 64;
990ac341f1SConrad Meyer c += 64;
1000ac341f1SConrad Meyer m += 64;
1010ac341f1SConrad Meyer }
1020ac341f1SConrad Meyer if (mlen) {
1030ac341f1SConrad Meyer crypto_core_salsa20(block, in, kcopy, NULL);
1040ac341f1SConrad Meyer for (i = 0; i < (unsigned int) mlen; i++) {
1050ac341f1SConrad Meyer c[i] = m[i] ^ block[i];
1060ac341f1SConrad Meyer }
1070ac341f1SConrad Meyer }
1080ac341f1SConrad Meyer sodium_memzero(block, sizeof block);
1090ac341f1SConrad Meyer sodium_memzero(kcopy, sizeof kcopy);
1100ac341f1SConrad Meyer
1110ac341f1SConrad Meyer return 0;
1120ac341f1SConrad Meyer }
1130ac341f1SConrad Meyer
1140ac341f1SConrad Meyer struct crypto_stream_salsa20_implementation
1150ac341f1SConrad Meyer crypto_stream_salsa20_ref_implementation = {
1160ac341f1SConrad Meyer SODIUM_C99(.stream =) stream_ref,
1170ac341f1SConrad Meyer SODIUM_C99(.stream_xor_ic =) stream_ref_xor_ic,
1180ac341f1SConrad Meyer };
1190ac341f1SConrad Meyer
1200ac341f1SConrad Meyer #endif
121