Skip to content

C API Reference

github-actions[bot] edited this page Jul 27, 2026 · 2 revisions

C API Reference

Reference documentation for the AMA Cryptography native C library (include/ama_cryptography.h). This library provides all cryptographic primitives with zero external dependencies.


Overview

The C library is built as both a shared library (.so/.dll) and static library (.a/.lib). It requires C11 (-std=c11).

Include path:

#include "../include/ama_cryptography.h"

Link flags:

# Shared library
-L./build -lama_cryptography

# Static library
-L./build -lama_cryptography_static

Context Management

ama_context_init()

Initialize a cryptographic context.

ama_context_t *ama_context_init(void);

ama_context_free()

Securely free a context (zeroes internal key material).

void ama_context_free(ama_context_t *ctx);

Random Number Generation

ama_random_bytes()

Generate cryptographically secure random bytes.

int ama_random_bytes(uint8_t *buf, size_t len);

Uses platform-native CSPRNG:

  • Linux: getrandom() syscall (kernel ≥ 3.17)
  • macOS: getentropy()
  • Windows: BCryptGenRandom()

Returns: 0 on success, negative on error.

uint8_t key[32];
if (ama_random_bytes(key, 32) != 0) {
    // handle error
}

Hash Functions

SHA3-256

// One-shot hash
int ama_sha3_256(
    const uint8_t *message, size_t message_len,
    uint8_t digest[32]          // Output: 32 bytes
);

// Streaming API
ama_sha3_ctx_t ctx;
ama_sha3_256_init(&ctx);
ama_sha3_256_update(&ctx, data, len);
ama_sha3_256_final(&ctx, digest);

SHAKE256 (XOF)

void ama_shake256_inc_init(ama_shake256incctx *ctx);
void ama_shake256_inc_absorb(ama_shake256incctx *ctx, const uint8_t *in, size_t inlen);
void ama_shake256_inc_finalize(ama_shake256incctx *ctx);
void ama_shake256_inc_squeeze(uint8_t *out, size_t outlen, ama_shake256incctx *ctx);
void ama_shake256_inc_ctx_release(ama_shake256incctx *ctx);

Message Authentication

HMAC-SHA3-256

int ama_hmac_sha3_256(
    const uint8_t *key, size_t key_len,
    const uint8_t *message, size_t message_len,
    uint8_t tag[32]             // Output: 32 bytes
);

Key Derivation

HKDF-SHA3-256

int ama_hkdf(
    const uint8_t *salt, size_t salt_len,   // Optional salt (NULL for zero salt)
    const uint8_t *ikm, size_t ikm_len,     // Input key material
    const uint8_t *info, size_t info_len,   // Context info
    uint8_t *okm, size_t okm_len            // Output: derived key
);

Example:

uint8_t derived_key[32];
const char *info = "ama-hmac-key-v1";
ama_hkdf(
    NULL, 0,                          // no salt
    master_secret, 32,                // input key material
    (uint8_t *)info, strlen(info),    // context
    derived_key, 32                   // output
);

Agent-Bound HKDF (INVARIANT-30)

Binds derived material to a named agent instance. Non-EPHEMERAL lifetimes and restricted capabilities (PERSISTENCE, SELF_REPLICATE, DELEGATE) require an operator-held authority key; otherwise the call refuses and writes nothing.

typedef struct {
    uint8_t version;      // AMA_AGENT_BINDING_VERSION
    uint8_t lifetime;     // ama_agent_lifetime_t (EPHEMERAL/SESSION/PERSISTENT)
    uint8_t capabilities; // bitmask of AMA_AGENT_CAP_*
    uint8_t reserved;     // MUST be zero
    uint8_t instance_id[32];
    uint8_t ethical_profile[32];  // all-zero = absent
    uint8_t authorization[32];    // all-zero = unauthorized
} ama_agent_binding_t;

ama_error_t ama_agent_binding_init(ama_agent_binding_t *b,
                                   ama_agent_lifetime_t lifetime,
                                   uint8_t capabilities,
                                   const uint8_t instance_id[32],
                                   const uint8_t *ethical_profile);  // or NULL

ama_error_t ama_agent_binding_authorize(ama_agent_binding_t *b,      // operator-side
                                        const uint8_t *authority_key,
                                        size_t key_len);             // >= 32

ama_error_t ama_agent_binding_check(const ama_agent_binding_t *b,    // constant-time
                                    const uint8_t *authority_key,
                                    size_t key_len);

ama_error_t ama_agent_binding_context(const ama_agent_binding_t *b,  // ML-DSA/SLH-DSA ctx
                                      const uint8_t *authority_key,
                                      size_t key_len,
                                      uint8_t out_ctx[32]);

ama_error_t ama_hkdf_agent_bound(const ama_agent_binding_t *b,
                                 const uint8_t *authority_key, size_t key_len,
                                 const uint8_t *salt, size_t salt_len,
                                 const uint8_t *ikm,  size_t ikm_len,
                                 const uint8_t *info, size_t info_len,
                                 uint8_t *okm, size_t okm_len);

Example — ordinary ephemeral use needs no authority key:

ama_agent_binding_t b;
uint8_t session_key[32];

ama_agent_binding_init(&b, AMA_AGENT_LIFETIME_EPHEMERAL,
                       AMA_AGENT_CAP_DATA_SIGN, instance_id, NULL);

if (ama_hkdf_agent_bound(&b, NULL, 0,
                         NULL, 0,
                         ikm, sizeof(ikm),
                         (const uint8_t *)"session", 7,
                         session_key, sizeof(session_key)) != AMA_SUCCESS) {
    /* refused: no bytes written */
}

Requesting AMA_AGENT_CAP_PERSISTENCE (or any non-EPHEMERAL lifetime) without a verifying authorization tag returns AMA_ERROR_ETHICAL_BINDING and writes nothing. The layer needs only SHA3/HMAC/HKDF, so it is available in the AMA_USE_NATIVE_PQC=OFF build as well.


Digital Signatures

Ed25519

// Generate key pair
// pk: 32 bytes, sk: 32 bytes (seed)
int ama_ed25519_keypair(uint8_t pk[32], uint8_t sk[32]);

// Sign a message
// sig: 64 bytes output
int ama_ed25519_sign(
    uint8_t sig[64],
    const uint8_t *message, size_t message_len,
    const uint8_t sk[32]
);

// Verify a signature
// Returns: 0 if valid, non-zero if invalid
int ama_ed25519_verify(
    const uint8_t sig[64],
    const uint8_t *message, size_t message_len,
    const uint8_t pk[32]
);

Example:

uint8_t pk[32], sk[32];
ama_ed25519_keypair(pk, sk);

uint8_t sig[64];
const uint8_t *msg = (uint8_t *)"Hello";
ama_ed25519_sign(sig, msg, 5, sk);

int valid = (ama_ed25519_verify(sig, msg, 5, pk) == 0);

ML-DSA-65 (Dilithium — FIPS 204)

// Key sizes
#define AMA_DILITHIUM_PK_BYTES   1952
#define AMA_DILITHIUM_SK_BYTES   4032
#define AMA_DILITHIUM_SIG_BYTES  3309

// Generate key pair
int ama_dilithium_keypair(
    uint8_t pk[AMA_DILITHIUM_PK_BYTES],
    uint8_t sk[AMA_DILITHIUM_SK_BYTES]
);

// Sign a message
int ama_dilithium_sign(
    uint8_t *sig, size_t *sig_len,          // sig_len output ≤ AMA_DILITHIUM_SIG_BYTES
    const uint8_t *message, size_t msg_len,
    const uint8_t sk[AMA_DILITHIUM_SK_BYTES]
);

// Verify a signature
// Returns: 0 if valid, non-zero if invalid
int ama_dilithium_verify(
    const uint8_t *sig, size_t sig_len,
    const uint8_t *message, size_t msg_len,
    const uint8_t pk[AMA_DILITHIUM_PK_BYTES]
);

ML-KEM-1024 (Kyber — FIPS 203)

// Key sizes
#define AMA_KYBER_PK_BYTES   1568
#define AMA_KYBER_SK_BYTES   3168
#define AMA_KYBER_CT_BYTES   1568
#define AMA_KYBER_SS_BYTES   32

// Generate key pair
int ama_kyber_keypair(
    uint8_t pk[AMA_KYBER_PK_BYTES],
    uint8_t sk[AMA_KYBER_SK_BYTES]
);

// Encapsulate: generates ciphertext and shared secret
int ama_kyber_enc(
    uint8_t ct[AMA_KYBER_CT_BYTES],
    uint8_t ss[AMA_KYBER_SS_BYTES],
    const uint8_t pk[AMA_KYBER_PK_BYTES]
);

// Decapsulate: recovers shared secret from ciphertext
int ama_kyber_dec(
    uint8_t ss[AMA_KYBER_SS_BYTES],
    const uint8_t ct[AMA_KYBER_CT_BYTES],
    const uint8_t sk[AMA_KYBER_SK_BYTES]
);

SPHINCS+-SHA2-256f (FIPS 205)

// Key sizes
#define AMA_SPHINCS_PK_BYTES   64
#define AMA_SPHINCS_SK_BYTES   128
#define AMA_SPHINCS_SIG_BYTES  49856

// Generate key pair
int ama_sphincs_keypair(
    uint8_t pk[AMA_SPHINCS_PK_BYTES],
    uint8_t sk[AMA_SPHINCS_SK_BYTES]
);

// Sign
int ama_sphincs_sign(
    uint8_t sig[AMA_SPHINCS_SIG_BYTES],
    const uint8_t *message, size_t msg_len,
    const uint8_t sk[AMA_SPHINCS_SK_BYTES]
);

// Verify
// Returns: 0 if valid, non-zero if invalid
int ama_sphincs_verify(
    const uint8_t sig[AMA_SPHINCS_SIG_BYTES],
    const uint8_t *message, size_t msg_len,
    const uint8_t pk[AMA_SPHINCS_PK_BYTES]
);

Authenticated Encryption

AES-256-GCM

// Encrypt
// Returns: 0 on success, negative on error
int ama_aes256_gcm_encrypt(
    const uint8_t *plaintext, size_t pt_len,
    const uint8_t *aad, size_t aad_len,     // Additional authenticated data
    const uint8_t key[32],                  // 256-bit key
    const uint8_t iv[12],                   // 96-bit nonce/IV
    uint8_t *ciphertext,                    // Output: pt_len bytes
    uint8_t tag[16]                         // Output: 16-byte GCM tag
);

// Decrypt and authenticate
// Returns: 0 on success, AMA_ERR_AUTH_FAILED if tag mismatch
int ama_aes256_gcm_decrypt(
    const uint8_t *ciphertext, size_t ct_len,
    const uint8_t *aad, size_t aad_len,
    const uint8_t key[32],
    const uint8_t iv[12],
    const uint8_t tag[16],
    uint8_t *plaintext                      // Output: ct_len bytes
);

ChaCha20-Poly1305

// Encrypt
int ama_chacha20poly1305_encrypt(
    const uint8_t *plaintext, size_t pt_len,
    const uint8_t *aad, size_t aad_len,
    const uint8_t key[32],                  // 256-bit key
    const uint8_t nonce[12],                // 96-bit nonce
    uint8_t *ciphertext,                    // Output: pt_len bytes
    uint8_t tag[16]                         // Output: 16-byte Poly1305 tag
);

// Decrypt and authenticate
int ama_chacha20poly1305_decrypt(
    const uint8_t *ciphertext, size_t ct_len,
    const uint8_t *aad, size_t aad_len,
    const uint8_t key[32],
    const uint8_t nonce[12],
    const uint8_t tag[16],
    uint8_t *plaintext
);

Key Exchange

X25519

// Generate key pair
// sk: 32 bytes (random scalar), pk: 32 bytes (Curve25519 public key)
int ama_x25519_keypair(uint8_t pk[32], uint8_t sk[32]);

// Compute shared secret
// shared_secret = X25519(sk, peer_pk)
int ama_x25519_key_exchange(
    uint8_t shared_secret[32],
    const uint8_t sk[32],
    const uint8_t peer_pk[32]
);

Password Hashing

Argon2id

int ama_argon2id(
    const uint8_t *password, size_t pwd_len,
    const uint8_t *salt, size_t salt_len,
    uint32_t t_cost,          // Time cost (iterations)
    uint32_t m_cost,          // Memory cost (KiB)
    uint32_t parallelism,     // Parallelism degree
    uint8_t *output, size_t output_len  // Output hash
);

Constant-Time Operations

// Constant-time memory comparison (timing-safe)
// Returns: 0 if equal, non-zero if different
int ama_consttime_memcmp(const void *a, const void *b, size_t len);

// Constant-time conditional swap (no branch)
void ama_consttime_swap(void *a, void *b, size_t len, int condition);

// Constant-time copy (no branch on condition)
void ama_consttime_copy(void *dst, const void *src, size_t len, int condition);

Error Codes

The canonical definition is the ama_error_t enum in include/ama_cryptography.h:

typedef enum {
    AMA_SUCCESS               =  0,
    AMA_ERROR_INVALID_PARAM   = -1,  // NULL pointer, bad length, out-of-range argument
    AMA_ERROR_MEMORY          = -2,  // Allocation failure
    AMA_ERROR_CRYPTO          = -3,  // Primitive-level failure
    AMA_ERROR_VERIFY_FAILED   = -4,  // Signature or authentication tag rejected
    AMA_ERROR_NOT_IMPLEMENTED = -5,  // Entry point compiled out of this build
    AMA_ERROR_TIMING_ATTACK   = -6,  // Timing-guard tripped
    AMA_ERROR_SIDE_CHANNEL    = -7,  // Side-channel guard tripped
    AMA_ERROR_OVERFLOW        = -8,  // Arithmetic/buffer overflow prevented
    AMA_ERROR_ETHICAL_BINDING = -9   // Agent-instance binding policy refused (INVARIANT-30)
} ama_error_t;

AMA_ERROR_ETHICAL_BINDING is deliberately distinct from AMA_ERROR_INVALID_PARAM: the arguments were well-formed, the policy refused. New codes are appended, so existing values never change.


Build Requirements

  • C Standard: C11 (CMAKE_C_STANDARD 11, no extensions)
  • CMake: 3.15+
  • Compiler: GCC 7+, Clang 6+, MSVC 2019+
  • Platforms: Linux, macOS, Windows

See Installation for build instructions.


See Cryptography Algorithms for algorithm specifications, or Installation for build instructions.

Clone this wiki locally