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_salsa2012.h"
100ac341f1SConrad Meyer #include "crypto_stream_salsa2012.h"
110ac341f1SConrad Meyer #include "utils.h"
120ac341f1SConrad Meyer 
130ac341f1SConrad Meyer int
crypto_stream_salsa2012(unsigned char * c,unsigned long long clen,const unsigned char * n,const unsigned char * k)140ac341f1SConrad Meyer crypto_stream_salsa2012(unsigned char *c, unsigned long long clen,
150ac341f1SConrad Meyer                         const unsigned char *n, const unsigned char *k)
160ac341f1SConrad Meyer {
170ac341f1SConrad Meyer     unsigned char in[16];
180ac341f1SConrad Meyer     unsigned char block[64];
190ac341f1SConrad Meyer     unsigned char kcopy[32];
200ac341f1SConrad Meyer     unsigned int  i;
210ac341f1SConrad Meyer     unsigned int  u;
220ac341f1SConrad Meyer 
230ac341f1SConrad Meyer     if (!clen) {
240ac341f1SConrad Meyer         return 0;
250ac341f1SConrad Meyer     }
260ac341f1SConrad Meyer     for (i = 0; i < 32; ++i) {
270ac341f1SConrad Meyer         kcopy[i] = k[i];
280ac341f1SConrad Meyer     }
290ac341f1SConrad Meyer     for (i = 0; i < 8; ++i) {
300ac341f1SConrad Meyer         in[i] = n[i];
310ac341f1SConrad Meyer     }
320ac341f1SConrad Meyer     for (i = 8; i < 16; ++i) {
330ac341f1SConrad Meyer         in[i] = 0;
340ac341f1SConrad Meyer     }
350ac341f1SConrad Meyer     while (clen >= 64) {
360ac341f1SConrad Meyer         crypto_core_salsa2012(c, in, kcopy, NULL);
370ac341f1SConrad Meyer         u = 1;
380ac341f1SConrad Meyer         for (i = 8; i < 16; ++i) {
390ac341f1SConrad Meyer             u += (unsigned int)in[i];
400ac341f1SConrad Meyer             in[i] = u;
410ac341f1SConrad Meyer             u >>= 8;
420ac341f1SConrad Meyer         }
430ac341f1SConrad Meyer         clen -= 64;
440ac341f1SConrad Meyer         c += 64;
450ac341f1SConrad Meyer     }
460ac341f1SConrad Meyer     if (clen) {
470ac341f1SConrad Meyer         crypto_core_salsa2012(block, in, kcopy, NULL);
480ac341f1SConrad Meyer         for (i = 0; i < (unsigned int)clen; ++i) {
490ac341f1SConrad Meyer             c[i] = block[i];
500ac341f1SConrad Meyer         }
510ac341f1SConrad Meyer     }
520ac341f1SConrad Meyer     sodium_memzero(block, sizeof block);
530ac341f1SConrad Meyer     sodium_memzero(kcopy, sizeof kcopy);
540ac341f1SConrad Meyer 
550ac341f1SConrad Meyer     return 0;
560ac341f1SConrad Meyer }
570ac341f1SConrad Meyer 
580ac341f1SConrad Meyer int
crypto_stream_salsa2012_xor(unsigned char * c,const unsigned char * m,unsigned long long mlen,const unsigned char * n,const unsigned char * k)590ac341f1SConrad Meyer crypto_stream_salsa2012_xor(unsigned char *c, const unsigned char *m,
600ac341f1SConrad Meyer                             unsigned long long mlen, const unsigned char *n,
610ac341f1SConrad Meyer                             const unsigned char *k)
620ac341f1SConrad Meyer {
630ac341f1SConrad Meyer     unsigned char in[16];
640ac341f1SConrad Meyer     unsigned char block[64];
650ac341f1SConrad Meyer     unsigned char kcopy[32];
660ac341f1SConrad Meyer     unsigned int  i;
670ac341f1SConrad Meyer     unsigned int  u;
680ac341f1SConrad Meyer 
690ac341f1SConrad Meyer     if (!mlen) {
700ac341f1SConrad Meyer         return 0;
710ac341f1SConrad Meyer     }
720ac341f1SConrad Meyer     for (i = 0; i < 32; ++i) {
730ac341f1SConrad Meyer         kcopy[i] = k[i];
740ac341f1SConrad Meyer     }
750ac341f1SConrad Meyer     for (i = 0; i < 8; ++i) {
760ac341f1SConrad Meyer         in[i] = n[i];
770ac341f1SConrad Meyer     }
780ac341f1SConrad Meyer     for (i = 8; i < 16; ++i) {
790ac341f1SConrad Meyer         in[i] = 0;
800ac341f1SConrad Meyer     }
810ac341f1SConrad Meyer     while (mlen >= 64) {
820ac341f1SConrad Meyer         crypto_core_salsa2012(block, in, kcopy, NULL);
830ac341f1SConrad Meyer         for (i = 0; i < 64; ++i) {
840ac341f1SConrad Meyer             c[i] = m[i] ^ block[i];
850ac341f1SConrad Meyer         }
860ac341f1SConrad Meyer         u = 1;
870ac341f1SConrad Meyer         for (i = 8; i < 16; ++i) {
880ac341f1SConrad Meyer             u += (unsigned int)in[i];
890ac341f1SConrad Meyer             in[i] = u;
900ac341f1SConrad Meyer             u >>= 8;
910ac341f1SConrad Meyer         }
920ac341f1SConrad Meyer         mlen -= 64;
930ac341f1SConrad Meyer         c += 64;
940ac341f1SConrad Meyer         m += 64;
950ac341f1SConrad Meyer     }
960ac341f1SConrad Meyer     if (mlen) {
970ac341f1SConrad Meyer         crypto_core_salsa2012(block, in, kcopy, NULL);
980ac341f1SConrad Meyer         for (i = 0; i < (unsigned int)mlen; ++i) {
990ac341f1SConrad Meyer             c[i] = m[i] ^ block[i];
1000ac341f1SConrad Meyer         }
1010ac341f1SConrad Meyer     }
1020ac341f1SConrad Meyer     sodium_memzero(block, sizeof block);
1030ac341f1SConrad Meyer     sodium_memzero(kcopy, sizeof kcopy);
1040ac341f1SConrad Meyer 
1050ac341f1SConrad Meyer     return 0;
1060ac341f1SConrad Meyer }
107