C API Reference
Complete API documentation for MetaMUI Crypto Primitives in C.
Installation
Using pkg-config
# Install the library
make install PREFIX=/usr/local
# Compile with pkg-config
gcc -o myapp myapp.c $(pkg-config --cflags --libs metamui-crypto)
Static Linking
gcc -o myapp myapp.c -lmetamui_crypto_static -lm -lpthread
Dynamic Linking
gcc -o myapp myapp.c -lmetamui_crypto -lm -lpthread
Quick Start
#include <metamui/crypto.h>
#include <stdio.h>
#include <string.h>
int main() {
// Initialize library
metamui_init();
// Generate Ed25519 keypair
metamui_ed25519_keypair_t keypair;
metamui_ed25519_generate_keypair(&keypair);
// Sign a message
const uint8_t message[] = "Hello, World!";
uint8_t signature[METAMUI_ED25519_SIGNATURE_SIZE];
metamui_ed25519_sign(signature, message, sizeof(message) - 1,
keypair.private_key);
// Verify signature
int valid = metamui_ed25519_verify(signature, message, sizeof(message) - 1,
keypair.public_key);
printf("Signature %s\n", valid ? "valid" : "invalid");
// Cleanup
metamui_cleanup();
return 0;
}
API Documentation
For detailed API documentation, see:
Header Files
Core Headers
#include <metamui/crypto.h> // Main header, includes all modules
#include <metamui/hash.h> // Hash functions
#include <metamui/signature.h> // Digital signatures
#include <metamui/encryption.h> // Symmetric encryption
#include <metamui/kex.h> // Key exchange
#include <metamui/kdf.h> // Key derivation
#include <metamui/pqc.h> // Post-quantum algorithms
#include <metamui/util.h> // Utility functions
Memory Management
Stack Allocation
// Fixed-size buffers on stack
uint8_t hash[METAMUI_SHA256_HASH_SIZE];
uint8_t key[METAMUI_CHACHA20_KEY_SIZE];
uint8_t nonce[METAMUI_CHACHA20_NONCE_SIZE];
Heap Allocation
// Dynamic allocation
size_t ciphertext_len = plaintext_len + METAMUI_CHACHA20_POLY1305_TAG_SIZE;
uint8_t *ciphertext = malloc(ciphertext_len);
// Always check allocation
if (ciphertext == NULL) {
return METAMUI_ERR_MEMORY;
}
// Always free when done
free(ciphertext);
Secure Memory
// Allocate secure memory (locked, non-swappable)
uint8_t *secret_key = metamui_secure_alloc(32);
if (secret_key == NULL) {
return METAMUI_ERR_MEMORY;
}
// Use the key...
// Secure cleanup (overwrites memory before freeing)
metamui_secure_free(secret_key, 32);
Error Handling
Return Codes
typedef enum {
METAMUI_OK = 0,
METAMUI_ERR_INVALID_PARAM = -1,
METAMUI_ERR_INVALID_KEY = -2,
METAMUI_ERR_INVALID_SIGNATURE = -3,
METAMUI_ERR_DECRYPT_FAILED = -4,
METAMUI_ERR_MEMORY = -5,
METAMUI_ERR_NOT_INITIALIZED = -6,
METAMUI_ERR_UNKNOWN = -99
} metamui_error_t;
Error Checking
metamui_error_t result;
// Check function return
result = metamui_aes256_gcm_encrypt(ciphertext, &ciphertext_len,
plaintext, plaintext_len,
key, nonce, aad, aad_len);
if (result != METAMUI_OK) {
fprintf(stderr, "Encryption failed: %s\n",
metamui_error_string(result));
return -1;
}
Thread Safety
Thread-Safe Functions
Most functions are thread-safe and can be called concurrently:
// These can be called from multiple threads simultaneously
metamui_sha256_hash(hash1, data1, len1); // Thread 1
metamui_sha256_hash(hash2, data2, len2); // Thread 2
Thread-Local State
Some operations require thread-local state:
// Each thread needs its own context
metamui_blake3_ctx_t ctx;
metamui_blake3_init(&ctx);
metamui_blake3_update(&ctx, data, len);
metamui_blake3_final(&ctx, hash);
Synchronization
// Use mutexes for shared resources
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&lock);
// Access shared cryptographic state
pthread_mutex_unlock(&lock);
Hash Functions
SHA-256/512
uint8_t hash[METAMUI_SHA256_HASH_SIZE];
metamui_sha256_hash(hash, data, data_len);
uint8_t hash512[METAMUI_SHA512_HASH_SIZE];
metamui_sha512_hash(hash512, data, data_len);
BLAKE2b/2s
uint8_t hash[METAMUI_BLAKE2B_HASH_SIZE];
metamui_blake2b_hash(hash, sizeof(hash), data, data_len, NULL, 0);
uint8_t hash2s[METAMUI_BLAKE2S_HASH_SIZE];
metamui_blake2s_hash(hash2s, sizeof(hash2s), data, data_len, NULL, 0);
BLAKE3
uint8_t hash[METAMUI_BLAKE3_HASH_SIZE];
metamui_blake3_hash(hash, data, data_len);
// Keyed hashing
uint8_t keyed_hash[METAMUI_BLAKE3_HASH_SIZE];
metamui_blake3_keyed_hash(keyed_hash, data, data_len, key);
// Derive key
uint8_t derived_key[32];
metamui_blake3_derive_key(derived_key, sizeof(derived_key),
"my-context", data, data_len);
Streaming Hash
metamui_sha256_ctx_t ctx;
metamui_sha256_init(&ctx);
// Process chunks
while (has_more_data()) {
metamui_sha256_update(&ctx, chunk, chunk_len);
}
// Get final hash
uint8_t hash[METAMUI_SHA256_HASH_SIZE];
metamui_sha256_final(&ctx, hash);
Digital Signatures
Ed25519
// Generate keypair
metamui_ed25519_keypair_t keypair;
metamui_ed25519_generate_keypair(&keypair);
// Sign
uint8_t signature[METAMUI_ED25519_SIGNATURE_SIZE];
metamui_ed25519_sign(signature, message, message_len,
keypair.private_key);
// Verify
int valid = metamui_ed25519_verify(signature, message, message_len,
keypair.public_key);
Sr25519
// Generate keypair
metamui_sr25519_keypair_t keypair;
metamui_sr25519_generate_keypair(&keypair);
// Sign with context
uint8_t signature[METAMUI_SR25519_SIGNATURE_SIZE];
metamui_sr25519_sign_with_context(signature, message, message_len,
keypair.private_key,
context, context_len);
// Verify with context
int valid = metamui_sr25519_verify_with_context(signature,
message, message_len,
keypair.public_key,
context, context_len);
Encryption
ChaCha20-Poly1305
// Generate key and nonce
uint8_t key[METAMUI_CHACHA20_KEY_SIZE];
uint8_t nonce[METAMUI_CHACHA20_POLY1305_NONCE_SIZE];
metamui_random_bytes(key, sizeof(key));
metamui_random_bytes(nonce, sizeof(nonce));
// Encrypt with associated data
uint8_t tag[METAMUI_POLY1305_TAG_SIZE];
size_t ciphertext_len = plaintext_len;
uint8_t *ciphertext = malloc(ciphertext_len);
metamui_chacha20_poly1305_encrypt(ciphertext, tag,
plaintext, plaintext_len,
aad, aad_len,
key, nonce);
// Decrypt and verify
uint8_t *decrypted = malloc(ciphertext_len);
int result = metamui_chacha20_poly1305_decrypt(decrypted,
ciphertext, ciphertext_len,
tag, aad, aad_len,
key, nonce);
if (result != METAMUI_OK) {
// Authentication failed
}
AES-256-GCM
// Generate key and IV
uint8_t key[METAMUI_AES256_KEY_SIZE];
uint8_t iv[METAMUI_AES256_GCM_IV_SIZE];
metamui_random_bytes(key, sizeof(key));
metamui_random_bytes(iv, sizeof(iv));
// Encrypt
uint8_t tag[METAMUI_AES256_GCM_TAG_SIZE];
size_t ciphertext_len = plaintext_len;
uint8_t *ciphertext = malloc(ciphertext_len);
metamui_aes256_gcm_encrypt(ciphertext, tag,
plaintext, plaintext_len,
aad, aad_len,
key, iv);
// Decrypt
uint8_t *decrypted = malloc(ciphertext_len);
int result = metamui_aes256_gcm_decrypt(decrypted,
ciphertext, ciphertext_len,
tag, aad, aad_len,
key, iv);
Key Exchange
X25519
// Generate keypairs
uint8_t alice_private[METAMUI_X25519_KEY_SIZE];
uint8_t alice_public[METAMUI_X25519_KEY_SIZE];
uint8_t bob_private[METAMUI_X25519_KEY_SIZE];
uint8_t bob_public[METAMUI_X25519_KEY_SIZE];
metamui_x25519_generate_keypair(alice_public, alice_private);
metamui_x25519_generate_keypair(bob_public, bob_private);
// Compute shared secrets
uint8_t alice_shared[METAMUI_X25519_KEY_SIZE];
uint8_t bob_shared[METAMUI_X25519_KEY_SIZE];
metamui_x25519_compute_shared(alice_shared, alice_private, bob_public);
metamui_x25519_compute_shared(bob_shared, bob_private, alice_public);
// alice_shared == bob_shared
Post-Quantum Algorithms
ML-KEM-768
// Generate keypair
metamui_mlkem768_keypair_t keypair;
metamui_mlkem768_generate_keypair(&keypair);
// Encapsulation (sender)
uint8_t ciphertext[METAMUI_MLKEM768_CIPHERTEXT_SIZE];
uint8_t shared_secret[METAMUI_MLKEM768_SHARED_SECRET_SIZE];
metamui_mlkem768_encapsulate(ciphertext, shared_secret,
keypair.public_key);
// Decapsulation (receiver)
uint8_t shared_secret2[METAMUI_MLKEM768_SHARED_SECRET_SIZE];
metamui_mlkem768_decapsulate(shared_secret2, ciphertext,
keypair.private_key);
// shared_secret == shared_secret2
Dilithium
// Generate keypair
metamui_dilithium3_keypair_t keypair;
metamui_dilithium3_generate_keypair(&keypair);
// Sign
size_t signature_len;
uint8_t signature[METAMUI_DILITHIUM3_MAX_SIGNATURE_SIZE];
metamui_dilithium3_sign(signature, &signature_len,
message, message_len,
keypair.private_key);
// Verify
int valid = metamui_dilithium3_verify(signature, signature_len,
message, message_len,
keypair.public_key);
Key Derivation
Argon2
// Generate salt
uint8_t salt[METAMUI_ARGON2_SALT_SIZE];
metamui_random_bytes(salt, sizeof(salt));
// Hash password
uint8_t hash[32];
metamui_argon2_hash(hash, sizeof(hash),
password, password_len,
salt, sizeof(salt),
3, // iterations
4096, // memory (KB)
1); // parallelism
// Verify password
int valid = metamui_argon2_verify(hash, sizeof(hash),
password, password_len,
salt, sizeof(salt),
3, 4096, 1);
PBKDF2
uint8_t salt[16];
metamui_random_bytes(salt, sizeof(salt));
uint8_t derived_key[32];
metamui_pbkdf2_sha256(derived_key, sizeof(derived_key),
password, password_len,
salt, sizeof(salt),
100000); // iterations
HKDF
// Extract
uint8_t prk[METAMUI_SHA256_HASH_SIZE];
metamui_hkdf_sha256_extract(prk, salt, salt_len, ikm, ikm_len);
// Expand
uint8_t okm[42]; // Can be any length
metamui_hkdf_sha256_expand(okm, sizeof(okm), prk, info, info_len);
// Or one-shot
metamui_hkdf_sha256(okm, sizeof(okm),
ikm, ikm_len,
salt, salt_len,
info, info_len);
Utility Functions
Random Number Generation
// Generate random bytes
uint8_t random_data[32];
metamui_random_bytes(random_data, sizeof(random_data));
// Generate random 32-bit integer
uint32_t random_int = metamui_random_u32();
// Generate random number in range [0, max)
uint32_t random_range = metamui_random_uniform(max);
Constant-Time Operations
// Constant-time comparison
int equal = metamui_ct_compare(a, b, len);
// Constant-time conditional copy
metamui_ct_select(dest, src1, src2, len, condition);
// Constant-time memory clear
metamui_secure_zero(sensitive_data, sizeof(sensitive_data));
Encoding/Decoding
// Hex encoding
char hex[65]; // 32 bytes = 64 hex chars + null
metamui_to_hex(hex, data, 32);
// Hex decoding
uint8_t decoded[32];
metamui_from_hex(decoded, hex, 64);
// Base64 encoding
char base64[45]; // 32 bytes = 44 base64 chars + null
size_t base64_len;
metamui_to_base64(base64, &base64_len, data, 32);
// Base64 decoding
uint8_t decoded_b64[32];
size_t decoded_len;
metamui_from_base64(decoded_b64, &decoded_len, base64, base64_len);
Build System Integration
CMake
find_package(MetaMUICrypto REQUIRED)
target_link_libraries(myapp MetaMUI::Crypto)
Makefile
CFLAGS += $(shell pkg-config --cflags metamui-crypto)
LDFLAGS += $(shell pkg-config --libs metamui-crypto)
myapp: myapp.c
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
Autotools
# In configure.ac
PKG_CHECK_MODULES([METAMUI], [metamui-crypto >= 3.0.0])
# In Makefile.am
myapp_CFLAGS = $(METAMUI_CFLAGS)
myapp_LDADD = $(METAMUI_LIBS)
Performance Optimization
SIMD Support
// Check for SIMD availability
if (metamui_has_avx2()) {
// Use AVX2-optimized functions
metamui_blake3_hash_avx2(hash, data, data_len);
} else if (metamui_has_sse41()) {
// Use SSE4.1-optimized functions
metamui_blake3_hash_sse41(hash, data, data_len);
} else {
// Fall back to portable implementation
metamui_blake3_hash(hash, data, data_len);
}
Batch Operations
// Batch signature verification
metamui_ed25519_batch_verify_result_t results[100];
metamui_ed25519_batch_verify(results,
signatures, messages, message_lens,
public_keys, count);
for (int i = 0; i < count; i++) {
if (results[i] == METAMUI_BATCH_VALID) {
// Signature i is valid
}
}
Memory Pools
// Create memory pool for repeated allocations
metamui_pool_t *pool = metamui_pool_create(1024 * 1024); // 1MB pool
// Allocate from pool (fast, no fragmentation)
void *buffer1 = metamui_pool_alloc(pool, 256);
void *buffer2 = metamui_pool_alloc(pool, 512);
// Reset pool (frees all allocations at once)
metamui_pool_reset(pool);
// Destroy pool when done
metamui_pool_destroy(pool);
Security Notes
Best Practices
- Always check return values - Crypto operations can fail
- Use secure random sources - Never use
rand()for crypto - Clear sensitive memory - Use
metamui_secure_zero() - Validate input sizes - Check buffer bounds
- Use constant-time operations - For secret-dependent code
Common Pitfalls
// DON'T: Compare secrets with memcmp (not constant-time)
if (memcmp(computed_mac, expected_mac, 32) == 0) { // BAD!
// ...
}
// DO: Use constant-time comparison
if (metamui_ct_compare(computed_mac, expected_mac, 32)) { // GOOD!
// ...
}
// DON'T: Leave secrets in memory
uint8_t secret_key[32];
// ... use key ...
// Key remains in memory! // BAD!
// DO: Clear sensitive data
uint8_t secret_key[32];
// ... use key ...
metamui_secure_zero(secret_key, sizeof(secret_key)); // GOOD!
Platform Security Features
// Enable platform security features
metamui_enable_secure_mode();
// Check if running in secure environment
if (metamui_is_secure_environment()) {
// Use hardware security features
metamui_use_hardware_rng();
metamui_use_hardware_aes();
}
Examples
Complete Encryption Example
#include <metamui/crypto.h>
#include <stdio.h>
#include <string.h>
int encrypt_file(const char *input_file, const char *output_file,
const uint8_t *key) {
FILE *in = fopen(input_file, "rb");
FILE *out = fopen(output_file, "wb");
if (!in || !out) {
return -1;
}
// Generate random nonce
uint8_t nonce[METAMUI_CHACHA20_POLY1305_NONCE_SIZE];
metamui_random_bytes(nonce, sizeof(nonce));
// Write nonce to output
fwrite(nonce, 1, sizeof(nonce), out);
// Initialize encryption context
metamui_chacha20_poly1305_ctx_t ctx;
metamui_chacha20_poly1305_init(&ctx, key, nonce);
// Encrypt file in chunks
uint8_t buffer[4096];
size_t bytes_read;
while ((bytes_read = fread(buffer, 1, sizeof(buffer), in)) > 0) {
metamui_chacha20_poly1305_update(&ctx, buffer, bytes_read);
fwrite(buffer, 1, bytes_read, out);
}
// Write authentication tag
uint8_t tag[METAMUI_POLY1305_TAG_SIZE];
metamui_chacha20_poly1305_final(&ctx, tag);
fwrite(tag, 1, sizeof(tag), out);
fclose(in);
fclose(out);
return 0;
}
Secure Communication Protocol
typedef struct {
metamui_mlkem768_keypair_t kem_keypair;
metamui_ed25519_keypair_t sign_keypair;
} identity_t;
int establish_secure_channel(identity_t *alice, identity_t *bob,
uint8_t *shared_key) {
// Alice: Create ephemeral shared secret
uint8_t ciphertext[METAMUI_MLKEM768_CIPHERTEXT_SIZE];
uint8_t alice_secret[METAMUI_MLKEM768_SHARED_SECRET_SIZE];
metamui_mlkem768_encapsulate(ciphertext, alice_secret,
bob->kem_keypair.public_key);
// Alice: Sign the ciphertext
uint8_t signature[METAMUI_ED25519_SIGNATURE_SIZE];
metamui_ed25519_sign(signature, ciphertext, sizeof(ciphertext),
alice->sign_keypair.private_key);
// Bob: Verify signature
if (!metamui_ed25519_verify(signature, ciphertext, sizeof(ciphertext),
alice->sign_keypair.public_key)) {
return -1; // Authentication failed
}
// Bob: Decapsulate to get shared secret
uint8_t bob_secret[METAMUI_MLKEM768_SHARED_SECRET_SIZE];
metamui_mlkem768_decapsulate(bob_secret, ciphertext,
bob->kem_keypair.private_key);
// Derive session key from shared secret
metamui_hkdf_sha256(shared_key, 32,
bob_secret, sizeof(bob_secret),
NULL, 0,
(uint8_t*)"session", 7);
// Clear secrets
metamui_secure_zero(alice_secret, sizeof(alice_secret));
metamui_secure_zero(bob_secret, sizeof(bob_secret));
return 0;
}