chacha20poly1305.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  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(
  11. chacha20poly1305_ctx* ctx,
  12. const uint8_t key[32],
  13. const uint8_t nonce[24]) {
  14. unsigned char subkey[32] = {0};
  15. unsigned char block0[64] = {0};
  16. ECRYPT_ctx tmp = {0};
  17. // Generate the Chacha20 key by applying HChaCha20 to the
  18. // original key and the first 16 bytes of the nonce.
  19. ECRYPT_keysetup(&tmp, key, 256, 16);
  20. tmp.input[12] = U8TO32_LITTLE(nonce + 0);
  21. tmp.input[13] = U8TO32_LITTLE(nonce + 4);
  22. tmp.input[14] = U8TO32_LITTLE(nonce + 8);
  23. tmp.input[15] = U8TO32_LITTLE(nonce + 12);
  24. hchacha20(&tmp, subkey);
  25. // Initialize Chacha20 with the newly generated key and
  26. // the last 8 bytes of the nonce.
  27. ECRYPT_keysetup(&ctx->chacha20, subkey, 256, 16);
  28. ECRYPT_ivsetup(&ctx->chacha20, nonce + 16);
  29. // Encrypt 64 bytes of zeros and use the first 32 bytes
  30. // as the Poly1305 key.
  31. ECRYPT_encrypt_bytes(&ctx->chacha20, block0, block0, 64);
  32. poly1305_init(&ctx->poly1305, block0);
  33. }
  34. // Encrypt n bytes of plaintext where n must be evenly divisible by the
  35. // Chacha20 blocksize of 64, except for the final n bytes of plaintext.
  36. void chacha20poly1305_encrypt(chacha20poly1305_ctx* ctx, const uint8_t* in, uint8_t* out, size_t n) {
  37. ECRYPT_encrypt_bytes(&ctx->chacha20, in, out, n);
  38. poly1305_update(&ctx->poly1305, out, n);
  39. }
  40. // Decrypt n bytes of ciphertext where n must be evenly divisible by the
  41. // Chacha20 blocksize of 64, except for the final n bytes of ciphertext.
  42. void chacha20poly1305_decrypt(chacha20poly1305_ctx* ctx, const uint8_t* in, uint8_t* out, size_t n) {
  43. poly1305_update(&ctx->poly1305, in, n);
  44. ECRYPT_encrypt_bytes(&ctx->chacha20, in, out, n);
  45. }
  46. // Include authenticated data in the Poly1305 MAC.
  47. void chacha20poly1305_auth(chacha20poly1305_ctx* ctx, const uint8_t* in, size_t n) {
  48. poly1305_update(&ctx->poly1305, in, n);
  49. }
  50. // Compute NaCl secretbox-style Poly1305 MAC.
  51. void chacha20poly1305_finish(chacha20poly1305_ctx* ctx, uint8_t mac[16]) {
  52. poly1305_finish(&ctx->poly1305, mac);
  53. }