1
2 #include <stdint.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 #include "crypto_stream_salsa20.h"
7 #include "private/common.h"
8 #include "private/sse2_64_32.h"
9 #include "utils.h"
10
11 #ifdef HAVE_EMMINTRIN_H
12
13 # ifdef __GNUC__
14 # pragma GCC target("sse2")
15 # endif
16 # include <emmintrin.h>
17
18 # include "../stream_salsa20.h"
19 # include "salsa20_xmm6int-sse2.h"
20
21 # define ROUNDS 20
22
23 typedef struct salsa_ctx {
24 uint32_t input[16];
25 } salsa_ctx;
26
27 static const int TR[16] = {
28 0, 5, 10, 15, 12, 1, 6, 11, 8, 13, 2, 7, 4, 9, 14, 3
29 };
30
31 static void
salsa_keysetup(salsa_ctx * ctx,const uint8_t * k)32 salsa_keysetup(salsa_ctx *ctx, const uint8_t *k)
33 {
34 ctx->input[TR[1]] = LOAD32_LE(k + 0);
35 ctx->input[TR[2]] = LOAD32_LE(k + 4);
36 ctx->input[TR[3]] = LOAD32_LE(k + 8);
37 ctx->input[TR[4]] = LOAD32_LE(k + 12);
38 ctx->input[TR[11]] = LOAD32_LE(k + 16);
39 ctx->input[TR[12]] = LOAD32_LE(k + 20);
40 ctx->input[TR[13]] = LOAD32_LE(k + 24);
41 ctx->input[TR[14]] = LOAD32_LE(k + 28);
42 ctx->input[TR[0]] = 0x61707865;
43 ctx->input[TR[5]] = 0x3320646e;
44 ctx->input[TR[10]] = 0x79622d32;
45 ctx->input[TR[15]] = 0x6b206574;
46 }
47
48 static void
salsa_ivsetup(salsa_ctx * ctx,const uint8_t * iv,const uint8_t * counter)49 salsa_ivsetup(salsa_ctx *ctx, const uint8_t *iv, const uint8_t *counter)
50 {
51 ctx->input[TR[6]] = LOAD32_LE(iv + 0);
52 ctx->input[TR[7]] = LOAD32_LE(iv + 4);
53 ctx->input[TR[8]] = counter == NULL ? 0 : LOAD32_LE(counter + 0);
54 ctx->input[TR[9]] = counter == NULL ? 0 : LOAD32_LE(counter + 4);
55 }
56
57 static void
salsa20_encrypt_bytes(salsa_ctx * ctx,const uint8_t * m,uint8_t * c,unsigned long long bytes)58 salsa20_encrypt_bytes(salsa_ctx *ctx, const uint8_t *m, uint8_t *c,
59 unsigned long long bytes)
60 {
61 uint32_t * const x = &ctx->input[0];
62
63 if (!bytes) {
64 return; /* LCOV_EXCL_LINE */
65 }
66
67 #include "u4.h"
68 #include "u1.h"
69 #include "u0.h"
70 }
71
72 static int
stream_sse2(unsigned char * c,unsigned long long clen,const unsigned char * n,const unsigned char * k)73 stream_sse2(unsigned char *c, unsigned long long clen, const unsigned char *n,
74 const unsigned char *k)
75 {
76 struct salsa_ctx ctx;
77
78 if (!clen) {
79 return 0;
80 }
81 COMPILER_ASSERT(crypto_stream_salsa20_KEYBYTES == 256 / 8);
82 salsa_keysetup(&ctx, k);
83 salsa_ivsetup(&ctx, n, NULL);
84 memset(c, 0, clen);
85 salsa20_encrypt_bytes(&ctx, c, c, clen);
86 sodium_memzero(&ctx, sizeof ctx);
87
88 return 0;
89 }
90
91 static int
stream_sse2_xor_ic(unsigned char * c,const unsigned char * m,unsigned long long mlen,const unsigned char * n,uint64_t ic,const unsigned char * k)92 stream_sse2_xor_ic(unsigned char *c, const unsigned char *m,
93 unsigned long long mlen, const unsigned char *n, uint64_t ic,
94 const unsigned char *k)
95 {
96 struct salsa_ctx ctx;
97 uint8_t ic_bytes[8];
98 uint32_t ic_high;
99 uint32_t ic_low;
100
101 if (!mlen) {
102 return 0;
103 }
104 ic_high = (uint32_t) (ic >> 32);
105 ic_low = (uint32_t) (ic);
106 STORE32_LE(&ic_bytes[0], ic_low);
107 STORE32_LE(&ic_bytes[4], ic_high);
108 salsa_keysetup(&ctx, k);
109 salsa_ivsetup(&ctx, n, ic_bytes);
110 salsa20_encrypt_bytes(&ctx, m, c, mlen);
111 sodium_memzero(&ctx, sizeof ctx);
112
113 return 0;
114 }
115
116 struct crypto_stream_salsa20_implementation
117 crypto_stream_salsa20_xmm6int_sse2_implementation = {
118 SODIUM_C99(.stream =) stream_sse2,
119 SODIUM_C99(.stream_xor_ic =) stream_sse2_xor_ic
120 };
121
122 #endif
123