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_chacha20poly1305.h" 9 #include "crypto_onetimeauth_poly1305.h" 10 #include "crypto_stream_chacha20.h" 11 #include "crypto_verify_16.h" 12 #include "randombytes.h" 13 #include "utils.h" 14 15 #include "private/common.h" 16 17 static const unsigned char _pad0[16] = { 0 }; 18 19 int 20 crypto_aead_chacha20poly1305_encrypt_detached(unsigned char *c, 21 unsigned char *mac, 22 unsigned long long *maclen_p, 23 const unsigned char *m, 24 unsigned long long mlen, 25 const unsigned char *ad, 26 unsigned long long adlen, 27 const unsigned char *nsec, 28 const unsigned char *npub, 29 const unsigned char *k) 30 { 31 crypto_onetimeauth_poly1305_state state; 32 unsigned char block0[64U]; 33 unsigned char slen[8U]; 34 35 (void) nsec; 36 crypto_stream_chacha20(block0, sizeof block0, npub, k); 37 crypto_onetimeauth_poly1305_init(&state, block0); 38 sodium_memzero(block0, sizeof block0); 39 40 crypto_onetimeauth_poly1305_update(&state, ad, adlen); 41 STORE64_LE(slen, (uint64_t) adlen); 42 crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen); 43 44 crypto_stream_chacha20_xor_ic(c, m, mlen, npub, 1U, k); 45 46 crypto_onetimeauth_poly1305_update(&state, c, mlen); 47 STORE64_LE(slen, (uint64_t) mlen); 48 crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen); 49 50 crypto_onetimeauth_poly1305_final(&state, mac); 51 sodium_memzero(&state, sizeof state); 52 53 if (maclen_p != NULL) { 54 *maclen_p = crypto_aead_chacha20poly1305_ABYTES; 55 } 56 return 0; 57 } 58 59 int 60 crypto_aead_chacha20poly1305_encrypt(unsigned char *c, 61 unsigned long long *clen_p, 62 const unsigned char *m, 63 unsigned long long mlen, 64 const unsigned char *ad, 65 unsigned long long adlen, 66 const unsigned char *nsec, 67 const unsigned char *npub, 68 const unsigned char *k) 69 { 70 unsigned long long clen = 0ULL; 71 int ret; 72 73 if (mlen > crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX) { 74 sodium_misuse(); 75 } 76 ret = crypto_aead_chacha20poly1305_encrypt_detached(c, 77 c + mlen, NULL, 78 m, mlen, 79 ad, adlen, 80 nsec, npub, k); 81 if (clen_p != NULL) { 82 if (ret == 0) { 83 clen = mlen + crypto_aead_chacha20poly1305_ABYTES; 84 } 85 *clen_p = clen; 86 } 87 return ret; 88 } 89 90 int 91 crypto_aead_chacha20poly1305_ietf_encrypt_detached(unsigned char *c, 92 unsigned char *mac, 93 unsigned long long *maclen_p, 94 const unsigned char *m, 95 unsigned long long mlen, 96 const unsigned char *ad, 97 unsigned long long adlen, 98 const unsigned char *nsec, 99 const unsigned char *npub, 100 const unsigned char *k) 101 { 102 crypto_onetimeauth_poly1305_state state; 103 unsigned char block0[64U]; 104 unsigned char slen[8U]; 105 106 (void) nsec; 107 crypto_stream_chacha20_ietf(block0, sizeof block0, npub, k); 108 crypto_onetimeauth_poly1305_init(&state, block0); 109 sodium_memzero(block0, sizeof block0); 110 111 crypto_onetimeauth_poly1305_update(&state, ad, adlen); 112 crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - adlen) & 0xf); 113 114 crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, npub, 1U, k); 115 116 crypto_onetimeauth_poly1305_update(&state, c, mlen); 117 crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - mlen) & 0xf); 118 119 STORE64_LE(slen, (uint64_t) adlen); 120 crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen); 121 122 STORE64_LE(slen, (uint64_t) mlen); 123 crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen); 124 125 crypto_onetimeauth_poly1305_final(&state, mac); 126 sodium_memzero(&state, sizeof state); 127 128 if (maclen_p != NULL) { 129 *maclen_p = crypto_aead_chacha20poly1305_ietf_ABYTES; 130 } 131 return 0; 132 } 133 134 int 135 crypto_aead_chacha20poly1305_ietf_encrypt(unsigned char *c, 136 unsigned long long *clen_p, 137 const unsigned char *m, 138 unsigned long long mlen, 139 const unsigned char *ad, 140 unsigned long long adlen, 141 const unsigned char *nsec, 142 const unsigned char *npub, 143 const unsigned char *k) 144 { 145 unsigned long long clen = 0ULL; 146 int ret; 147 148 if (mlen > crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX) { 149 sodium_misuse(); 150 } 151 ret = crypto_aead_chacha20poly1305_ietf_encrypt_detached(c, 152 c + mlen, NULL, 153 m, mlen, 154 ad, adlen, 155 nsec, npub, k); 156 if (clen_p != NULL) { 157 if (ret == 0) { 158 clen = mlen + crypto_aead_chacha20poly1305_ietf_ABYTES; 159 } 160 *clen_p = clen; 161 } 162 return ret; 163 } 164 165 int 166 crypto_aead_chacha20poly1305_decrypt_detached(unsigned char *m, 167 unsigned char *nsec, 168 const unsigned char *c, 169 unsigned long long clen, 170 const unsigned char *mac, 171 const unsigned char *ad, 172 unsigned long long adlen, 173 const unsigned char *npub, 174 const unsigned char *k) 175 { 176 crypto_onetimeauth_poly1305_state state; 177 unsigned char block0[64U]; 178 unsigned char slen[8U]; 179 unsigned char computed_mac[crypto_aead_chacha20poly1305_ABYTES]; 180 unsigned long long mlen; 181 int ret; 182 183 (void) nsec; 184 crypto_stream_chacha20(block0, sizeof block0, npub, k); 185 crypto_onetimeauth_poly1305_init(&state, block0); 186 sodium_memzero(block0, sizeof block0); 187 188 crypto_onetimeauth_poly1305_update(&state, ad, adlen); 189 STORE64_LE(slen, (uint64_t) adlen); 190 crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen); 191 192 mlen = clen; 193 crypto_onetimeauth_poly1305_update(&state, c, mlen); 194 STORE64_LE(slen, (uint64_t) mlen); 195 crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen); 196 197 crypto_onetimeauth_poly1305_final(&state, computed_mac); 198 sodium_memzero(&state, sizeof state); 199 200 COMPILER_ASSERT(sizeof computed_mac == 16U); 201 ret = crypto_verify_16(computed_mac, mac); 202 sodium_memzero(computed_mac, sizeof computed_mac); 203 if (m == NULL) { 204 return ret; 205 } 206 if (ret != 0) { 207 memset(m, 0, mlen); 208 return -1; 209 } 210 crypto_stream_chacha20_xor_ic(m, c, mlen, npub, 1U, k); 211 212 return 0; 213 } 214 215 int 216 crypto_aead_chacha20poly1305_decrypt(unsigned char *m, 217 unsigned long long *mlen_p, 218 unsigned char *nsec, 219 const unsigned char *c, 220 unsigned long long clen, 221 const unsigned char *ad, 222 unsigned long long adlen, 223 const unsigned char *npub, 224 const unsigned char *k) 225 { 226 unsigned long long mlen = 0ULL; 227 int ret = -1; 228 229 if (clen >= crypto_aead_chacha20poly1305_ABYTES) { 230 ret = crypto_aead_chacha20poly1305_decrypt_detached 231 (m, nsec, 232 c, clen - crypto_aead_chacha20poly1305_ABYTES, 233 c + clen - crypto_aead_chacha20poly1305_ABYTES, 234 ad, adlen, npub, k); 235 } 236 if (mlen_p != NULL) { 237 if (ret == 0) { 238 mlen = clen - crypto_aead_chacha20poly1305_ABYTES; 239 } 240 *mlen_p = mlen; 241 } 242 return ret; 243 } 244 245 int 246 crypto_aead_chacha20poly1305_ietf_decrypt_detached(unsigned char *m, 247 unsigned char *nsec, 248 const unsigned char *c, 249 unsigned long long clen, 250 const unsigned char *mac, 251 const unsigned char *ad, 252 unsigned long long adlen, 253 const unsigned char *npub, 254 const unsigned char *k) 255 { 256 crypto_onetimeauth_poly1305_state state; 257 unsigned char block0[64U]; 258 unsigned char slen[8U]; 259 unsigned char computed_mac[crypto_aead_chacha20poly1305_ietf_ABYTES]; 260 unsigned long long mlen; 261 int ret; 262 263 (void) nsec; 264 crypto_stream_chacha20_ietf(block0, sizeof block0, npub, k); 265 crypto_onetimeauth_poly1305_init(&state, block0); 266 sodium_memzero(block0, sizeof block0); 267 268 crypto_onetimeauth_poly1305_update(&state, ad, adlen); 269 crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - adlen) & 0xf); 270 271 mlen = clen; 272 crypto_onetimeauth_poly1305_update(&state, c, mlen); 273 crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - mlen) & 0xf); 274 275 STORE64_LE(slen, (uint64_t) adlen); 276 crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen); 277 278 STORE64_LE(slen, (uint64_t) mlen); 279 crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen); 280 281 crypto_onetimeauth_poly1305_final(&state, computed_mac); 282 sodium_memzero(&state, sizeof state); 283 284 COMPILER_ASSERT(sizeof computed_mac == 16U); 285 ret = crypto_verify_16(computed_mac, mac); 286 sodium_memzero(computed_mac, sizeof computed_mac); 287 if (m == NULL) { 288 return ret; 289 } 290 if (ret != 0) { 291 memset(m, 0, mlen); 292 return -1; 293 } 294 crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, npub, 1U, k); 295 296 return 0; 297 } 298 299 int 300 crypto_aead_chacha20poly1305_ietf_decrypt(unsigned char *m, 301 unsigned long long *mlen_p, 302 unsigned char *nsec, 303 const unsigned char *c, 304 unsigned long long clen, 305 const unsigned char *ad, 306 unsigned long long adlen, 307 const unsigned char *npub, 308 const unsigned char *k) 309 { 310 unsigned long long mlen = 0ULL; 311 int ret = -1; 312 313 if (clen >= crypto_aead_chacha20poly1305_ietf_ABYTES) { 314 ret = crypto_aead_chacha20poly1305_ietf_decrypt_detached 315 (m, nsec, 316 c, clen - crypto_aead_chacha20poly1305_ietf_ABYTES, 317 c + clen - crypto_aead_chacha20poly1305_ietf_ABYTES, 318 ad, adlen, npub, k); 319 } 320 if (mlen_p != NULL) { 321 if (ret == 0) { 322 mlen = clen - crypto_aead_chacha20poly1305_ietf_ABYTES; 323 } 324 *mlen_p = mlen; 325 } 326 return ret; 327 } 328 329 size_t 330 crypto_aead_chacha20poly1305_ietf_keybytes(void) 331 { 332 return crypto_aead_chacha20poly1305_ietf_KEYBYTES; 333 } 334 335 size_t 336 crypto_aead_chacha20poly1305_ietf_npubbytes(void) 337 { 338 return crypto_aead_chacha20poly1305_ietf_NPUBBYTES; 339 } 340 341 size_t 342 crypto_aead_chacha20poly1305_ietf_nsecbytes(void) 343 { 344 return crypto_aead_chacha20poly1305_ietf_NSECBYTES; 345 } 346 347 size_t 348 crypto_aead_chacha20poly1305_ietf_abytes(void) 349 { 350 return crypto_aead_chacha20poly1305_ietf_ABYTES; 351 } 352 353 size_t 354 crypto_aead_chacha20poly1305_ietf_messagebytes_max(void) 355 { 356 return crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX; 357 } 358 359 void 360 crypto_aead_chacha20poly1305_ietf_keygen(unsigned char k[crypto_aead_chacha20poly1305_ietf_KEYBYTES]) 361 { 362 randombytes_buf(k, crypto_aead_chacha20poly1305_ietf_KEYBYTES); 363 } 364 365 size_t 366 crypto_aead_chacha20poly1305_keybytes(void) 367 { 368 return crypto_aead_chacha20poly1305_KEYBYTES; 369 } 370 371 size_t 372 crypto_aead_chacha20poly1305_npubbytes(void) 373 { 374 return crypto_aead_chacha20poly1305_NPUBBYTES; 375 } 376 377 size_t 378 crypto_aead_chacha20poly1305_nsecbytes(void) 379 { 380 return crypto_aead_chacha20poly1305_NSECBYTES; 381 } 382 383 size_t 384 crypto_aead_chacha20poly1305_abytes(void) 385 { 386 return crypto_aead_chacha20poly1305_ABYTES; 387 } 388 389 size_t 390 crypto_aead_chacha20poly1305_messagebytes_max(void) 391 { 392 return crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX; 393 } 394 395 void 396 crypto_aead_chacha20poly1305_keygen(unsigned char k[crypto_aead_chacha20poly1305_KEYBYTES]) 397 { 398 randombytes_buf(k, crypto_aead_chacha20poly1305_KEYBYTES); 399 } 400