/*
 * nostr_chacha20.h - ChaCha20 stream cipher implementation
 * 
 * Implementation based on RFC 8439 "ChaCha20 and Poly1305 for IETF Protocols"
 * 
 * This is a small, portable implementation for NIP-44 support in the NOSTR library.
 * The implementation prioritizes correctness and simplicity over performance.
 */

#ifndef NOSTR_CHACHA20_H
#define NOSTR_CHACHA20_H

#include <stdint.h>
#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

/*
 * ============================================================================
 * CONSTANTS AND DEFINITIONS
 * ============================================================================
 */

#define CHACHA20_KEY_SIZE    32  /* 256 bits */
#define CHACHA20_NONCE_SIZE  12  /* 96 bits */
#define CHACHA20_BLOCK_SIZE  64  /* 512 bits */

/*
 * ============================================================================
 * CORE CHACHA20 FUNCTIONS
 * ============================================================================
 */

/**
 * ChaCha20 quarter round operation
 * 
 * Operates on four 32-bit words performing the core ChaCha20 quarter round:
 * a += b; d ^= a; d <<<= 16;
 * c += d; b ^= c; b <<<= 12;
 * a += b; d ^= a; d <<<= 8;
 * c += d; b ^= c; b <<<= 7;
 * 
 * @param state[in,out] ChaCha state as 16 32-bit words
 * @param a, b, c, d    Indices into state array for quarter round
 */
void chacha20_quarter_round(uint32_t state[16], int a, int b, int c, int d);

/**
 * ChaCha20 block function
 * 
 * Transforms a 64-byte input block using ChaCha20 algorithm with 20 rounds.
 * 
 * @param key[in]       32-byte key
 * @param counter[in]   32-bit block counter
 * @param nonce[in]     12-byte nonce
 * @param output[out]   64-byte output buffer
 * @return              0 on success, negative on error
 */
int chacha20_block(const uint8_t key[32], uint32_t counter, 
                   const uint8_t nonce[12], uint8_t output[64]);

/**
 * ChaCha20 encryption/decryption
 * 
 * Encrypts or decrypts data using ChaCha20 stream cipher.
 * Since ChaCha20 is a stream cipher, encryption and decryption are the same operation.
 * 
 * @param key[in]           32-byte key
 * @param counter[in]       Initial 32-bit counter value
 * @param nonce[in]         12-byte nonce
 * @param input[in]         Input data to encrypt/decrypt
 * @param output[out]       Output buffer (can be same as input)
 * @param length[in]        Length of input data in bytes
 * @return                  0 on success, negative on error
 */
int chacha20_encrypt(const uint8_t key[32], uint32_t counter, 
                     const uint8_t nonce[12], const uint8_t* input, 
                     uint8_t* output, size_t length);

/*
 * ============================================================================
 * UTILITY FUNCTIONS
 * ============================================================================
 */

/**
 * Initialize ChaCha20 state matrix
 * 
 * Sets up the initial 16-word state matrix with constants, key, counter, and nonce.
 * 
 * @param state[out]    16-word state array to initialize
 * @param key[in]       32-byte key
 * @param counter[in]   32-bit block counter
 * @param nonce[in]     12-byte nonce
 */
void chacha20_init_state(uint32_t state[16], const uint8_t key[32], 
                         uint32_t counter, const uint8_t nonce[12]);

/**
 * Serialize ChaCha20 state to bytes
 * 
 * Converts 16 32-bit words to 64 bytes in little-endian format.
 * 
 * @param state[in]     16-word state array
 * @param output[out]   64-byte output buffer
 */
void chacha20_serialize_state(const uint32_t state[16], uint8_t output[64]);

#ifdef __cplusplus
}
#endif

#endif /* NOSTR_CHACHA20_H */
