e9b594c1267da3fdebf3eb49ad1dae5e1b30ff1d
[trex.git] /
1
2 #include <assert.h>
3 #include <limits.h>
4 #include <stdint.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8 #include "crypto_core_hsalsa20.h"
9 #include "crypto_onetimeauth_poly1305.h"
10 #include "crypto_secretbox.h"
11 #include "crypto_stream_salsa20.h"
12 #include "utils.h"
13
14 static const unsigned char sigma[16] = {
15     'e', 'x', 'p', 'a', 'n', 'd', ' ', '3', '2', '-', 'b', 'y', 't', 'e', ' ', 'k'
16 };
17
18 int
19 crypto_secretbox_detached(unsigned char *c, unsigned char *mac,
20                           const unsigned char *m,
21                           unsigned long long mlen, const unsigned char *n,
22                           const unsigned char *k)
23 {
24     crypto_onetimeauth_poly1305_state state;
25     unsigned char                     block0[64U];
26     unsigned char                     subkey[crypto_stream_salsa20_KEYBYTES];
27     unsigned long long                i;
28     unsigned long long                mlen0;
29
30     crypto_core_hsalsa20(subkey, n, k, sigma);
31
32     if (((uintptr_t) c >= (uintptr_t) m &&
33          (uintptr_t) c - (uintptr_t) m < mlen) ||
34         ((uintptr_t) m >= (uintptr_t) c &&
35          (uintptr_t) m - (uintptr_t) c < mlen)) {
36         memmove(c, m, mlen);
37         m = c;
38     }
39     memset(block0, 0U, crypto_secretbox_ZEROBYTES);
40     (void) sizeof(int[64U >= crypto_secretbox_ZEROBYTES ? 1 : -1]);
41     mlen0 = mlen;
42     if (mlen0 > 64U - crypto_secretbox_ZEROBYTES) {
43         mlen0 = 64U - crypto_secretbox_ZEROBYTES;
44     }
45     for (i = 0U; i < mlen0; i++) {
46         block0[i + crypto_secretbox_ZEROBYTES] = m[i];
47     }
48     crypto_stream_salsa20_xor(block0, block0,
49                               mlen0 + crypto_secretbox_ZEROBYTES,
50                               n + 16, subkey);
51     (void) sizeof(int[crypto_secretbox_ZEROBYTES >=
52                       crypto_onetimeauth_poly1305_KEYBYTES ? 1 : -1]);
53     crypto_onetimeauth_poly1305_init(&state, block0);
54
55     memcpy(c, block0 + crypto_secretbox_ZEROBYTES, mlen0);
56     sodium_memzero(block0, sizeof block0);
57     if (mlen > mlen0) {
58         crypto_stream_salsa20_xor_ic(c + mlen0, m + mlen0, mlen - mlen0,
59                                      n + 16, 1U, subkey);
60     }
61     sodium_memzero(subkey, sizeof subkey);
62
63     crypto_onetimeauth_poly1305_update(&state, c, mlen);
64     crypto_onetimeauth_poly1305_final(&state, mac);
65     sodium_memzero(&state, sizeof state);
66
67     return 0;
68 }
69
70 int
71 crypto_secretbox_easy(unsigned char *c, const unsigned char *m,
72                       unsigned long long mlen, const unsigned char *n,
73                       const unsigned char *k)
74 {
75     if (mlen > SIZE_MAX - crypto_secretbox_MACBYTES) {
76         return -1;
77     }
78     return crypto_secretbox_detached(c + crypto_secretbox_MACBYTES,
79                                      c, m, mlen, n, k);
80 }
81
82 int
83 crypto_secretbox_open_detached(unsigned char *m, const unsigned char *c,
84                                const unsigned char *mac,
85                                unsigned long long clen,
86                                const unsigned char *n,
87                                const unsigned char *k)
88 {
89     unsigned char      block0[64U];
90     unsigned char      subkey[crypto_stream_salsa20_KEYBYTES];
91     unsigned long long i;
92     unsigned long long mlen0;
93
94     crypto_core_hsalsa20(subkey, n, k, sigma);
95     crypto_stream_salsa20(block0, crypto_stream_salsa20_KEYBYTES,
96                           n + 16, subkey);
97     if (crypto_onetimeauth_poly1305_verify(mac, c, clen, block0) != 0) {
98         sodium_memzero(subkey, sizeof subkey);
99         return -1;
100     }
101     if (((uintptr_t) c >= (uintptr_t) m &&
102          (uintptr_t) c - (uintptr_t) m < clen) ||
103         ((uintptr_t) m >= (uintptr_t) c &&
104          (uintptr_t) m - (uintptr_t) c < clen)) {
105         memmove(m, c, clen);
106         c = m;
107     }
108     mlen0 = clen;
109     if (mlen0 > 64U - crypto_secretbox_ZEROBYTES) {
110         mlen0 = 64U - crypto_secretbox_ZEROBYTES;
111     }
112     memcpy(block0 + crypto_secretbox_ZEROBYTES, c, mlen0);
113     crypto_stream_salsa20_xor(block0, block0,
114                               crypto_secretbox_ZEROBYTES + mlen0,
115                               n + 16, subkey);
116     for (i = 0U; i < mlen0; i++) {
117         m[i] = block0[i + crypto_secretbox_ZEROBYTES];
118     }
119     if (clen > mlen0) {
120         crypto_stream_salsa20_xor_ic(m + mlen0, c + mlen0, clen - mlen0,
121                                      n + 16, 1U, subkey);
122     }
123     sodium_memzero(subkey, sizeof subkey);
124
125     return 0;
126 }
127
128 int
129 crypto_secretbox_open_easy(unsigned char *m, const unsigned char *c,
130                            unsigned long long clen, const unsigned char *n,
131                            const unsigned char *k)
132 {
133     if (clen < crypto_secretbox_MACBYTES) {
134         return -1;
135     }
136     return crypto_secretbox_open_detached(m, c + crypto_secretbox_MACBYTES, c,
137                                           clen - crypto_secretbox_MACBYTES,
138                                           n, k);
139 }