XChaCha20-Poly1305.h (5233B)
1 /* 2 * XChaCha20-Poly1305 AEAD Implementation 3 * 4 * Compliant with: 5 * - draft-irtf-cfrg-xchacha (XChaCha: eXtended-nonce ChaCha and AEAD) 6 * - Used in libsodium, WireGuard, age encryption 7 * 8 * Key Differences from ChaCha20-Poly1305: 9 * - 192-bit nonces (24 bytes) instead of 96-bit (12 bytes) 10 * - Safe to use random nonces (no collision concerns) 11 * - Same performance as ChaCha20-Poly1305 12 * - HChaCha20 for key derivation from extended nonce 13 * 14 * Security Features: 15 * - 256-bit keys 16 * - 192-bit nonces (can be randomly generated) 17 * - Authenticated encryption (AEAD) 18 * - Fast software implementation (~1-2 GB/s) 19 * - No hardware acceleration needed 20 * - No timing attacks 21 * 22 * Advantages over ChaCha20-Poly1305: 23 * - Larger nonce space (2^192 vs 2^96) 24 * - Can use random nonces without collision risk 25 * - No need for nonce counter management 26 * - Simpler to use correctly 27 * 28 * Use XChaCha20-Poly1305 when: 29 * - You want to use random nonces 30 * - You don't want to track nonce state 31 * - You need nonce misuse resistance 32 */ 33 34 #ifndef XCHACHA20_POLY1305_H 35 #define XCHACHA20_POLY1305_H 36 37 #include <stdint.h> 38 #include <stdlib.h> 39 40 #ifdef __cplusplus 41 extern "C" { 42 #endif 43 44 /* Constants */ 45 #define XCHACHA20_KEY_SIZE 32 /* 256 bits */ 46 #define XCHACHA20_NONCE_SIZE 24 /* 192 bits (extended) */ 47 #define XCHACHA20_BLOCK_SIZE 64 /* 512 bits */ 48 #define XCHACHA20_TAG_SIZE 16 /* 128 bits */ 49 50 /* XChaCha20 context (reuses ChaCha20 internals) */ 51 typedef struct { 52 uint32_t state[16]; 53 uint8_t keystream[64]; 54 size_t keystream_pos; 55 uint64_t counter; 56 } xchacha20_context; 57 58 /* Poly1305 context */ 59 typedef struct { 60 uint32_t r[5]; 61 uint32_t h[5]; 62 uint32_t pad[4]; 63 uint8_t buffer[16]; 64 size_t buffer_len; 65 uint64_t total_len; 66 } xchacha20_poly1305_context_mac; 67 68 /* XChaCha20-Poly1305 AEAD context */ 69 typedef struct { 70 xchacha20_context cipher; 71 xchacha20_poly1305_context_mac mac; 72 uint64_t aad_len; 73 uint64_t data_len; 74 } xchacha20_poly1305_context; 75 76 /** 77 * Initialize XChaCha20-Poly1305 AEAD 78 * 79 * @param ctx AEAD context 80 * @param key 256-bit (32 byte) encryption key 81 * @param nonce 192-bit (24 byte) nonce (can be random!) 82 * @return 0 on success, -1 on error 83 * 84 * Security Notes: 85 * - Nonces can be randomly generated (192 bits is large enough) 86 * - No need to track nonce counter 87 * - Collision probability: ~2^96 messages before concern 88 * - Provides both encryption and authentication 89 */ 90 int xchacha20_poly1305_init(xchacha20_poly1305_context *ctx, 91 const uint8_t *key, 92 const uint8_t *nonce); 93 94 /** 95 * XChaCha20-Poly1305 AEAD Encryption 96 * 97 * @param ctx Initialized context 98 * @param aad Additional authenticated data (can be NULL if aad_len is 0) 99 * @param aad_len AAD length in bytes 100 * @param plaintext Input plaintext 101 * @param pt_len Plaintext length in bytes 102 * @param ciphertext Output ciphertext buffer (must be pt_len bytes) 103 * @param tag Output authentication tag (must be 16 bytes) 104 * @return 0 on success, -1 on error 105 * 106 * Security Notes: 107 * - AAD is authenticated but not encrypted 108 * - Maximum plaintext: 2^38 - 64 bytes (~256 GB) 109 * - Tag must be sent with ciphertext 110 * - Verify tag before using decrypted data 111 * 112 * Performance: 113 * - Same speed as ChaCha20-Poly1305 (~1-2 GB/s) 114 * - Minimal overhead from HChaCha20 key derivation 115 */ 116 int xchacha20_poly1305_encrypt(xchacha20_poly1305_context *ctx, 117 const uint8_t *aad, size_t aad_len, 118 const uint8_t *plaintext, size_t pt_len, 119 uint8_t *ciphertext, 120 uint8_t *tag); 121 122 /** 123 * XChaCha20-Poly1305 AEAD Decryption 124 * 125 * @param ctx Initialized context 126 * @param aad Additional authenticated data (must match encryption) 127 * @param aad_len AAD length in bytes 128 * @param ciphertext Input ciphertext 129 * @param ct_len Ciphertext length in bytes 130 * @param tag Authentication tag from encryption (16 bytes) 131 * @param plaintext Output plaintext buffer (must be ct_len bytes) 132 * @return 0 on success, -1 on authentication failure 133 * 134 * Security Notes: 135 * - Returns -1 if authentication tag doesn't match 136 * - Plaintext is NOT valid if function returns -1 137 * - Constant-time tag comparison 138 * - MUST verify return value before using plaintext 139 */ 140 int xchacha20_poly1305_decrypt(xchacha20_poly1305_context *ctx, 141 const uint8_t *aad, size_t aad_len, 142 const uint8_t *ciphertext, size_t ct_len, 143 const uint8_t *tag, 144 uint8_t *plaintext); 145 146 /** 147 * Clean up context (zeros sensitive data) 148 * 149 * @param ctx Context to clean 150 * 151 * Security: Zeros all key material and state 152 */ 153 void xchacha20_poly1305_cleanup(xchacha20_poly1305_context *ctx); 154 155 /** 156 * HChaCha20 - Key derivation for XChaCha20 157 * (Internal function, exposed for testing) 158 * 159 * @param key 256-bit input key 160 * @param nonce 128-bit input (first 16 bytes of XChaCha nonce) 161 * @param subkey 256-bit output subkey 162 */ 163 void hchacha20(const uint8_t key[32], const uint8_t nonce[16], uint8_t subkey[32]); 164 165 #ifdef __cplusplus 166 } 167 #endif 168 169 #endif /* XCHACHA20_POLY1305_H */