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
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
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
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
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
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