// The MIT License (MIT)
//
// Copyright (C) 2026 Scott Duensing
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

// Security library: Diffie-Hellman key exchange + XTEA-CTR cipher
// Targets 486-class hardware with 1024-bit DH (256-bit private exponent)
// and XTEA in CTR mode for symmetric encryption.
//
// Why XTEA instead of AES/DES:
//   XTEA requires zero lookup tables, no key schedule, and compiles to
//   ~20 instructions per round (shifts, adds, XORs). This makes it ideal
//   for a 486 where cache is tiny (8KB) and AES's 4KB S-boxes would
//   thrash it. DES is similarly table-heavy and also has a complex key
//   schedule. XTEA has no library dependencies  -- the entire cipher fits
//   in a dozen lines of C. At 32 rounds, XTEA provides 128-bit security
//   with negligible per-byte cost on even the slowest target hardware.
//
// Why 1024-bit DH with 256-bit private exponent:
//   RFC 2409 Group 2 provides interoperability and a well-audited safe
//   prime. 256-bit private exponents (vs full 1024-bit) reduce the modular
//   exponentiation from ~1024 squarings+multiplies to ~256, making key
//   generation feasible on a 486 in seconds rather than minutes. The
//   security reduction is negligible (Pollard's rho on 256-bit exponent
//   is ~2^128 operations, same as XTEA's key strength).
//
// RNG:
//   XTEA-CTR DRBG seeded from PIT timer jitter and BIOS tick count.
//   Hardware entropy is weak (~20 bits from PIT), so callers should
//   supplement with user-generated entropy (keyboard timing, etc.)
//   before generating DH keys.

#ifndef SECURITY_H
#define SECURITY_H

#include <stdint.h>
#include <stdbool.h>

// Key sizes (bytes)
#define SEC_DH_KEY_SIZE         128 // 1024-bit DH public key
#define SEC_XTEA_KEY_SIZE        16 // 128-bit XTEA key

// Error codes
#define SEC_SUCCESS               0
#define SEC_ERR_PARAM            -1
#define SEC_ERR_NOT_READY        -2

// Opaque types
typedef struct SecDhS SecDhT;
typedef struct SecCipherS SecCipherT;


// RNG  -- seed before generating keys. Hardware entropy is weak (~20 bits);
// callers should supplement with keyboard timing, mouse jitter, etc.
int  secRngGatherEntropy(uint8_t *buf, int len);
void secRngAddEntropy(const uint8_t *data, int len);
void secRngBytes(uint8_t *buf, int len);
void secRngSeed(const uint8_t *entropy, int len);

// Diffie-Hellman key exchange (1024-bit, RFC 2409 Group 2)
SecDhT *secDhCreate(void);
int     secDhComputeSecret(SecDhT *dh, const uint8_t *remotePub, int len);
int     secDhDeriveKey(SecDhT *dh, uint8_t *key, int keyLen);
void    secDhDestroy(SecDhT *dh);
int     secDhGenerateKeys(SecDhT *dh);
int     secDhGetPublicKey(SecDhT *dh, uint8_t *buf, int *len);

// XTEA cipher in CTR mode. CTR mode turns a block cipher into a stream
// cipher: encrypt an incrementing counter with the key to produce a
// keystream, then XOR with plaintext. Encrypt and decrypt are identical
// (XOR is its own inverse). The counter must never repeat with the same
// key, which is why secLink derives separate TX/RX keys.
SecCipherT *secCipherCreate(const uint8_t *key);
void        secCipherCrypt(SecCipherT *c, uint8_t *data, int len);
void        secCipherDestroy(SecCipherT *c);

#endif
