945efe3324fc9de17c7dbedb0a68c9d643dbeb6d
[trex.git] /
1
2 #include <limits.h>
3 #include <string.h>
4
5 #include "crypto_aead_chacha20poly1305.h"
6 #include "crypto_onetimeauth_poly1305.h"
7 #include "crypto_stream_chacha20.h"
8 #include "crypto_verify_16.h"
9 #include "utils.h"
10
11 static inline void
12 _u64_le_from_ull(unsigned char out[8U], unsigned long long x)
13 {
14     out[0] = (unsigned char) (x & 0xff); x >>= 8;
15     out[1] = (unsigned char) (x & 0xff); x >>= 8;
16     out[2] = (unsigned char) (x & 0xff); x >>= 8;
17     out[3] = (unsigned char) (x & 0xff); x >>= 8;
18     out[4] = (unsigned char) (x & 0xff); x >>= 8;
19     out[5] = (unsigned char) (x & 0xff); x >>= 8;
20     out[6] = (unsigned char) (x & 0xff); x >>= 8;
21     out[7] = (unsigned char) (x & 0xff);
22 }
23
24 int
25 crypto_aead_chacha20poly1305_encrypt(unsigned char *c,
26                                      unsigned long long *clen,
27                                      const unsigned char *m,
28                                      unsigned long long mlen,
29                                      const unsigned char *ad,
30                                      unsigned long long adlen,
31                                      const unsigned char *nsec,
32                                      const unsigned char *npub,
33                                      const unsigned char *k)
34 {
35     crypto_onetimeauth_poly1305_state state;
36     unsigned char                     block0[64U];
37     unsigned char                     slen[8U];
38
39     (void) nsec;
40 /* LCOV_EXCL_START */
41 #ifdef ULONG_LONG_MAX
42     if (mlen > ULONG_LONG_MAX - crypto_aead_chacha20poly1305_ABYTES) {
43         if (clen != NULL) {
44             *clen = 0ULL;
45         }
46         return -1;
47     }
48 #endif
49 /* LCOV_EXCL_STOP */
50
51     crypto_stream_chacha20(block0, sizeof block0, npub, k);
52     crypto_onetimeauth_poly1305_init(&state, block0);
53     sodium_memzero(block0, sizeof block0);
54
55     crypto_onetimeauth_poly1305_update(&state, ad, adlen);
56     _u64_le_from_ull(slen, adlen);
57     crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
58
59     crypto_stream_chacha20_xor_ic(c, m, mlen, npub, 1U, k);
60
61     crypto_onetimeauth_poly1305_update(&state, c, mlen);
62     _u64_le_from_ull(slen, mlen);
63     crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
64
65     crypto_onetimeauth_poly1305_final(&state, c + mlen);
66     sodium_memzero(&state, sizeof state);
67
68     if (clen != NULL) {
69         *clen = mlen + crypto_aead_chacha20poly1305_ABYTES;
70     }
71     return 0;
72 }
73
74 int
75 crypto_aead_chacha20poly1305_decrypt(unsigned char *m,
76                                      unsigned long long *mlen,
77                                      unsigned char *nsec,
78                                      const unsigned char *c,
79                                      unsigned long long clen,
80                                      const unsigned char *ad,
81                                      unsigned long long adlen,
82                                      const unsigned char *npub,
83                                      const unsigned char *k)
84 {
85     crypto_onetimeauth_poly1305_state state;
86     unsigned char                     block0[64U];
87     unsigned char                     slen[8U];
88     unsigned char                     mac[crypto_aead_chacha20poly1305_ABYTES];
89     int                               ret;
90
91     (void) nsec;
92     if (mlen != NULL) {
93         *mlen = 0ULL;
94     }
95     if (clen < crypto_aead_chacha20poly1305_ABYTES) {
96         return -1;
97     }
98     crypto_stream_chacha20(block0, sizeof block0, npub, k);
99     crypto_onetimeauth_poly1305_init(&state, block0);
100     sodium_memzero(block0, sizeof block0);
101
102     crypto_onetimeauth_poly1305_update(&state, ad, adlen);
103     _u64_le_from_ull(slen, adlen);
104     crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
105
106     crypto_onetimeauth_poly1305_update
107         (&state, c, clen - crypto_aead_chacha20poly1305_ABYTES);
108     _u64_le_from_ull(slen, clen - crypto_aead_chacha20poly1305_ABYTES);
109     crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
110
111     crypto_onetimeauth_poly1305_final(&state, mac);
112     sodium_memzero(&state, sizeof state);
113
114     (void) sizeof(int[sizeof mac == 16U ? 1 : -1]);
115     ret = crypto_verify_16(mac,
116                            c + clen - crypto_aead_chacha20poly1305_ABYTES);
117     sodium_memzero(mac, sizeof mac);
118     if (ret != 0) {
119         memset(m, 0, clen - crypto_aead_chacha20poly1305_ABYTES);
120         return -1;
121     }
122     crypto_stream_chacha20_xor_ic
123         (m, c,  clen - crypto_aead_chacha20poly1305_ABYTES, npub, 1U, k);
124     if (mlen != NULL) {
125         *mlen = clen - crypto_aead_chacha20poly1305_ABYTES;
126     }
127     return 0;
128 }
129
130 size_t
131 crypto_aead_chacha20poly1305_keybytes(void) {
132     return crypto_aead_chacha20poly1305_KEYBYTES;
133 }
134
135 size_t
136 crypto_aead_chacha20poly1305_npubbytes(void) {
137     return crypto_aead_chacha20poly1305_NPUBBYTES;
138 }
139
140 size_t
141 crypto_aead_chacha20poly1305_nsecbytes(void) {
142     return crypto_aead_chacha20poly1305_NSECBYTES;
143 }
144
145 size_t
146 crypto_aead_chacha20poly1305_abytes(void) {
147     return crypto_aead_chacha20poly1305_ABYTES;
148 }