1 
2 #include <stdint.h>
3 #include <stdlib.h>
4 #include <limits.h>
5 #include <string.h>
6 
7 #include "core.h"
8 #include "crypto_aead_xchacha20poly1305.h"
9 #include "crypto_aead_chacha20poly1305.h"
10 #include "crypto_core_hchacha20.h"
11 #include "randombytes.h"
12 #include "utils.h"
13 
14 #include "private/common.h"
15 
16 int
crypto_aead_xchacha20poly1305_ietf_encrypt_detached(unsigned char * c,unsigned char * mac,unsigned long long * maclen_p,const unsigned char * m,unsigned long long mlen,const unsigned char * ad,unsigned long long adlen,const unsigned char * nsec,const unsigned char * npub,const unsigned char * k)17 crypto_aead_xchacha20poly1305_ietf_encrypt_detached(unsigned char *c,
18                                                     unsigned char *mac,
19                                                     unsigned long long *maclen_p,
20                                                     const unsigned char *m,
21                                                     unsigned long long mlen,
22                                                     const unsigned char *ad,
23                                                     unsigned long long adlen,
24                                                     const unsigned char *nsec,
25                                                     const unsigned char *npub,
26                                                     const unsigned char *k)
27 {
28     unsigned char k2[crypto_core_hchacha20_OUTPUTBYTES];
29     unsigned char npub2[crypto_aead_chacha20poly1305_ietf_NPUBBYTES] = { 0 };
30     int           ret;
31 
32     crypto_core_hchacha20(k2, npub, k, NULL);
33     memcpy(npub2 + 4, npub + crypto_core_hchacha20_INPUTBYTES,
34            crypto_aead_chacha20poly1305_ietf_NPUBBYTES - 4);
35     ret = crypto_aead_chacha20poly1305_ietf_encrypt_detached
36         (c, mac, maclen_p, m, mlen, ad, adlen, nsec, npub2, k2);
37     sodium_memzero(k2, crypto_core_hchacha20_OUTPUTBYTES);
38 
39     return ret;
40 }
41 
42 int
crypto_aead_xchacha20poly1305_ietf_encrypt(unsigned char * c,unsigned long long * clen_p,const unsigned char * m,unsigned long long mlen,const unsigned char * ad,unsigned long long adlen,const unsigned char * nsec,const unsigned char * npub,const unsigned char * k)43 crypto_aead_xchacha20poly1305_ietf_encrypt(unsigned char *c,
44                                            unsigned long long *clen_p,
45                                            const unsigned char *m,
46                                            unsigned long long mlen,
47                                            const unsigned char *ad,
48                                            unsigned long long adlen,
49                                            const unsigned char *nsec,
50                                            const unsigned char *npub,
51                                            const unsigned char *k)
52 {
53     unsigned long long clen = 0ULL;
54     int                ret;
55 
56     if (mlen > crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX) {
57         sodium_misuse();
58     }
59     ret = crypto_aead_xchacha20poly1305_ietf_encrypt_detached
60         (c, c + mlen, NULL, m, mlen, ad, adlen, nsec, npub, k);
61     if (clen_p != NULL) {
62         if (ret == 0) {
63             clen = mlen + crypto_aead_xchacha20poly1305_ietf_ABYTES;
64         }
65         *clen_p = clen;
66     }
67     return ret;
68 }
69 
70 int
crypto_aead_xchacha20poly1305_ietf_decrypt_detached(unsigned char * m,unsigned char * nsec,const unsigned char * c,unsigned long long clen,const unsigned char * mac,const unsigned char * ad,unsigned long long adlen,const unsigned char * npub,const unsigned char * k)71 crypto_aead_xchacha20poly1305_ietf_decrypt_detached(unsigned char *m,
72                                                     unsigned char *nsec,
73                                                     const unsigned char *c,
74                                                     unsigned long long clen,
75                                                     const unsigned char *mac,
76                                                     const unsigned char *ad,
77                                                     unsigned long long adlen,
78                                                     const unsigned char *npub,
79                                                     const unsigned char *k)
80 {
81     unsigned char k2[crypto_core_hchacha20_OUTPUTBYTES];
82     unsigned char npub2[crypto_aead_chacha20poly1305_ietf_NPUBBYTES] = { 0 };
83     int           ret;
84 
85     crypto_core_hchacha20(k2, npub, k, NULL);
86     memcpy(npub2 + 4, npub + crypto_core_hchacha20_INPUTBYTES,
87            crypto_aead_chacha20poly1305_ietf_NPUBBYTES - 4);
88     ret = crypto_aead_chacha20poly1305_ietf_decrypt_detached
89         (m, nsec, c, clen, mac, ad, adlen, npub2, k2);
90     sodium_memzero(k2, crypto_core_hchacha20_OUTPUTBYTES);
91 
92     return ret;
93 
94 }
95 
96 int
crypto_aead_xchacha20poly1305_ietf_decrypt(unsigned char * m,unsigned long long * mlen_p,unsigned char * nsec,const unsigned char * c,unsigned long long clen,const unsigned char * ad,unsigned long long adlen,const unsigned char * npub,const unsigned char * k)97 crypto_aead_xchacha20poly1305_ietf_decrypt(unsigned char *m,
98                                            unsigned long long *mlen_p,
99                                            unsigned char *nsec,
100                                            const unsigned char *c,
101                                            unsigned long long clen,
102                                            const unsigned char *ad,
103                                            unsigned long long adlen,
104                                            const unsigned char *npub,
105                                            const unsigned char *k)
106 {
107     unsigned long long mlen = 0ULL;
108     int                ret = -1;
109 
110     if (clen >= crypto_aead_xchacha20poly1305_ietf_ABYTES) {
111         ret = crypto_aead_xchacha20poly1305_ietf_decrypt_detached
112             (m, nsec,
113              c, clen - crypto_aead_xchacha20poly1305_ietf_ABYTES,
114              c + clen - crypto_aead_xchacha20poly1305_ietf_ABYTES,
115              ad, adlen, npub, k);
116     }
117     if (mlen_p != NULL) {
118         if (ret == 0) {
119             mlen = clen - crypto_aead_xchacha20poly1305_ietf_ABYTES;
120         }
121         *mlen_p = mlen;
122     }
123     return ret;
124 }
125 
126 size_t
crypto_aead_xchacha20poly1305_ietf_keybytes(void)127 crypto_aead_xchacha20poly1305_ietf_keybytes(void)
128 {
129     return crypto_aead_xchacha20poly1305_ietf_KEYBYTES;
130 }
131 
132 size_t
crypto_aead_xchacha20poly1305_ietf_npubbytes(void)133 crypto_aead_xchacha20poly1305_ietf_npubbytes(void)
134 {
135     return crypto_aead_xchacha20poly1305_ietf_NPUBBYTES;
136 }
137 
138 size_t
crypto_aead_xchacha20poly1305_ietf_nsecbytes(void)139 crypto_aead_xchacha20poly1305_ietf_nsecbytes(void)
140 {
141     return crypto_aead_xchacha20poly1305_ietf_NSECBYTES;
142 }
143 
144 size_t
crypto_aead_xchacha20poly1305_ietf_abytes(void)145 crypto_aead_xchacha20poly1305_ietf_abytes(void)
146 {
147     return crypto_aead_xchacha20poly1305_ietf_ABYTES;
148 }
149 
150 size_t
crypto_aead_xchacha20poly1305_ietf_messagebytes_max(void)151 crypto_aead_xchacha20poly1305_ietf_messagebytes_max(void)
152 {
153     return crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX;
154 }
155 
156 void
crypto_aead_xchacha20poly1305_ietf_keygen(unsigned char k[crypto_aead_xchacha20poly1305_ietf_KEYBYTES])157 crypto_aead_xchacha20poly1305_ietf_keygen(unsigned char k[crypto_aead_xchacha20poly1305_ietf_KEYBYTES])
158 {
159     randombytes_buf(k, crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
160 }
161