DVX_GUI/security
2026-03-17 23:51:01 -05:00
..
Makefile Reliable, secure, serial link protocol added. 2026-03-10 21:05:52 -05:00
README.md Reliable, secure, serial link protocol added. 2026-03-10 21:05:52 -05:00
security.c Much new documentation added as comments to code. 2026-03-17 23:51:01 -05:00
security.h Much new documentation added as comments to code. 2026-03-17 23:51:01 -05:00

Security — DH Key Exchange and XTEA-CTR Cipher

Cryptographic library providing Diffie-Hellman key exchange and XTEA symmetric encryption, optimized for 486-class DOS hardware running under DJGPP/DPMI.

Components

Diffie-Hellman Key Exchange

  • 1024-bit MODP group (RFC 2409 Group 2 safe prime)
  • 256-bit private exponents for fast computation on 486 CPUs
  • Montgomery multiplication (CIOS variant) for modular exponentiation
  • Lazy-initialized Montgomery constants (R^2 mod p, -p0^-1 mod 2^32)

XTEA Cipher (CTR Mode)

  • 128-bit key, 64-bit block size, 32 rounds
  • CTR mode — encrypt and decrypt are the same XOR operation
  • No lookup tables, no key schedule — just shifts, adds, and XORs
  • Ideal for constrained environments with small key setup cost

Pseudo-Random Number Generator

  • XTEA-CTR based DRBG (deterministic random bit generator)
  • Hardware entropy from PIT counter (~10 bits) and BIOS tick count
  • Supports additional entropy injection (keyboard timing, mouse, etc.)
  • Auto-seeds from hardware on first use if not explicitly seeded

Performance

At serial port speeds, encryption overhead is minimal:

Speed Blocks/sec CPU cycles/sec % of 33 MHz 486
9600 120 ~240K < 1%
57600 720 ~1.4M ~4%
115200 1440 ~2.9M ~9%

DH key exchange takes approximately 0.3s at 66 MHz or 0.6s at 33 MHz (256-bit private exponent, 1024-bit modulus).

API Reference

Constants

Name Value Description
SEC_DH_KEY_SIZE 128 DH public key size (bytes)
SEC_XTEA_KEY_SIZE 16 XTEA key size (bytes)
SEC_SUCCESS 0 Success
SEC_ERR_PARAM -1 Invalid parameter
SEC_ERR_NOT_READY -2 Keys not yet generated/derived
SEC_ERR_ALLOC -3 Memory allocation failed

Types

typedef struct SecDhS SecDhT;         // Opaque DH context
typedef struct SecCipherS SecCipherT; // Opaque cipher context

RNG Functions

int secRngGatherEntropy(uint8_t *buf, int len);

Reads hardware entropy sources (PIT counter, BIOS tick count). Returns the number of bytes written. Provides roughly 20 bits of true entropy.

void secRngSeed(const uint8_t *entropy, int len);

Initializes the DRBG with the given entropy. XOR-folds the input into the XTEA key, derives the counter, and mixes state by generating and discarding 64 bytes.

void secRngAddEntropy(const uint8_t *data, int len);

Mixes additional entropy into the running RNG state without resetting it. Use this to stir in keyboard timing, mouse jitter, or other runtime entropy.

void secRngBytes(uint8_t *buf, int len);

Generates len pseudo-random bytes. Auto-seeds from hardware if not previously seeded.

Diffie-Hellman Functions

SecDhT *secDhCreate(void);

Allocates a new DH context. Returns NULL on allocation failure.

int secDhGenerateKeys(SecDhT *dh);

Generates a 256-bit random private key and computes the corresponding 1024-bit public key (g^private mod p). The RNG should be seeded first.

int secDhGetPublicKey(SecDhT *dh, uint8_t *buf, int *len);

Exports the public key into buf. On entry, *len must be at least SEC_DH_KEY_SIZE (128). On return, *len is set to 128.

int secDhComputeSecret(SecDhT *dh, const uint8_t *remotePub, int len);

Computes the shared secret from the remote side's public key. Validates that the remote key is in range [2, p-2] to prevent small-subgroup attacks.

int secDhDeriveKey(SecDhT *dh, uint8_t *key, int keyLen);

Derives a symmetric key by XOR-folding the 128-byte shared secret down to keyLen bytes.

void secDhDestroy(SecDhT *dh);

Securely zeroes and frees the DH context (private key, shared secret).

Cipher Functions

SecCipherT *secCipherCreate(const uint8_t *key);

Creates an XTEA-CTR cipher context with the given 16-byte key. Counter starts at zero.

void secCipherCrypt(SecCipherT *c, uint8_t *data, int len);

Encrypts or decrypts data in place. CTR mode is symmetric — the same operation encrypts and decrypts.

void secCipherSetNonce(SecCipherT *c, uint32_t nonceLo, uint32_t nonceHi);

Sets the 64-bit nonce/counter. Call before encrypting if you need a specific starting counter value.

void secCipherDestroy(SecCipherT *c);

Securely zeroes and frees the cipher context.

Example

Full Key Exchange

#include "security.h"
#include <string.h>

// Seed the RNG
uint8_t entropy[16];
secRngGatherEntropy(entropy, sizeof(entropy));
secRngSeed(entropy, sizeof(entropy));

// Create DH context and generate keys
SecDhT *dh = secDhCreate();
secDhGenerateKeys(dh);

// Export public key to send to remote
uint8_t myPub[SEC_DH_KEY_SIZE];
int     pubLen = SEC_DH_KEY_SIZE;
secDhGetPublicKey(dh, myPub, &pubLen);
// ... send myPub to remote, receive remotePub ...

// Compute shared secret and derive a 16-byte key
secDhComputeSecret(dh, remotePub, SEC_DH_KEY_SIZE);

uint8_t key[SEC_XTEA_KEY_SIZE];
secDhDeriveKey(dh, key, SEC_XTEA_KEY_SIZE);
secDhDestroy(dh);

// Create cipher and encrypt
SecCipherT *cipher = secCipherCreate(key);
uint8_t message[] = "Secret message";
secCipherCrypt(cipher, message, sizeof(message));
// message is now encrypted

// Decrypt (same operation — CTR mode is symmetric)
// Reset counter first if using the same cipher context
secCipherSetNonce(cipher, 0, 0);
secCipherCrypt(cipher, message, sizeof(message));
// message is now plaintext again

secCipherDestroy(cipher);

Standalone Encryption

// XTEA-CTR can be used independently of DH
uint8_t key[SEC_XTEA_KEY_SIZE] = { /* your key */ };
SecCipherT *c = secCipherCreate(key);

uint8_t data[1024];
// ... fill data ...
secCipherCrypt(c, data, sizeof(data));  // encrypt in place

secCipherDestroy(c);

Implementation Details

BigNum Arithmetic

All modular arithmetic uses a 1024-bit big number type (BigNumT) stored as 32 x uint32_t words in little-endian order. Operations:

  • Add, subtract, compare, shift-left-1, bit test
  • Montgomery multiplication (CIOS with implicit right-shift)
  • Modular exponentiation (left-to-right binary square-and-multiply)

Montgomery Multiplication

The CIOS (Coarsely Integrated Operand Scanning) variant computes a * b * R^-1 mod m in a single pass with implicit division by the word base. Constants are computed once on first DH use:

  • R^2 mod p — via 2048 iterations of shift-and-conditional-subtract
  • -p[0]^-1 mod 2^32 — via Newton's method (5 iterations)

Secure Zeroing

Key material is erased using a volatile-pointer loop that the compiler cannot optimize away, preventing sensitive data from lingering in memory.

Building

make        # builds ../lib/libsecurity.a
make clean  # removes objects and library

Target: DJGPP cross-compiler, 486+ CPU.