chacha20poly1305.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. // Implementations of the XChaCha20 + Poly1305 and ChaCha20 + Poly1305
  2. // AEAD constructions with a goal of simplicity and correctness rather
  3. // than performance.
  4. #include "chacha20poly1305.h"
  5. #include "ecrypt-portable.h"
  6. void hchacha20(ECRYPT_ctx *x,u8 *c);
  7. // Initialize the XChaCha20 + Poly1305 context for encryption or decryption
  8. // using a 32 byte key and 24 byte nonce. The key and the first 16 bytes of
  9. // the nonce are used as input to HChaCha20 to derive the Chacha20 key.
  10. void xchacha20poly1305_init(chacha20poly1305_ctx *ctx, const uint8_t key[32], const uint8_t nonce[24]) {
  11. unsigned char subkey[32] = {0};
  12. unsigned char block0[64] = {0};
  13. ECRYPT_ctx tmp = {0};
  14. // Generate the Chacha20 key by applying HChaCha20 to the
  15. // original key and the first 16 bytes of the nonce.
  16. ECRYPT_keysetup(&tmp, key, 256, 16);
  17. tmp.input[12] = U8TO32_LITTLE(nonce + 0);
  18. tmp.input[13] = U8TO32_LITTLE(nonce + 4);
  19. tmp.input[14] = U8TO32_LITTLE(nonce + 8);
  20. tmp.input[15] = U8TO32_LITTLE(nonce + 12);
  21. hchacha20(&tmp, subkey);
  22. // Initialize Chacha20 with the newly generated key and
  23. // the last 8 bytes of the nonce.
  24. ECRYPT_keysetup(&ctx->chacha20, subkey, 256, 16);
  25. ECRYPT_ivsetup(&ctx->chacha20, nonce+16);
  26. // Encrypt 64 bytes of zeros and use the first 32 bytes
  27. // as the Poly1305 key.
  28. ECRYPT_encrypt_bytes(&ctx->chacha20, block0, block0, 64);
  29. poly1305_init(&ctx->poly1305, block0);
  30. }
  31. // Encrypt n bytes of plaintext where n must be evenly divisible by the
  32. // Chacha20 blocksize of 64, except for the final n bytes of plaintext.
  33. void chacha20poly1305_encrypt(chacha20poly1305_ctx *ctx, const uint8_t *in, uint8_t *out, size_t n) {
  34. ECRYPT_encrypt_bytes(&ctx->chacha20, in, out, n);
  35. poly1305_update(&ctx->poly1305, out, n);
  36. }
  37. // Decrypt n bytes of ciphertext where n must be evenly divisible by the
  38. // Chacha20 blocksize of 64, except for the final n bytes of ciphertext.
  39. void chacha20poly1305_decrypt(chacha20poly1305_ctx *ctx, const uint8_t *in, uint8_t *out, size_t n) {
  40. poly1305_update(&ctx->poly1305, in, n);
  41. ECRYPT_encrypt_bytes(&ctx->chacha20, in, out, n);
  42. }
  43. // Include authenticated data in the Poly1305 MAC.
  44. void chacha20poly1305_auth(chacha20poly1305_ctx *ctx, const uint8_t *in, size_t n) {
  45. poly1305_update(&ctx->poly1305, in, n);
  46. }
  47. // Compute NaCl secretbox-style Poly1305 MAC.
  48. void chacha20poly1305_finish(chacha20poly1305_ctx *ctx, uint8_t mac[16]) {
  49. poly1305_finish(&ctx->poly1305, mac);
  50. }