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
|
||||
|
||||
from aegis import aegis256x4 as a
|
||||
from pyaegis import aegis256x4 as a
|
||||
|
||||
|
||||
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 time
|
||||
|
||||
from aegis import aegis128l, aegis128x2, aegis128x4, aegis256, aegis256x2, aegis256x4
|
||||
from pyaegis import aegis128l, aegis128x2, aegis128x4, aegis256, aegis256x2, aegis256x4
|
||||
|
||||
MSG_LEN = 16384000 # 16 MiB
|
||||
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]
|
||||
requires = ["hatchling"]
|
||||
requires = ["hatchling", "cffi>=2.0.0"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
@@ -26,3 +26,13 @@ Homepage = "https://github.com/aegis-aead/libaegis"
|
||||
dev = [
|
||||
"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 sys import stderr
|
||||
|
||||
import aegis.aegis128l
|
||||
import aegis.aegis128x2
|
||||
import aegis.aegis128x4
|
||||
import aegis.aegis256
|
||||
import aegis.aegis256x2
|
||||
import aegis.aegis256x4
|
||||
import pytest
|
||||
from pyaegis import aegis128l, aegis128x2, aegis128x4, aegis256, aegis256x2, aegis256x4
|
||||
|
||||
from .util import random_split_bytes
|
||||
|
||||
@@ -20,12 +15,12 @@ def load_encryption_test_vectors():
|
||||
|
||||
# Map filename to algorithm module
|
||||
algorithm_files = {
|
||||
"aegis-128l-test-vectors.json": aegis.aegis128l,
|
||||
"aegis-128x2-test-vectors.json": aegis.aegis128x2,
|
||||
"aegis-128x4-test-vectors.json": aegis.aegis128x4,
|
||||
"aegis-256-test-vectors.json": aegis.aegis256,
|
||||
"aegis-256x2-test-vectors.json": aegis.aegis256x2,
|
||||
"aegis-256x4-test-vectors.json": aegis.aegis256x4,
|
||||
"aegis-128l-test-vectors.json": aegis128l,
|
||||
"aegis-128x2-test-vectors.json": aegis128x2,
|
||||
"aegis-128x4-test-vectors.json": aegis128x4,
|
||||
"aegis-256-test-vectors.json": aegis256,
|
||||
"aegis-256x2-test-vectors.json": aegis256x2,
|
||||
"aegis-256x4-test-vectors.json": aegis256x4,
|
||||
}
|
||||
|
||||
for filename, alg_module in algorithm_files.items():
|
||||
|
||||
+7
-12
@@ -1,13 +1,8 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import aegis.aegis128l
|
||||
import aegis.aegis128x2
|
||||
import aegis.aegis128x4
|
||||
import aegis.aegis256
|
||||
import aegis.aegis256x2
|
||||
import aegis.aegis256x4
|
||||
import pytest
|
||||
from pyaegis import aegis128l, aegis128x2, aegis128x4, aegis256, aegis256x2, aegis256x4
|
||||
|
||||
from .util import random_split_bytes
|
||||
|
||||
@@ -24,17 +19,17 @@ def load_mac_test_vectors():
|
||||
def get_algorithm_module(name):
|
||||
"""Map test vector name to algorithm module."""
|
||||
if "128L" in name:
|
||||
return aegis.aegis128l
|
||||
return aegis128l
|
||||
elif "128X2" in name:
|
||||
return aegis.aegis128x2
|
||||
return aegis128x2
|
||||
elif "128X4" in name:
|
||||
return aegis.aegis128x4
|
||||
return aegis128x4
|
||||
elif "256" in name and "256X2" not in name and "256X4" not in name:
|
||||
return aegis.aegis256
|
||||
return aegis256
|
||||
elif "256X2" in name:
|
||||
return aegis.aegis256x2
|
||||
return aegis256x2
|
||||
elif "256X4" in name:
|
||||
return aegis.aegis256x4
|
||||
return aegis256x4
|
||||
else:
|
||||
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