/* pq_crypto_firmware.h — Post-quantum crypto wrappers for ESP32 firmware.
 *
 * Provides firmware-friendly wrappers around the PQClean algorithms:
 *   - ML-DSA-65 (FIPS 204 signatures)
 *   - SLH-DSA-128s (FIPS 205 hash-based signatures)
 *   - ML-KEM-768 (FIPS 203 key encapsulation)
 *
 * Key generation is deterministic from a 32-byte seed (derived from the
 * mnemonic via BIP-32/HMAC-SHA512). The seed feeds the deterministic DRBG
 * (pq_drbg_firmware.c) which replaces PQClean's randombytes() during keygen.
 *
 * ed25519 and x25519 are handled separately via mbedtls (see
 * key_derivation.c) and are not part of this PQClean component.
 */
#ifndef FIRMWARE_PQ_CRYPTO_H
#define FIRMWARE_PQ_CRYPTO_H

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

/* --- Algorithm identifiers --- */
typedef enum {
    FW_PQ_ALG_ML_DSA_65 = 0,
    FW_PQ_ALG_SLH_DSA_128S,
    FW_PQ_ALG_ML_KEM_768,
    FW_PQ_ALG_UNKNOWN
} fw_pq_alg_t;

/* --- Key sizes (compile-time constants, matching PQClean api.h) --- */
#define FW_ML_DSA_65_PUBKEY_LEN   1952
#define FW_ML_DSA_65_PRIVKEY_LEN  4032
#define FW_ML_DSA_65_SIG_LEN      3309

#define FW_SLH_DSA_128S_PUBKEY_LEN   32
#define FW_SLH_DSA_128S_PRIVKEY_LEN  64
#define FW_SLH_DSA_128S_SIG_LEN      7856

#define FW_ML_KEM_768_PUBKEY_LEN      1184
#define FW_ML_KEM_768_PRIVKEY_LEN     2400
#define FW_ML_KEM_768_CIPHERTEXT_LEN  1088
#define FW_ML_KEM_768_SHARED_SECRET_LEN 32

/* --- Key generation (deterministic from seed) --- */

/* Generate an ML-DSA-65 keypair from a 32-byte seed.
 * pk must be at least FW_ML_DSA_65_PUBKEY_LEN bytes.
 * sk must be at least FW_ML_DSA_65_PRIVKEY_LEN bytes.
 * Returns 0 on success, -1 on error. */
int fw_pq_ml_dsa_65_keygen(const uint8_t seed[32],
                            uint8_t *pk, uint8_t *sk);

/* Generate an SLH-DSA-128s keypair from a 32-byte seed.
 * pk must be at least FW_SLH_DSA_128S_PUBKEY_LEN bytes.
 * sk must be at least FW_SLH_DSA_128S_PRIVKEY_LEN bytes.
 * Returns 0 on success, -1 on error.
 * WARNING: SLH-DSA-128s keygen takes 5-30 seconds on ESP32. */
int fw_pq_slh_dsa_128s_keygen(const uint8_t seed[32],
                               uint8_t *pk, uint8_t *sk);

/* Generate an ML-KEM-768 keypair from a 32-byte seed.
 * pk must be at least FW_ML_KEM_768_PUBKEY_LEN bytes.
 * sk must be at least FW_ML_KEM_768_PRIVKEY_LEN bytes.
 * Returns 0 on success, -1 on error. */
int fw_pq_ml_kem_768_keygen(const uint8_t seed[32],
                             uint8_t *pk, uint8_t *sk);

/* --- Signing (ML-DSA-65, SLH-DSA-128s) --- */

/* Sign a message with ML-DSA-65.
 * sig must be at least FW_ML_DSA_65_SIG_LEN bytes.
 * Returns 0 on success, -1 on error. */
int fw_pq_ml_dsa_65_sign(uint8_t *sig, size_t *siglen,
                          const uint8_t *m, size_t mlen,
                          const uint8_t *sk);

/* Verify an ML-DSA-65 signature.
 * Returns 0 on valid, -1 on invalid. */
int fw_pq_ml_dsa_65_verify(const uint8_t *sig, size_t siglen,
                            const uint8_t *m, size_t mlen,
                            const uint8_t *pk);

/* Sign a message with SLH-DSA-128s.
 * sig must be at least FW_SLH_DSA_128S_SIG_LEN bytes.
 * WARNING: SLH-DSA-128s signing takes 5-30 seconds on ESP32.
 * Returns 0 on success, -1 on error. */
int fw_pq_slh_dsa_128s_sign(uint8_t *sig, size_t *siglen,
                              const uint8_t *m, size_t mlen,
                              const uint8_t *sk);

/* Verify an SLH-DSA-128s signature.
 * Returns 0 on valid, -1 on invalid. */
int fw_pq_slh_dsa_128s_verify(const uint8_t *sig, size_t siglen,
                                const uint8_t *m, size_t mlen,
                                const uint8_t *pk);

/* --- KEM (ML-KEM-768) --- */

/* Encapsulate: generate ciphertext + shared secret from a public key.
 * Uses real randomness (ESP32 hardware RNG) — not the deterministic DRBG.
 * ct must be at least FW_ML_KEM_768_CIPHERTEXT_LEN bytes.
 * ss must be at least FW_ML_KEM_768_SHARED_SECRET_LEN bytes.
 * Returns 0 on success, -1 on error. */
int fw_pq_ml_kem_768_encaps(uint8_t *ct, uint8_t *ss, const uint8_t *pk);

/* Decapsulate: recover shared secret from secret key + ciphertext.
 * ss must be at least FW_ML_KEM_768_SHARED_SECRET_LEN bytes.
 * Returns 0 on success, -1 on error. */
int fw_pq_ml_kem_768_decaps(uint8_t *ss, const uint8_t *ct, const uint8_t *sk);

#endif /* FIRMWARE_PQ_CRYPTO_H */
