Rename module to pyaegis, implement build with zig.
This commit is contained in:
@@ -1,467 +0,0 @@
|
|||||||
"""Dynamic loader for libaegis using CFFI (ABI mode).
|
|
||||||
|
|
||||||
This module avoids compiling any C shim. It loads the shared library built by
|
|
||||||
the project (e.g., build-shared/libaegis.so) or a system-installed libaegis.
|
|
||||||
|
|
||||||
Environment variables:
|
|
||||||
- AEGIS_LIB_PATH: full path to the libaegis shared library to load
|
|
||||||
- AEGIS_LIB_DIR: directory containing the shared library (libaegis.so)
|
|
||||||
|
|
||||||
Exports:
|
|
||||||
- ffi: a cffi.FFI instance with the libaegis API declared
|
|
||||||
- lib: the loaded libaegis shared library (ffi.dlopen)
|
|
||||||
- libc: the C runtime (for posix_memalign/free on POSIX)
|
|
||||||
- alloc_aligned(size, alignment): return (void*) pointer with requested alignment
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
from cffi import FFI
|
|
||||||
|
|
||||||
try:
|
|
||||||
# ctypes is only used to resolve libc reliably across platforms
|
|
||||||
import ctypes.util as _ctypes_util # type: ignore
|
|
||||||
except Exception: # pragma: no cover - very unlikely to happen
|
|
||||||
_ctypes_util = None # type: ignore[assignment]
|
|
||||||
|
|
||||||
|
|
||||||
ffi = FFI()
|
|
||||||
|
|
||||||
# Public API from headers (aegis.h and all aegis variant headers). Keep it macro-free.
|
|
||||||
ffi.cdef(
|
|
||||||
r"""
|
|
||||||
typedef unsigned char uint8_t;
|
|
||||||
typedef unsigned long size_t;
|
|
||||||
|
|
||||||
/* aegis.h */
|
|
||||||
int aegis_init(void);
|
|
||||||
int aegis_verify_16(const uint8_t *x, const uint8_t *y);
|
|
||||||
int aegis_verify_32(const uint8_t *x, const uint8_t *y);
|
|
||||||
|
|
||||||
/* aegis128l.h */
|
|
||||||
typedef struct {
|
|
||||||
/* CRYPTO_ALIGN(32) */ uint8_t opaque[256];
|
|
||||||
} aegis128l_state;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
/* CRYPTO_ALIGN(32) */ uint8_t opaque[384];
|
|
||||||
} aegis128l_mac_state;
|
|
||||||
|
|
||||||
size_t aegis128l_keybytes(void);
|
|
||||||
size_t aegis128l_npubbytes(void);
|
|
||||||
size_t aegis128l_abytes_min(void);
|
|
||||||
size_t aegis128l_abytes_max(void);
|
|
||||||
size_t aegis128l_tailbytes_max(void);
|
|
||||||
|
|
||||||
int aegis128l_encrypt_detached(uint8_t *c, uint8_t *mac, size_t maclen, const uint8_t *m,
|
|
||||||
size_t mlen, const uint8_t *ad, size_t adlen, const uint8_t *npub,
|
|
||||||
const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis128l_decrypt_detached(uint8_t *m, const uint8_t *c, size_t clen, const uint8_t *mac,
|
|
||||||
size_t maclen, const uint8_t *ad, size_t adlen, const uint8_t *npub,
|
|
||||||
const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis128l_encrypt(uint8_t *c, size_t maclen, const uint8_t *m, size_t mlen, const uint8_t *ad,
|
|
||||||
size_t adlen, const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis128l_decrypt(uint8_t *m, const uint8_t *c, size_t clen, size_t maclen, const uint8_t *ad,
|
|
||||||
size_t adlen, const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
void aegis128l_state_init(aegis128l_state *st_, const uint8_t *ad, size_t adlen,
|
|
||||||
const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis128l_state_encrypt_update(aegis128l_state *st_, uint8_t *c, size_t clen_max,
|
|
||||||
size_t *written, const uint8_t *m, size_t mlen);
|
|
||||||
|
|
||||||
int aegis128l_state_encrypt_detached_final(aegis128l_state *st_, uint8_t *c, size_t clen_max,
|
|
||||||
size_t *written, uint8_t *mac, size_t maclen);
|
|
||||||
|
|
||||||
int aegis128l_state_encrypt_final(aegis128l_state *st_, uint8_t *c, size_t clen_max,
|
|
||||||
size_t *written, size_t maclen);
|
|
||||||
|
|
||||||
int aegis128l_state_decrypt_detached_update(aegis128l_state *st_, uint8_t *m, size_t mlen_max,
|
|
||||||
size_t *written, const uint8_t *c, size_t clen);
|
|
||||||
|
|
||||||
int aegis128l_state_decrypt_detached_final(aegis128l_state *st_, uint8_t *m, size_t mlen_max,
|
|
||||||
size_t *written, const uint8_t *mac, size_t maclen);
|
|
||||||
|
|
||||||
void aegis128l_stream(uint8_t *out, size_t len, const uint8_t *npub, const uint8_t *k);
|
|
||||||
void aegis128l_encrypt_unauthenticated(uint8_t *c, const uint8_t *m, size_t mlen,
|
|
||||||
const uint8_t *npub, const uint8_t *k);
|
|
||||||
void aegis128l_decrypt_unauthenticated(uint8_t *m, const uint8_t *c, size_t clen,
|
|
||||||
const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
void aegis128l_mac_init(aegis128l_mac_state *st_, const uint8_t *k, const uint8_t *npub);
|
|
||||||
int aegis128l_mac_update(aegis128l_mac_state *st_, const uint8_t *m, size_t mlen);
|
|
||||||
int aegis128l_mac_final(aegis128l_mac_state *st_, uint8_t *mac, size_t maclen);
|
|
||||||
int aegis128l_mac_verify(aegis128l_mac_state *st_, const uint8_t *mac, size_t maclen);
|
|
||||||
void aegis128l_mac_reset(aegis128l_mac_state *st_);
|
|
||||||
void aegis128l_mac_state_clone(aegis128l_mac_state *dst, const aegis128l_mac_state *src);
|
|
||||||
|
|
||||||
/* aegis128x2.h */
|
|
||||||
typedef struct {
|
|
||||||
/* CRYPTO_ALIGN(64) */ uint8_t opaque[448];
|
|
||||||
} aegis128x2_state;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
/* CRYPTO_ALIGN(64) */ uint8_t opaque[704];
|
|
||||||
} aegis128x2_mac_state;
|
|
||||||
|
|
||||||
size_t aegis128x2_keybytes(void);
|
|
||||||
size_t aegis128x2_npubbytes(void);
|
|
||||||
size_t aegis128x2_abytes_min(void);
|
|
||||||
size_t aegis128x2_abytes_max(void);
|
|
||||||
size_t aegis128x2_tailbytes_max(void);
|
|
||||||
|
|
||||||
int aegis128x2_encrypt_detached(uint8_t *c, uint8_t *mac, size_t maclen, const uint8_t *m,
|
|
||||||
size_t mlen, const uint8_t *ad, size_t adlen, const uint8_t *npub,
|
|
||||||
const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis128x2_decrypt_detached(uint8_t *m, const uint8_t *c, size_t clen, const uint8_t *mac,
|
|
||||||
size_t maclen, const uint8_t *ad, size_t adlen, const uint8_t *npub,
|
|
||||||
const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis128x2_encrypt(uint8_t *c, size_t maclen, const uint8_t *m, size_t mlen, const uint8_t *ad,
|
|
||||||
size_t adlen, const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis128x2_decrypt(uint8_t *m, const uint8_t *c, size_t clen, size_t maclen, const uint8_t *ad,
|
|
||||||
size_t adlen, const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
void aegis128x2_state_init(aegis128x2_state *st_, const uint8_t *ad, size_t adlen,
|
|
||||||
const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis128x2_state_encrypt_update(aegis128x2_state *st_, uint8_t *c, size_t clen_max,
|
|
||||||
size_t *written, const uint8_t *m, size_t mlen);
|
|
||||||
|
|
||||||
int aegis128x2_state_encrypt_detached_final(aegis128x2_state *st_, uint8_t *c, size_t clen_max,
|
|
||||||
size_t *written, uint8_t *mac, size_t maclen);
|
|
||||||
|
|
||||||
int aegis128x2_state_encrypt_final(aegis128x2_state *st_, uint8_t *c, size_t clen_max,
|
|
||||||
size_t *written, size_t maclen);
|
|
||||||
|
|
||||||
int aegis128x2_state_decrypt_detached_update(aegis128x2_state *st_, uint8_t *m, size_t mlen_max,
|
|
||||||
size_t *written, const uint8_t *c, size_t clen);
|
|
||||||
|
|
||||||
int aegis128x2_state_decrypt_detached_final(aegis128x2_state *st_, uint8_t *m, size_t mlen_max,
|
|
||||||
size_t *written, const uint8_t *mac, size_t maclen);
|
|
||||||
|
|
||||||
void aegis128x2_stream(uint8_t *out, size_t len, const uint8_t *npub, const uint8_t *k);
|
|
||||||
void aegis128x2_encrypt_unauthenticated(uint8_t *c, const uint8_t *m, size_t mlen,
|
|
||||||
const uint8_t *npub, const uint8_t *k);
|
|
||||||
void aegis128x2_decrypt_unauthenticated(uint8_t *m, const uint8_t *c, size_t clen,
|
|
||||||
const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
void aegis128x2_mac_init(aegis128x2_mac_state *st_, const uint8_t *k, const uint8_t *npub);
|
|
||||||
int aegis128x2_mac_update(aegis128x2_mac_state *st_, const uint8_t *m, size_t mlen);
|
|
||||||
int aegis128x2_mac_final(aegis128x2_mac_state *st_, uint8_t *mac, size_t maclen);
|
|
||||||
int aegis128x2_mac_verify(aegis128x2_mac_state *st_, const uint8_t *mac, size_t maclen);
|
|
||||||
void aegis128x2_mac_reset(aegis128x2_mac_state *st_);
|
|
||||||
void aegis128x2_mac_state_clone(aegis128x2_mac_state *dst, const aegis128x2_mac_state *src);
|
|
||||||
|
|
||||||
/* aegis128x4.h */
|
|
||||||
typedef struct {
|
|
||||||
/* CRYPTO_ALIGN(64) */ uint8_t opaque[832];
|
|
||||||
} aegis128x4_state;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
/* CRYPTO_ALIGN(64) */ uint8_t opaque[1344];
|
|
||||||
} aegis128x4_mac_state;
|
|
||||||
|
|
||||||
size_t aegis128x4_keybytes(void);
|
|
||||||
size_t aegis128x4_npubbytes(void);
|
|
||||||
size_t aegis128x4_abytes_min(void);
|
|
||||||
size_t aegis128x4_abytes_max(void);
|
|
||||||
size_t aegis128x4_tailbytes_max(void);
|
|
||||||
|
|
||||||
int aegis128x4_encrypt_detached(uint8_t *c, uint8_t *mac, size_t maclen, const uint8_t *m,
|
|
||||||
size_t mlen, const uint8_t *ad, size_t adlen, const uint8_t *npub,
|
|
||||||
const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis128x4_decrypt_detached(uint8_t *m, const uint8_t *c, size_t clen, const uint8_t *mac,
|
|
||||||
size_t maclen, const uint8_t *ad, size_t adlen, const uint8_t *npub,
|
|
||||||
const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis128x4_encrypt(uint8_t *c, size_t maclen, const uint8_t *m, size_t mlen, const uint8_t *ad,
|
|
||||||
size_t adlen, const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis128x4_decrypt(uint8_t *m, const uint8_t *c, size_t clen, size_t maclen, const uint8_t *ad,
|
|
||||||
size_t adlen, const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
void aegis128x4_state_init(aegis128x4_state *st_, const uint8_t *ad, size_t adlen,
|
|
||||||
const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis128x4_state_encrypt_update(aegis128x4_state *st_, uint8_t *c, size_t clen_max,
|
|
||||||
size_t *written, const uint8_t *m, size_t mlen);
|
|
||||||
|
|
||||||
int aegis128x4_state_encrypt_detached_final(aegis128x4_state *st_, uint8_t *c, size_t clen_max,
|
|
||||||
size_t *written, uint8_t *mac, size_t maclen);
|
|
||||||
|
|
||||||
int aegis128x4_state_encrypt_final(aegis128x4_state *st_, uint8_t *c, size_t clen_max,
|
|
||||||
size_t *written, size_t maclen);
|
|
||||||
|
|
||||||
int aegis128x4_state_decrypt_detached_update(aegis128x4_state *st_, uint8_t *m, size_t mlen_max,
|
|
||||||
size_t *written, const uint8_t *c, size_t clen);
|
|
||||||
|
|
||||||
int aegis128x4_state_decrypt_detached_final(aegis128x4_state *st_, uint8_t *m, size_t mlen_max,
|
|
||||||
size_t *written, const uint8_t *mac, size_t maclen);
|
|
||||||
|
|
||||||
void aegis128x4_stream(uint8_t *out, size_t len, const uint8_t *npub, const uint8_t *k);
|
|
||||||
void aegis128x4_encrypt_unauthenticated(uint8_t *c, const uint8_t *m, size_t mlen,
|
|
||||||
const uint8_t *npub, const uint8_t *k);
|
|
||||||
void aegis128x4_decrypt_unauthenticated(uint8_t *m, const uint8_t *c, size_t clen,
|
|
||||||
const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
void aegis128x4_mac_init(aegis128x4_mac_state *st_, const uint8_t *k, const uint8_t *npub);
|
|
||||||
int aegis128x4_mac_update(aegis128x4_mac_state *st_, const uint8_t *m, size_t mlen);
|
|
||||||
int aegis128x4_mac_final(aegis128x4_mac_state *st_, uint8_t *mac, size_t maclen);
|
|
||||||
int aegis128x4_mac_verify(aegis128x4_mac_state *st_, const uint8_t *mac, size_t maclen);
|
|
||||||
void aegis128x4_mac_reset(aegis128x4_mac_state *st_);
|
|
||||||
void aegis128x4_mac_state_clone(aegis128x4_mac_state *dst, const aegis128x4_mac_state *src);
|
|
||||||
|
|
||||||
/* aegis256.h */
|
|
||||||
typedef struct {
|
|
||||||
/* CRYPTO_ALIGN(16) */ uint8_t opaque[192];
|
|
||||||
} aegis256_state;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
/* CRYPTO_ALIGN(16) */ uint8_t opaque[288];
|
|
||||||
} aegis256_mac_state;
|
|
||||||
|
|
||||||
size_t aegis256_keybytes(void);
|
|
||||||
size_t aegis256_npubbytes(void);
|
|
||||||
size_t aegis256_abytes_min(void);
|
|
||||||
size_t aegis256_abytes_max(void);
|
|
||||||
size_t aegis256_tailbytes_max(void);
|
|
||||||
|
|
||||||
int aegis256_encrypt_detached(uint8_t *c, uint8_t *mac, size_t maclen, const uint8_t *m,
|
|
||||||
size_t mlen, const uint8_t *ad, size_t adlen, const uint8_t *npub,
|
|
||||||
const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis256_decrypt_detached(uint8_t *m, const uint8_t *c, size_t clen, const uint8_t *mac,
|
|
||||||
size_t maclen, const uint8_t *ad, size_t adlen, const uint8_t *npub,
|
|
||||||
const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis256_encrypt(uint8_t *c, size_t maclen, const uint8_t *m, size_t mlen, const uint8_t *ad,
|
|
||||||
size_t adlen, const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis256_decrypt(uint8_t *m, const uint8_t *c, size_t clen, size_t maclen, const uint8_t *ad,
|
|
||||||
size_t adlen, const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
void aegis256_state_init(aegis256_state *st_, const uint8_t *ad, size_t adlen,
|
|
||||||
const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis256_state_encrypt_update(aegis256_state *st_, uint8_t *c, size_t clen_max,
|
|
||||||
size_t *written, const uint8_t *m, size_t mlen);
|
|
||||||
|
|
||||||
int aegis256_state_encrypt_detached_final(aegis256_state *st_, uint8_t *c, size_t clen_max,
|
|
||||||
size_t *written, uint8_t *mac, size_t maclen);
|
|
||||||
|
|
||||||
int aegis256_state_encrypt_final(aegis256_state *st_, uint8_t *c, size_t clen_max,
|
|
||||||
size_t *written, size_t maclen);
|
|
||||||
|
|
||||||
int aegis256_state_decrypt_detached_update(aegis256_state *st_, uint8_t *m, size_t mlen_max,
|
|
||||||
size_t *written, const uint8_t *c, size_t clen);
|
|
||||||
|
|
||||||
int aegis256_state_decrypt_detached_final(aegis256_state *st_, uint8_t *m, size_t mlen_max,
|
|
||||||
size_t *written, const uint8_t *mac, size_t maclen);
|
|
||||||
|
|
||||||
void aegis256_stream(uint8_t *out, size_t len, const uint8_t *npub, const uint8_t *k);
|
|
||||||
void aegis256_encrypt_unauthenticated(uint8_t *c, const uint8_t *m, size_t mlen,
|
|
||||||
const uint8_t *npub, const uint8_t *k);
|
|
||||||
void aegis256_decrypt_unauthenticated(uint8_t *m, const uint8_t *c, size_t clen,
|
|
||||||
const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
void aegis256_mac_init(aegis256_mac_state *st_, const uint8_t *k, const uint8_t *npub);
|
|
||||||
int aegis256_mac_update(aegis256_mac_state *st_, const uint8_t *m, size_t mlen);
|
|
||||||
int aegis256_mac_final(aegis256_mac_state *st_, uint8_t *mac, size_t maclen);
|
|
||||||
int aegis256_mac_verify(aegis256_mac_state *st_, const uint8_t *mac, size_t maclen);
|
|
||||||
void aegis256_mac_reset(aegis256_mac_state *st_);
|
|
||||||
void aegis256_mac_state_clone(aegis256_mac_state *dst, const aegis256_mac_state *src);
|
|
||||||
|
|
||||||
/* aegis256x2.h */
|
|
||||||
typedef struct {
|
|
||||||
/* CRYPTO_ALIGN(32) */ uint8_t opaque[320];
|
|
||||||
} aegis256x2_state;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
/* CRYPTO_ALIGN(32) */ uint8_t opaque[512];
|
|
||||||
} aegis256x2_mac_state;
|
|
||||||
|
|
||||||
size_t aegis256x2_keybytes(void);
|
|
||||||
size_t aegis256x2_npubbytes(void);
|
|
||||||
size_t aegis256x2_abytes_min(void);
|
|
||||||
size_t aegis256x2_abytes_max(void);
|
|
||||||
size_t aegis256x2_tailbytes_max(void);
|
|
||||||
|
|
||||||
int aegis256x2_encrypt_detached(uint8_t *c, uint8_t *mac, size_t maclen, const uint8_t *m,
|
|
||||||
size_t mlen, const uint8_t *ad, size_t adlen, const uint8_t *npub,
|
|
||||||
const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis256x2_decrypt_detached(uint8_t *m, const uint8_t *c, size_t clen, const uint8_t *mac,
|
|
||||||
size_t maclen, const uint8_t *ad, size_t adlen, const uint8_t *npub,
|
|
||||||
const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis256x2_encrypt(uint8_t *c, size_t maclen, const uint8_t *m, size_t mlen, const uint8_t *ad,
|
|
||||||
size_t adlen, const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis256x2_decrypt(uint8_t *m, const uint8_t *c, size_t clen, size_t maclen, const uint8_t *ad,
|
|
||||||
size_t adlen, const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
void aegis256x2_state_init(aegis256x2_state *st_, const uint8_t *ad, size_t adlen,
|
|
||||||
const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis256x2_state_encrypt_update(aegis256x2_state *st_, uint8_t *c, size_t clen_max,
|
|
||||||
size_t *written, const uint8_t *m, size_t mlen);
|
|
||||||
|
|
||||||
int aegis256x2_state_encrypt_detached_final(aegis256x2_state *st_, uint8_t *c, size_t clen_max,
|
|
||||||
size_t *written, uint8_t *mac, size_t maclen);
|
|
||||||
|
|
||||||
int aegis256x2_state_encrypt_final(aegis256x2_state *st_, uint8_t *c, size_t clen_max,
|
|
||||||
size_t *written, size_t maclen);
|
|
||||||
|
|
||||||
int aegis256x2_state_decrypt_detached_update(aegis256x2_state *st_, uint8_t *m, size_t mlen_max,
|
|
||||||
size_t *written, const uint8_t *c, size_t clen);
|
|
||||||
|
|
||||||
int aegis256x2_state_decrypt_detached_final(aegis256x2_state *st_, uint8_t *m, size_t mlen_max,
|
|
||||||
size_t *written, const uint8_t *mac, size_t maclen);
|
|
||||||
|
|
||||||
void aegis256x2_stream(uint8_t *out, size_t len, const uint8_t *npub, const uint8_t *k);
|
|
||||||
void aegis256x2_encrypt_unauthenticated(uint8_t *c, const uint8_t *m, size_t mlen,
|
|
||||||
const uint8_t *npub, const uint8_t *k);
|
|
||||||
void aegis256x2_decrypt_unauthenticated(uint8_t *m, const uint8_t *c, size_t clen,
|
|
||||||
const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
void aegis256x2_mac_init(aegis256x2_mac_state *st_, const uint8_t *k, const uint8_t *npub);
|
|
||||||
int aegis256x2_mac_update(aegis256x2_mac_state *st_, const uint8_t *m, size_t mlen);
|
|
||||||
int aegis256x2_mac_final(aegis256x2_mac_state *st_, uint8_t *mac, size_t maclen);
|
|
||||||
int aegis256x2_mac_verify(aegis256x2_mac_state *st_, const uint8_t *mac, size_t maclen);
|
|
||||||
void aegis256x2_mac_reset(aegis256x2_mac_state *st_);
|
|
||||||
void aegis256x2_mac_state_clone(aegis256x2_mac_state *dst, const aegis256x2_mac_state *src);
|
|
||||||
|
|
||||||
/* aegis256x4.h */
|
|
||||||
typedef struct {
|
|
||||||
/* CRYPTO_ALIGN(64) */ uint8_t opaque[576];
|
|
||||||
} aegis256x4_state;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
/* CRYPTO_ALIGN(64) */ uint8_t opaque[960];
|
|
||||||
} aegis256x4_mac_state;
|
|
||||||
|
|
||||||
size_t aegis256x4_keybytes(void);
|
|
||||||
size_t aegis256x4_npubbytes(void);
|
|
||||||
size_t aegis256x4_abytes_min(void);
|
|
||||||
size_t aegis256x4_abytes_max(void);
|
|
||||||
size_t aegis256x4_tailbytes_max(void);
|
|
||||||
|
|
||||||
int aegis256x4_encrypt_detached(uint8_t *c, uint8_t *mac, size_t maclen, const uint8_t *m,
|
|
||||||
size_t mlen, const uint8_t *ad, size_t adlen, const uint8_t *npub,
|
|
||||||
const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis256x4_decrypt_detached(uint8_t *m, const uint8_t *c, size_t clen, const uint8_t *mac,
|
|
||||||
size_t maclen, const uint8_t *ad, size_t adlen, const uint8_t *npub,
|
|
||||||
const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis256x4_encrypt(uint8_t *c, size_t maclen, const uint8_t *m, size_t mlen, const uint8_t *ad,
|
|
||||||
size_t adlen, const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis256x4_decrypt(uint8_t *m, const uint8_t *c, size_t clen, size_t maclen, const uint8_t *ad,
|
|
||||||
size_t adlen, const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
void aegis256x4_state_init(aegis256x4_state *st_, const uint8_t *ad, size_t adlen,
|
|
||||||
const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
int aegis256x4_state_encrypt_update(aegis256x4_state *st_, uint8_t *c, size_t clen_max,
|
|
||||||
size_t *written, const uint8_t *m, size_t mlen);
|
|
||||||
|
|
||||||
int aegis256x4_state_encrypt_detached_final(aegis256x4_state *st_, uint8_t *c, size_t clen_max,
|
|
||||||
size_t *written, uint8_t *mac, size_t maclen);
|
|
||||||
|
|
||||||
int aegis256x4_state_encrypt_final(aegis256x4_state *st_, uint8_t *c, size_t clen_max,
|
|
||||||
size_t *written, size_t maclen);
|
|
||||||
|
|
||||||
int aegis256x4_state_decrypt_detached_update(aegis256x4_state *st_, uint8_t *m, size_t mlen_max,
|
|
||||||
size_t *written, const uint8_t *c, size_t clen);
|
|
||||||
|
|
||||||
int aegis256x4_state_decrypt_detached_final(aegis256x4_state *st_, uint8_t *m, size_t mlen_max,
|
|
||||||
size_t *written, const uint8_t *mac, size_t maclen);
|
|
||||||
|
|
||||||
void aegis256x4_stream(uint8_t *out, size_t len, const uint8_t *npub, const uint8_t *k);
|
|
||||||
void aegis256x4_encrypt_unauthenticated(uint8_t *c, const uint8_t *m, size_t mlen,
|
|
||||||
const uint8_t *npub, const uint8_t *k);
|
|
||||||
void aegis256x4_decrypt_unauthenticated(uint8_t *m, const uint8_t *c, size_t clen,
|
|
||||||
const uint8_t *npub, const uint8_t *k);
|
|
||||||
|
|
||||||
void aegis256x4_mac_init(aegis256x4_mac_state *st_, const uint8_t *k, const uint8_t *npub);
|
|
||||||
int aegis256x4_mac_update(aegis256x4_mac_state *st_, const uint8_t *m, size_t mlen);
|
|
||||||
int aegis256x4_mac_final(aegis256x4_mac_state *st_, uint8_t *mac, size_t maclen);
|
|
||||||
int aegis256x4_mac_verify(aegis256x4_mac_state *st_, const uint8_t *mac, size_t maclen);
|
|
||||||
void aegis256x4_mac_reset(aegis256x4_mac_state *st_);
|
|
||||||
void aegis256x4_mac_state_clone(aegis256x4_mac_state *dst, const aegis256x4_mac_state *src);
|
|
||||||
|
|
||||||
/* libc bits for aligned allocation on POSIX */
|
|
||||||
int posix_memalign(void **memptr, size_t alignment, size_t size);
|
|
||||||
void free(void *ptr);
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _platform_lib_name() -> str:
|
|
||||||
if sys.platform.startswith("linux"):
|
|
||||||
return "libaegis.so"
|
|
||||||
if sys.platform == "darwin":
|
|
||||||
return "libaegis.dylib"
|
|
||||||
if os.name == "nt":
|
|
||||||
return "aegis.dll"
|
|
||||||
return "libaegis.so"
|
|
||||||
|
|
||||||
|
|
||||||
def _load_libaegis():
|
|
||||||
# Let the dynamic loader search system paths
|
|
||||||
try:
|
|
||||||
lib = ffi.dlopen(_platform_lib_name())
|
|
||||||
return lib
|
|
||||||
except Exception as e:
|
|
||||||
hint = "Install libaegis system-wide."
|
|
||||||
raise OSError(f"Could not load libaegis: {e}\n{hint}")
|
|
||||||
|
|
||||||
|
|
||||||
def _load_libc():
|
|
||||||
# Use ctypes.util to find a usable libc name; fallback to None-dlopen on POSIX
|
|
||||||
if _ctypes_util is not None:
|
|
||||||
libc_name = _ctypes_util.find_library("c") # type: ignore[attr-defined]
|
|
||||||
if libc_name:
|
|
||||||
try:
|
|
||||||
return ffi.dlopen(libc_name)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
# Fallback: try process globals (works on many Unix platforms)
|
|
||||||
try:
|
|
||||||
return ffi.dlopen(None)
|
|
||||||
except Exception as e:
|
|
||||||
raise OSError(f"Unable to load libc for aligned allocation: {e}")
|
|
||||||
|
|
||||||
|
|
||||||
lib: Any = _load_libaegis()
|
|
||||||
libc: Any = _load_libc()
|
|
||||||
|
|
||||||
# Initialize CPU feature selection (recommended by the library)
|
|
||||||
try:
|
|
||||||
lib.aegis_init()
|
|
||||||
except Exception:
|
|
||||||
# Non-fatal; functions will still work, maybe slower
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def alloc_aligned(size: int, alignment: int = 64):
|
|
||||||
"""Allocate aligned memory via posix_memalign(); returns a void* cdata.
|
|
||||||
|
|
||||||
The returned pointer must be freed with libc.free(). Attach a GC finalizer
|
|
||||||
at call sites using ffi.gc(ptr, libc.free) after casting to the target type.
|
|
||||||
"""
|
|
||||||
memptr = ffi.new("void **")
|
|
||||||
rc = libc.posix_memalign(memptr, alignment, size)
|
|
||||||
if rc != 0 or memptr[0] == ffi.NULL:
|
|
||||||
raise MemoryError(f"posix_memalign({alignment}, {size}) failed with rc={rc}")
|
|
||||||
return memptr[0]
|
|
||||||
@@ -10,7 +10,7 @@ Covers:
|
|||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from aegis import aegis256x4 as a
|
from pyaegis import aegis256x4 as a
|
||||||
|
|
||||||
|
|
||||||
def hx(b, limit: int | None = None) -> str:
|
def hx(b, limit: int | None = None) -> str:
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ Output format and throughput units mirror the Zig benchmark (Mb/s).
|
|||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from aegis import aegis128l, aegis128x2, aegis128x4, aegis256, aegis256x2, aegis256x4
|
from pyaegis import aegis128l, aegis128x2, aegis128x4, aegis256, aegis256x2, aegis256x4
|
||||||
|
|
||||||
MSG_LEN = 16384000 # 16 MiB
|
MSG_LEN = 16384000 # 16 MiB
|
||||||
ITERATIONS = 100
|
ITERATIONS = 100
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
"""Dynamic loader for libaegis using CFFI (ABI mode).
|
||||||
|
|
||||||
|
This module loads the shared library bundled with the package.
|
||||||
|
|
||||||
|
Exports:
|
||||||
|
- ffi: a cffi.FFI instance with the libaegis API declared
|
||||||
|
- lib: the loaded libaegis shared library (ffi.dlopen)
|
||||||
|
- libc: the C runtime (for posix_memalign/free on POSIX)
|
||||||
|
- alloc_aligned(size, alignment): return (void*) pointer with requested alignment
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from cffi import FFI
|
||||||
|
|
||||||
|
ffi = FFI()
|
||||||
|
|
||||||
|
# Load CFFI cdef declarations from text file
|
||||||
|
cdef_path = os.path.join(os.path.dirname(__file__), "build", "aegis_cdef.h")
|
||||||
|
with open(cdef_path, "r", encoding="utf-8") as f:
|
||||||
|
cdef_content = f.read()
|
||||||
|
ffi.cdef(cdef_content)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# ctypes is only used to resolve libc reliably across platforms
|
||||||
|
import ctypes.util as _ctypes_util # type: ignore
|
||||||
|
except Exception: # pragma: no cover - very unlikely to happen
|
||||||
|
_ctypes_util = None # type: ignore[assignment]
|
||||||
|
|
||||||
|
|
||||||
|
def _platform_lib_name() -> str:
|
||||||
|
if sys.platform == "darwin":
|
||||||
|
return "libaegis.dylib"
|
||||||
|
if os.name == "nt":
|
||||||
|
return "aegis.dll"
|
||||||
|
return "libaegis.so"
|
||||||
|
|
||||||
|
|
||||||
|
def _load_libaegis():
|
||||||
|
pkg_dir = os.path.dirname(__file__)
|
||||||
|
candidate = os.path.join(pkg_dir, "build", _platform_lib_name())
|
||||||
|
if os.path.exists(candidate):
|
||||||
|
try:
|
||||||
|
return ffi.dlopen(candidate)
|
||||||
|
except Exception as e:
|
||||||
|
raise OSError(f"Failed to load libaegis from {candidate}: {e}")
|
||||||
|
else:
|
||||||
|
raise OSError(f"Could not find libaegis at {candidate}")
|
||||||
|
|
||||||
|
|
||||||
|
def _load_libc():
|
||||||
|
# Use ctypes.util to find a usable libc name; fallback to None-dlopen on POSIX
|
||||||
|
if _ctypes_util is not None:
|
||||||
|
libc_name = _ctypes_util.find_library("c") # type: ignore[attr-defined]
|
||||||
|
if libc_name:
|
||||||
|
try:
|
||||||
|
return ffi.dlopen(libc_name)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
# Fallback: try process globals (works on many Unix platforms)
|
||||||
|
try:
|
||||||
|
return ffi.dlopen(None)
|
||||||
|
except Exception as e:
|
||||||
|
raise OSError(f"Unable to load libc for aligned allocation: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
lib: Any = _load_libaegis()
|
||||||
|
libc: Any = _load_libc()
|
||||||
|
|
||||||
|
# Initialize CPU feature selection (recommended by the library)
|
||||||
|
try:
|
||||||
|
lib.aegis_init()
|
||||||
|
except Exception:
|
||||||
|
# Non-fatal; functions will still work, maybe slower
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def alloc_aligned(size: int, alignment: int = 64):
|
||||||
|
"""Allocate aligned memory via posix_memalign(); returns a void* cdata.
|
||||||
|
|
||||||
|
The returned pointer must be freed with libc.free(). Attach a GC finalizer
|
||||||
|
at call sites using ffi.gc(ptr, libc.free) after casting to the target type.
|
||||||
|
"""
|
||||||
|
memptr = ffi.new("void **")
|
||||||
|
rc = libc.posix_memalign(memptr, alignment, size)
|
||||||
|
if rc != 0 or memptr[0] == ffi.NULL:
|
||||||
|
raise MemoryError(f"posix_memalign({alignment}, {size}) failed with rc={rc}")
|
||||||
|
return memptr[0]
|
||||||
+11
-1
@@ -1,5 +1,5 @@
|
|||||||
[build-system]
|
[build-system]
|
||||||
requires = ["hatchling"]
|
requires = ["hatchling", "cffi>=2.0.0"]
|
||||||
build-backend = "hatchling.build"
|
build-backend = "hatchling.build"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
@@ -26,3 +26,13 @@ Homepage = "https://github.com/aegis-aead/libaegis"
|
|||||||
dev = [
|
dev = [
|
||||||
"pytest>=8.4.2",
|
"pytest>=8.4.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[tool.hatch.build.hooks.custom]
|
||||||
|
# Placeholder build hook for compiling libaegis with Zig during wheel builds.
|
||||||
|
# The actual Zig build is intentionally not executed yet.
|
||||||
|
path = "tools/build_hook.py"
|
||||||
|
|
||||||
|
[tool.hatch.build.targets.wheel]
|
||||||
|
# Ensure only the Python package is included by default; native artifacts
|
||||||
|
# will be added by the build hook once implemented.
|
||||||
|
packages = ["pyaegis"]
|
||||||
|
|||||||
+7
-12
@@ -2,13 +2,8 @@ import json
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from sys import stderr
|
from sys import stderr
|
||||||
|
|
||||||
import aegis.aegis128l
|
|
||||||
import aegis.aegis128x2
|
|
||||||
import aegis.aegis128x4
|
|
||||||
import aegis.aegis256
|
|
||||||
import aegis.aegis256x2
|
|
||||||
import aegis.aegis256x4
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from pyaegis import aegis128l, aegis128x2, aegis128x4, aegis256, aegis256x2, aegis256x4
|
||||||
|
|
||||||
from .util import random_split_bytes
|
from .util import random_split_bytes
|
||||||
|
|
||||||
@@ -20,12 +15,12 @@ def load_encryption_test_vectors():
|
|||||||
|
|
||||||
# Map filename to algorithm module
|
# Map filename to algorithm module
|
||||||
algorithm_files = {
|
algorithm_files = {
|
||||||
"aegis-128l-test-vectors.json": aegis.aegis128l,
|
"aegis-128l-test-vectors.json": aegis128l,
|
||||||
"aegis-128x2-test-vectors.json": aegis.aegis128x2,
|
"aegis-128x2-test-vectors.json": aegis128x2,
|
||||||
"aegis-128x4-test-vectors.json": aegis.aegis128x4,
|
"aegis-128x4-test-vectors.json": aegis128x4,
|
||||||
"aegis-256-test-vectors.json": aegis.aegis256,
|
"aegis-256-test-vectors.json": aegis256,
|
||||||
"aegis-256x2-test-vectors.json": aegis.aegis256x2,
|
"aegis-256x2-test-vectors.json": aegis256x2,
|
||||||
"aegis-256x4-test-vectors.json": aegis.aegis256x4,
|
"aegis-256x4-test-vectors.json": aegis256x4,
|
||||||
}
|
}
|
||||||
|
|
||||||
for filename, alg_module in algorithm_files.items():
|
for filename, alg_module in algorithm_files.items():
|
||||||
|
|||||||
+7
-12
@@ -1,13 +1,8 @@
|
|||||||
import json
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import aegis.aegis128l
|
|
||||||
import aegis.aegis128x2
|
|
||||||
import aegis.aegis128x4
|
|
||||||
import aegis.aegis256
|
|
||||||
import aegis.aegis256x2
|
|
||||||
import aegis.aegis256x4
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from pyaegis import aegis128l, aegis128x2, aegis128x4, aegis256, aegis256x2, aegis256x4
|
||||||
|
|
||||||
from .util import random_split_bytes
|
from .util import random_split_bytes
|
||||||
|
|
||||||
@@ -24,17 +19,17 @@ def load_mac_test_vectors():
|
|||||||
def get_algorithm_module(name):
|
def get_algorithm_module(name):
|
||||||
"""Map test vector name to algorithm module."""
|
"""Map test vector name to algorithm module."""
|
||||||
if "128L" in name:
|
if "128L" in name:
|
||||||
return aegis.aegis128l
|
return aegis128l
|
||||||
elif "128X2" in name:
|
elif "128X2" in name:
|
||||||
return aegis.aegis128x2
|
return aegis128x2
|
||||||
elif "128X4" in name:
|
elif "128X4" in name:
|
||||||
return aegis.aegis128x4
|
return aegis128x4
|
||||||
elif "256" in name and "256X2" not in name and "256X4" not in name:
|
elif "256" in name and "256X2" not in name and "256X4" not in name:
|
||||||
return aegis.aegis256
|
return aegis256
|
||||||
elif "256X2" in name:
|
elif "256X2" in name:
|
||||||
return aegis.aegis256x2
|
return aegis256x2
|
||||||
elif "256X4" in name:
|
elif "256X4" in name:
|
||||||
return aegis.aegis256x4
|
return aegis256x4
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Unknown algorithm in test vector name: {name}")
|
raise ValueError(f"Unknown algorithm in test vector name: {name}")
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
"""Hatch build hook for building dynamic libaegis library using Zig."""
|
||||||
|
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
||||||
|
|
||||||
|
|
||||||
|
class BuildHook(BuildHookInterface):
|
||||||
|
"""Build dynamic library with Zig and include in wheel."""
|
||||||
|
|
||||||
|
def initialize(self, version: str, build_data: dict) -> None:
|
||||||
|
"""Build library with Zig and add it to the wheel."""
|
||||||
|
if self.target_name != "wheel":
|
||||||
|
return
|
||||||
|
|
||||||
|
if not shutil.which("zig"):
|
||||||
|
raise RuntimeError("Zig compiler not found in PATH")
|
||||||
|
|
||||||
|
libaegis_dir = Path(self.root) / "libaegis"
|
||||||
|
original_build_zig = libaegis_dir / "build.zig"
|
||||||
|
if not original_build_zig.exists():
|
||||||
|
raise RuntimeError(f"libaegis source not found at {libaegis_dir}")
|
||||||
|
|
||||||
|
# Prepare a temporary build directory (avoid touching original files)
|
||||||
|
build_dir = Path.cwd() / "libaegis-build"
|
||||||
|
build_dir.mkdir(exist_ok=True)
|
||||||
|
build_zig = build_dir / "build.zig"
|
||||||
|
build_zig.write_text(
|
||||||
|
original_build_zig.read_text(encoding="utf-8").replace(
|
||||||
|
".linkage = .static,", ".linkage = .dynamic,"
|
||||||
|
),
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
for res in "build.zig.zon", "src":
|
||||||
|
(build_dir / res).symlink_to(libaegis_dir / res)
|
||||||
|
self.app.display_info("[aegis] Building libaegis dynamic library with Zig...")
|
||||||
|
try:
|
||||||
|
subprocess.run(
|
||||||
|
["zig", "build", "-Drelease"],
|
||||||
|
check=True,
|
||||||
|
cwd=str(build_dir),
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT,
|
||||||
|
)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
output = e.stdout.decode(errors="replace") if e.stdout else ""
|
||||||
|
raise RuntimeError(f"Zig build failed:\n{output}") from e
|
||||||
|
|
||||||
|
lib_dir = build_dir / "zig-out" / "lib"
|
||||||
|
|
||||||
|
dynamic_lib = None
|
||||||
|
for lib_file in lib_dir.iterdir():
|
||||||
|
if lib_file.name.startswith("libaegis") and lib_file.suffix in (
|
||||||
|
".so",
|
||||||
|
".dylib",
|
||||||
|
".dll",
|
||||||
|
):
|
||||||
|
dynamic_lib = lib_file
|
||||||
|
break
|
||||||
|
|
||||||
|
if not dynamic_lib or not dynamic_lib.exists():
|
||||||
|
raise RuntimeError(f"Built dynamic library not found in {lib_dir}")
|
||||||
|
|
||||||
|
if "force_include" not in build_data:
|
||||||
|
build_data["force_include"] = {}
|
||||||
|
dest_rel = str(Path("build") / dynamic_lib.name)
|
||||||
|
build_data["force_include"][str(dynamic_lib)] = dest_rel
|
||||||
|
self.app.display_info(f"[aegis] Added dynamic library to wheel: {dest_rel}")
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Generate CFFI cdef string from libaegis headers.
|
||||||
|
|
||||||
|
This script parses the C header files and extracts function declarations,
|
||||||
|
typedefs, and struct definitions to generate the cdef() string needed by CFFI.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pathlib
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def preprocess_content(content: str) -> str:
|
||||||
|
"""Remove comments, preprocessor directives, and extern "C" blocks."""
|
||||||
|
# Remove multi-line comments
|
||||||
|
content = re.sub(r"/\*.*?\*/", " ", content, flags=re.DOTALL)
|
||||||
|
# Remove line comments
|
||||||
|
content = re.sub(r"//.*$", "", content, flags=re.MULTILINE)
|
||||||
|
# Remove preprocessor directives
|
||||||
|
content = re.sub(r"^\s*#.*$", "", content, flags=re.MULTILINE)
|
||||||
|
# Remove extern "C" blocks
|
||||||
|
content = re.sub(r'extern\s+"C"\s*\{', "", content)
|
||||||
|
content = re.sub(r"(?:^|\n)\s*\}\s*(?:\n|$)", "\n", content, flags=re.MULTILINE)
|
||||||
|
|
||||||
|
return content
|
||||||
|
|
||||||
|
|
||||||
|
def clean_declaration(text: str) -> str:
|
||||||
|
"""Clean up a C declaration for CFFI consumption."""
|
||||||
|
# Remove __attribute__(...) with proper nesting
|
||||||
|
while "__attribute__" in text:
|
||||||
|
old = text
|
||||||
|
text = re.sub(r"__attribute__\s*\(\([^()]*\)\)", "", text)
|
||||||
|
if text == old:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Remove CRYPTO_ALIGN(...)
|
||||||
|
text = re.sub(r"CRYPTO_ALIGN\s*\(\s*\d+\s*\)", "", text)
|
||||||
|
|
||||||
|
# Normalize whitespace but preserve structure
|
||||||
|
lines = []
|
||||||
|
for line in text.split("\n"):
|
||||||
|
line = re.sub(r"\s+", " ", line).strip()
|
||||||
|
if line:
|
||||||
|
lines.append(line)
|
||||||
|
|
||||||
|
return " ".join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
def extract_declarations(header_path: pathlib.Path) -> list[str]:
|
||||||
|
"""Extract function declarations and typedefs from a header file."""
|
||||||
|
content = header_path.read_text(encoding="utf-8")
|
||||||
|
content = preprocess_content(content)
|
||||||
|
declarations = []
|
||||||
|
|
||||||
|
# Extract typedefs (including structs)
|
||||||
|
typedef_pattern = r"typedef\s+struct\s+\w+\s*\{[^}]+\}\s*\w+\s*;"
|
||||||
|
for match in re.finditer(typedef_pattern, content, re.DOTALL):
|
||||||
|
decl = clean_declaration(match.group(0))
|
||||||
|
if decl:
|
||||||
|
declarations.append(decl)
|
||||||
|
|
||||||
|
# Extract function declarations - more permissive pattern
|
||||||
|
func_pattern = r"((?:const\s+)?(?:int|void|size_t)\s+\w+\s*\([^;]+?\)\s*;)"
|
||||||
|
for match in re.finditer(func_pattern, content, re.DOTALL):
|
||||||
|
decl = clean_declaration(match.group(0))
|
||||||
|
if decl and "aegis" in decl.lower():
|
||||||
|
declarations.append(decl)
|
||||||
|
|
||||||
|
return declarations
|
||||||
|
|
||||||
|
|
||||||
|
def format_declaration(decl: str, max_width: int = 100) -> str:
|
||||||
|
"""Format a declaration for readability, with intelligent line breaking."""
|
||||||
|
# If it's short enough, return as-is
|
||||||
|
if len(decl) <= max_width:
|
||||||
|
return decl
|
||||||
|
|
||||||
|
# For function declarations, try to break at parameter boundaries
|
||||||
|
if "(" in decl and ")" in decl:
|
||||||
|
# Find the function name and opening paren
|
||||||
|
match = re.match(r"(.*?\s+\w+\s*)\((.*)\)(.*)", decl)
|
||||||
|
if match:
|
||||||
|
prefix, params, suffix = match.groups()
|
||||||
|
# Break parameters if they're too long
|
||||||
|
if len(prefix) + len(params) + 2 > max_width:
|
||||||
|
# Split parameters
|
||||||
|
param_list = [p.strip() for p in params.split(",")]
|
||||||
|
if len(param_list) > 1:
|
||||||
|
formatted_params = (",\n" + " " * (len(prefix) + 1)).join(
|
||||||
|
param_list
|
||||||
|
)
|
||||||
|
return f"{prefix}({formatted_params}){suffix}"
|
||||||
|
|
||||||
|
return decl
|
||||||
|
|
||||||
|
|
||||||
|
def generate_cdef(include_dir: pathlib.Path) -> str:
|
||||||
|
"""Generate the complete CFFI cdef string from all aegis headers."""
|
||||||
|
|
||||||
|
lines = [
|
||||||
|
"typedef unsigned char uint8_t;",
|
||||||
|
"typedef unsigned long size_t;",
|
||||||
|
"",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Header files in order, skipping aegis.h as it might be included elsewhere
|
||||||
|
headers = [
|
||||||
|
"aegis.h",
|
||||||
|
"aegis128l.h",
|
||||||
|
"aegis128x2.h",
|
||||||
|
"aegis128x4.h",
|
||||||
|
"aegis256.h",
|
||||||
|
"aegis256x2.h",
|
||||||
|
"aegis256x4.h",
|
||||||
|
]
|
||||||
|
|
||||||
|
for header_name in headers:
|
||||||
|
header_path = include_dir / header_name
|
||||||
|
if not header_path.exists():
|
||||||
|
print(f"Warning: {header_name} not found", file=sys.stderr)
|
||||||
|
continue
|
||||||
|
|
||||||
|
lines.append(f"/* {header_name} */")
|
||||||
|
declarations = extract_declarations(header_path)
|
||||||
|
|
||||||
|
for decl in declarations:
|
||||||
|
formatted = format_declaration(decl)
|
||||||
|
lines.append(formatted)
|
||||||
|
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
|
# Add libc bits for aligned allocation
|
||||||
|
lines.extend(
|
||||||
|
[
|
||||||
|
"/* libc bits for aligned allocation on POSIX */",
|
||||||
|
"int posix_memalign(void **memptr, size_t alignment, size_t size);",
|
||||||
|
"void free(void *ptr);",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
# Find the include directory
|
||||||
|
root = pathlib.Path(__file__).resolve().parents[2]
|
||||||
|
include_dir = root / "src" / "include"
|
||||||
|
|
||||||
|
if not include_dir.exists():
|
||||||
|
print(f"Include directory not found: {include_dir}", file=sys.stderr)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
cdef_string = generate_cdef(include_dir)
|
||||||
|
|
||||||
|
# Write to a file in the pyaegis/build subdirectory
|
||||||
|
output_dir = root / "python" / "pyaegis" / "build"
|
||||||
|
output_dir.mkdir(exist_ok=True)
|
||||||
|
output_path = output_dir / "aegis_cdef.h"
|
||||||
|
output_path.write_text(cdef_string, encoding="utf-8")
|
||||||
|
print(f"Generated: {output_path}", file=sys.stderr)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
Reference in New Issue
Block a user