Feat: Added vaptvupt codec, fix jasmin tests

This commit is contained in:
Cristian Cezar Moisés 2026-03-30 06:56:52 -03:00
commit 6651842748
63 changed files with 6577 additions and 342 deletions

262
include/vaptvupt.h Normal file
View file

@ -0,0 +1,262 @@
/* VaptVupt codec — originally Apache-2.0 by Cristian Cezar Moisés
* Integrated into Zupt MIT License
* Copyright (c) 2026 Cristian Cezar Moisés
* SPDX-License-Identifier: MIT AND Apache-2.0
*/
/*
* VaptVupt Codec Next-generation lossless compression
* Public API and data structures
*
* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright 2026 Cristian.
* Zero dependencies. Pure C11.
*/
#ifndef VAPTVUPT_H
#define VAPTVUPT_H
#include <stdint.h>
#include <stddef.h>
/* VAPTVUPT: When integrated into Zupt, pull in zupt_xxh64 declaration */
#ifndef VV_STANDALONE
#include "zupt.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* ═══════════════════════════════════════════════════════════════
* VERSION & CONSTANTS
* */
#define VV_VERSION_MAJOR 0
#define VV_VERSION_MINOR 1
#define VV_VERSION_PATCH 0
#define VV_VERSION_STRING "0.1.0"
#define VV_MAGIC 0x56560100u /* "VV\x01\x00" */
#define VV_MAX_BLOCK_SIZE (1u << 20) /* 1 MB per block */
#define VV_MIN_MATCH 4
#define VV_MAX_MATCH 65535
#define VV_MAX_LIT_RUN 65535
#define VV_MAX_OFFSET (1u << 24) /* 16 MB default window */
/* ═══════════════════════════════════════════════════════════════
* ERROR CODES
* */
typedef enum {
VV_OK = 0,
VV_ERR_IO = -1,
VV_ERR_CORRUPT = -2,
VV_ERR_NOMEM = -3,
VV_ERR_OVERFLOW = -4,
VV_ERR_BAD_MAGIC = -5,
VV_ERR_PARAM = -6,
} vv_error_t;
/* ═══════════════════════════════════════════════════════════════
* COMPRESSION MODES
* */
typedef enum {
VV_MODE_ULTRA_FAST = 0, /* Speed priority: greedy parse, no entropy */
VV_MODE_BALANCED = 1, /* Default: lazy parse + Huffman */
VV_MODE_EXTREME = 2, /* Ratio priority: optimal parse + Huffman */
} vv_mode_t;
/* ═══════════════════════════════════════════════════════════════
* BLOCK TYPES (2-bit field in block header)
* */
typedef enum {
VV_BLOCK_RAW = 0, /* Uncompressed (stored) */
VV_BLOCK_COMPRESSED = 1, /* LZ + raw literals */
VV_BLOCK_RLE = 2, /* Run-length (single byte) */
VV_BLOCK_ENTROPY = 3, /* LZ + entropy-coded literals (ANS or Huffman) */
} vv_block_type_t;
/* Entropy sub-type tags (first byte of entropy section in type-3 blocks) */
#define VV_ENTROPY_HUFFMAN 0x48 /* 'H' — Huffman (v0.3-v0.4) */
#define VV_ENTROPY_ANS 0x41 /* 'A' — tANS single-stream (v0.5) */
#define VV_ENTROPY_ANS4 0x49 /* 'I' — tANS 4-way interleaved (v0.6+) */
#define VV_ENTROPY_CTX 0x43 /* 'C' — tANS order-1 context model (v0.7+) */
#define VV_ENTROPY_SEQ 0x53 /* 'S' — sequence coding: ANS on lits+ml+of (v0.8+) */
/* Block header accessors (2-bit type, 1-bit last, 21-bit size) */
static inline vv_block_type_t vv_bh_type(uint32_t h) { return (vv_block_type_t)(h & 3); }
static inline int vv_bh_last(uint32_t h) { return (h >> 2) & 1; }
static inline uint32_t vv_bh_size(uint32_t h) { return (h >> 3) & 0x1FFFFF; }
static inline uint32_t vv_bh_pack(vv_block_type_t t, int last, uint32_t sz) {
return (uint32_t)t | ((uint32_t)last << 2) | (sz << 3);
}
/* ═══════════════════════════════════════════════════════════════
* TOKEN TYPES (in the sequence stream)
*
* Each token is: [type:2][litlen:6] [optional litlen ext]
* [literal bytes]
* [matchlen ext] [offset bytes]
*
* The decoder reads a compact token byte, copies literals,
* then copies a match. This is LZ4-like for speed.
* */
/* Token byte layout:
* Bits 7-4: literal_length (0-14, 15=extended)
* Bits 3-0: match_length - VV_MIN_MATCH (0-14, 15=extended)
*
* Followed by:
* [extended literal length varint, if litlen==15]
* [literal bytes]
* [offset: 2 bytes LE (or 3 bytes if high bit set)]
* [extended match length varint, if matchlen==15]
*/
/* ═══════════════════════════════════════════════════════════════
* ON-DISK STRUCTURES
* */
#pragma pack(push, 1)
/* Frame header: 16 bytes */
typedef struct {
uint32_t magic; /* VV_MAGIC */
uint8_t version; /* Format version (1) */
uint8_t flags; /* bit0: has_checksum, bit1: has_dict */
uint8_t mode_hint; /* Compression mode used (informational) */
uint8_t window_log; /* Window size = 1 << window_log */
uint64_t content_size; /* Uncompressed size (0 = unknown) */
} vv_frame_header_t;
/* Block header: 4 bytes */
typedef struct {
/* Bits 0-1: block_type (vv_block_type_t) */
/* Bit 2: last_block flag */
/* Bits 3-23: decompressed_size (max 1 MB) */
/* Bits 24-31: reserved */
uint32_t packed;
} vv_block_header_t;
/* Frame footer: 12 bytes */
typedef struct {
uint64_t checksum; /* XXH64 of decompressed content */
uint32_t footer_magic; /* 0x56564E44 = "VVND" */
} vv_frame_footer_t;
#pragma pack(pop)
/* Block header accessors defined above with block type enum */
/* ═══════════════════════════════════════════════════════════════
* MATCHER STATE
* */
#define VV_HC_BITS 18
#define VV_HC_SIZE (1u << VV_HC_BITS)
typedef struct {
int32_t table[VV_HC_SIZE]; /* Hash → most recent position */
int32_t *chain; /* Chain array (window_size entries) */
uint32_t window_size;
uint32_t chain_depth; /* Max chain traversal (level-dependent) */
} vv_matcher_t;
/* ═══════════════════════════════════════════════════════════════
* HUFFMAN TABLES (entropy coding)
*
* 256-symbol alphabet. Max code length 12 bits.
* Decode table: 4096 entries × 2 bytes = 8 KB (fits in L1).
* */
#define VV_HUF_MAX_BITS 12
#define VV_HUF_TABLE_SIZE (1 << VV_HUF_MAX_BITS)
typedef struct {
uint8_t lengths[256]; /* Code lengths per symbol */
uint16_t codes[256]; /* Canonical codes (for encoding) */
/* Decode table: entry = (symbol << 8) | num_bits */
uint16_t decode[VV_HUF_TABLE_SIZE];
} vv_huffman_t;
/* ═══════════════════════════════════════════════════════════════
* ENCODER/DECODER OPTIONS
* */
typedef struct {
vv_mode_t mode;
uint8_t window_log; /* 0 = auto (20 for balanced, 24 for extreme) */
int checksum; /* 1 = compute XXH64 */
int verbose;
} vv_options_t;
static inline void vv_default_options(vv_options_t *o) {
o->mode = VV_MODE_BALANCED;
o->window_log = 0;
o->checksum = 1;
o->verbose = 0;
}
/* ═══════════════════════════════════════════════════════════════
* PUBLIC API
* */
/* Compress src[0..src_len-1] into dst[0..dst_cap-1].
* Returns compressed size, or negative error code. */
int64_t vv_compress(const uint8_t *src, size_t src_len,
uint8_t *dst, size_t dst_cap,
const vv_options_t *opts);
/* Decompress src[0..src_len-1] into dst[0..dst_cap-1].
* Returns decompressed size, or negative error code. */
int64_t vv_decompress(const uint8_t *src, size_t src_len,
uint8_t *dst, size_t dst_cap);
/* Compute upper bound on compressed size for src_len input bytes. */
size_t vv_compress_bound(size_t src_len);
/* ═══════════════════════════════════════════════════════════════
* INTERNAL HELPERS (shared across modules)
* */
/* XXH64 hash (simplified, for checksum) */
/* VAPTVUPT: vv_xxh64 aliased to zupt_xxh64 (avoid duplicate symbol) */
#define vv_xxh64 zupt_xxh64
/* Hash function for matcher */
static inline uint32_t vv_hash4(const uint8_t *p) {
uint32_t v;
__builtin_memcpy(&v, p, 4);
return (v * 2654435761u) >> (32 - VV_HC_BITS);
}
/* Read/write little-endian helpers */
static inline uint16_t vv_read16(const uint8_t *p) {
uint16_t v; __builtin_memcpy(&v, p, 2); return v;
}
static inline uint32_t vv_read32(const uint8_t *p) {
uint32_t v; __builtin_memcpy(&v, p, 4); return v;
}
static inline void vv_write16(uint8_t *p, uint16_t v) {
__builtin_memcpy(p, &v, 2);
}
static inline void vv_write32(uint8_t *p, uint32_t v) {
__builtin_memcpy(p, &v, 4);
}
/* ═══════════════════════════════════════════════════════════════
* SIMD COPY HELPERS (declared here, defined in vv_simd.c)
* */
/* Copy exactly n bytes, may over-read/write by up to 32 bytes.
* Caller must ensure sufficient slack in destination. */
void vv_copy_fast(uint8_t *dst, const uint8_t *src, size_t n);
/* Copy match with overlap handling (offset may be < copy length). */
void vv_copy_match(uint8_t *dst, uint32_t offset, size_t length);
#ifdef __cplusplus
}
#endif
#endif /* VAPTVUPT_H */

121
include/vv_ans.h Normal file
View file

@ -0,0 +1,121 @@
/* VaptVupt codec — originally Apache-2.0 by Cristian Cezar Moisés
* Integrated into Zupt MIT License
* Copyright (c) 2026 Cristian Cezar Moisés
* SPDX-License-Identifier: MIT AND Apache-2.0
*/
/*
* VaptVupt tANS Entropy Codec (v2: sparse header + 4-way interleaved)
*
* Standalone: define VV_ANS_STANDALONE to use without VaptVupt.
* ZUPT-COMPAT: this header has zero VaptVupt dependencies when standalone.
*
* v0.6 changes:
* - Adaptive sparse/dense header (Item 1): 3× smaller on typical data
* - 4-way interleaved encode/decode (Item 2): ~2.5× faster decode
*/
#ifndef VV_ANS_H
#define VV_ANS_H
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define VVA_TABLE_LOG 12
#define VVA_TABLE_SIZE (1 << VVA_TABLE_LOG) /* 4096 */
#define VVA_MAX_SYMBOL 256
/* Header format discriminators */
#define VVA_HDR_SINGLE 0x01 /* Single symbol: 0-bit encoding */
#define VVA_HDR_SPARSE 0x02 /* ≤32 active symbols: (sym,freq) pairs */
#define VVA_HDR_DENSE 0x03 /* >32 active symbols: max_sym + freq array */
/* ZUPT-COMPAT: v0.5 legacy format detected by first byte being 0x00-0xFF
* without matching any HDR_* code fall back to old read path. */
#define VVA_HDR_LEGACY 0x00 /* v0.5 format: [max_sym] [2B×(max_sym+1)] */
#ifdef VV_ANS_STANDALONE
typedef enum {
VVA_OK = 0,
VVA_ERR_IO = -1,
VVA_ERR_CORRUPT = -2,
VVA_ERR_NOMEM = -3,
VVA_ERR_OVERFLOW = -4,
VVA_ERR_PARAM = -6,
} vva_error_t;
#else
#include "vaptvupt.h"
typedef vv_error_t vva_error_t;
#define VVA_OK VV_OK
#define VVA_ERR_CORRUPT VV_ERR_CORRUPT
#define VVA_ERR_NOMEM VV_ERR_NOMEM
#define VVA_ERR_OVERFLOW VV_ERR_OVERFLOW
#define VVA_ERR_PARAM VV_ERR_PARAM
#endif
typedef struct {
uint8_t symbol;
uint8_t nbits;
uint16_t baseline;
} vva_dec_entry_t;
/* ═══ Public API ═══ */
/* Single-stream encode/decode (tag 'A', backward compat with v0.5) */
vva_error_t vva_encode(const uint8_t *src, size_t src_len,
uint8_t *dst, size_t dst_cap, size_t *dst_len);
vva_error_t vva_decode(const uint8_t *src, size_t src_len,
uint8_t *dst, size_t dst_cap,
size_t num_literals, size_t *src_consumed);
/* 4-way interleaved encode/decode (tag 'I', v0.6+) */
vva_error_t vva_encode4(const uint8_t *src, size_t src_len,
uint8_t *dst, size_t dst_cap, size_t *dst_len);
vva_error_t vva_decode4(const uint8_t *src, size_t src_len,
uint8_t *dst, size_t dst_cap,
size_t num_literals, size_t *src_consumed);
/* Order-1 context model encode/decode (tag 'C', v0.7+)
* Uses 256 ANS tables one per previous byte. Contexts with too few
* observations inherit from the global table. 4 MB decode memory. */
vva_error_t vva_encode_ctx(const uint8_t *src, size_t src_len,
uint8_t *dst, size_t dst_cap, size_t *dst_len);
vva_error_t vva_decode_ctx(const uint8_t *src, size_t src_len,
uint8_t *dst, size_t dst_cap,
size_t num_literals, size_t *src_consumed);
/* ═══ Sequence coding (tag 'S', v0.8+) ═══
* ZUPT-COMPAT: available when VV_ANS_STANDALONE is defined.
*
* Encodes an LZ token stream using 3 ANS tables: literals, match-length
* codes (36 symbols), and offset codes (24 symbols). Replaces raw varint
* storage of match metadata, saving 8-15% on typical data.
*
* Input token format (from LZ engine):
* [token: litlen:4|matchlen:4] [litlen_ext] [literal_bytes] [2B offset LE] [matchlen_ext]
* Output: [3 table headers] [4B seq_count] [4B lit_count] [ANS bitstream]
*/
#define VVA_ML_CODES 36 /* Match length code count */
#define VVA_OF_CODES 24 /* Offset code count */
vva_error_t vva_encode_sequences(const uint8_t *tokens, size_t tok_len,
uint8_t *dst, size_t dst_cap, size_t *dst_len,
int off_bytes);
vva_error_t vva_decode_sequences(const uint8_t *src, size_t src_len,
uint8_t *dst, size_t dst_cap, size_t *dst_len);
static inline size_t vva_bound(size_t src_len) {
/* Context model header can be up to ~10KB, seq coding adds 3 table headers */
return 12288 + (src_len * 15 + 7) / 8 + 16;
}
#ifdef __cplusplus
}
#endif
#endif /* VV_ANS_H */

129
include/vv_huffman.h Normal file
View file

@ -0,0 +1,129 @@
/* VaptVupt codec — originally Apache-2.0 by Cristian Cezar Moisés
* Integrated into Zupt MIT License
* Copyright (c) 2026 Cristian Cezar Moisés
* SPDX-License-Identifier: MIT AND Apache-2.0
*/
/*
* VaptVupt Canonical Huffman Codec
*
* Standalone header: can be used independently with VV_HUFFMAN_STANDALONE.
* Designed for embedding in Zupt or any other LZ codec.
*
* API:
* vvh_encode() compress raw literals into Huffman bitstream
* vvh_decode() decompress Huffman bitstream back to raw literals
*
* Format:
* [1B max_symbol] [packed nibble code lengths] [LSB-first bitstream]
*
* Performance targets:
* Encode: 150 MB/s Decode: 800 MB/s (x86-64, -O2)
*/
#ifndef VV_HUFFMAN_H
#define VV_HUFFMAN_H
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ═══════════════════════════════════════════════════════════════
* CONSTANTS
* */
#define VVH_SYMBOLS 256
#define VVH_MAX_CODE_LEN 15
#define VVH_DECODE_BITS 12
#define VVH_DECODE_SIZE (1 << VVH_DECODE_BITS) /* 4096 entries */
/* ═══════════════════════════════════════════════════════════════
* ERROR CODES (compatible with vv_error_t when not standalone)
* */
#ifdef VV_HUFFMAN_STANDALONE
typedef enum {
VVH_OK = 0,
VVH_ERR_CORRUPT = -2,
VVH_ERR_NOMEM = -3,
VVH_ERR_OVERFLOW= -4,
} vvh_error_t;
#else
#include "vaptvupt.h"
typedef vv_error_t vvh_error_t;
#define VVH_OK VV_OK
#define VVH_ERR_CORRUPT VV_ERR_CORRUPT
#define VVH_ERR_NOMEM VV_ERR_NOMEM
#define VVH_ERR_OVERFLOW VV_ERR_OVERFLOW
#endif
/* ═══════════════════════════════════════════════════════════════
* ENCODE TABLE (used by encoder only)
* */
typedef struct {
uint8_t lengths[VVH_SYMBOLS]; /* Code length per symbol (0 = absent) */
uint16_t codes[VVH_SYMBOLS]; /* Bit-reversed canonical codes (LSB-first) */
} vvh_enc_table_t;
/* ═══════════════════════════════════════════════════════════════
* DECODE TABLE (used by decoder only)
*
* 12-bit lookup: 4096 entries × 4 bytes = 16 KB (L1-resident).
* Entry: bits [7:0] = symbol, bits [11:8] = code length.
* Symbols with code length > 12 use a slow path.
* */
typedef struct {
uint32_t table[VVH_DECODE_SIZE]; /* Fast lookup (codes ≤ 12 bits) */
/* Slow table for codes 13-15 bits (max 256 entries) */
uint16_t slow_code[VVH_SYMBOLS]; /* Bit-reversed code */
uint8_t slow_len[VVH_SYMBOLS]; /* Code length */
uint8_t slow_sym[VVH_SYMBOLS]; /* Symbol value */
int slow_count; /* Number of slow-path symbols */
} vvh_dec_table_t;
/* ═══════════════════════════════════════════════════════════════
* PUBLIC API
* */
/*
* Encode raw literal bytes into Huffman bitstream.
*
* src[0..src_len-1] raw literal bytes
* dst[0..dst_cap-1] output buffer (header + bitstream)
* *dst_len on success, set to actual compressed size
*
* Returns VVH_OK on success, or VVH_ERR_OVERFLOW if dst too small.
* If compressed size >= src_len, returns VVH_ERR_OVERFLOW (incompressible).
*/
vvh_error_t vvh_encode(const uint8_t *src, size_t src_len,
uint8_t *dst, size_t dst_cap, size_t *dst_len);
/*
* Decode Huffman bitstream back to raw literal bytes.
*
* src[0..src_len-1] compressed data (header + bitstream)
* dst[0..dst_cap-1] output buffer for decoded literals
* num_literals expected number of decoded symbols
* *src_consumed on success, bytes consumed from src
*
* Returns VVH_OK on success, or error code.
*/
vvh_error_t vvh_decode(const uint8_t *src, size_t src_len,
uint8_t *dst, size_t dst_cap,
size_t num_literals, size_t *src_consumed);
/*
* Upper bound on compressed size for src_len literal bytes.
*/
static inline size_t vvh_bound(size_t src_len) {
/* header (129 max) + bitstream (15 bits/symbol worst case) + slack */
return 129 + (src_len * 15 + 7) / 8 + 8;
}
#ifdef __cplusplus
}
#endif
#endif /* VV_HUFFMAN_H */

View file

@ -30,7 +30,7 @@
#define zupt_mkdir(p) mkdir(p, 0755)
#endif
#define ZUPT_VERSION_STRING "1.5.0"
#define ZUPT_VERSION_STRING "2.0.0"
#define ZUPT_FORMAT_MAJOR 1
#define ZUPT_FORMAT_MINOR 4
@ -74,6 +74,7 @@
#define ZUPT_CODEC_ZUPT_LZ 0x0008
#define ZUPT_CODEC_ZUPT_LZH 0x0009 /* LZ77 + Huffman */
#define ZUPT_CODEC_ZUPT_LZHP 0x000A /* LZ77 + Huffman + Byte Prediction (default) */
#define ZUPT_CODEC_VAPTVUPT 0x0010 /* VAPTVUPT: VaptVupt LZ + ANS entropy codec */
/* Crypto */
#define ZUPT_SALT_SIZE 32
@ -128,15 +129,35 @@ typedef struct {
uint8_t *payload;
} zupt_block_t;
/* Buffer canary for keyring overflow detection */
#define ZUPT_CANARY 0xDEADCAFEBABEFACEULL
typedef struct {
uint64_t canary_head; /* Must equal ZUPT_CANARY */
uint8_t enc_key[ZUPT_AES_KEY_SIZE];
uint8_t mac_key[ZUPT_HMAC_SIZE];
uint8_t salt[ZUPT_SALT_SIZE];
uint8_t base_nonce[ZUPT_NONCE_SIZE];
uint32_t iterations;
int active;
uint64_t canary_tail; /* Must equal ZUPT_CANARY */
} zupt_keyring_t;
/* Check keyring canaries — abort on buffer overflow */
static inline void zupt_keyring_init(zupt_keyring_t *kr) {
volatile uint8_t *p = (volatile uint8_t *)kr;
for (size_t i = 0; i < sizeof(*kr); i++) p[i] = 0;
kr->canary_head = ZUPT_CANARY;
kr->canary_tail = ZUPT_CANARY;
}
static inline void zupt_keyring_check(const zupt_keyring_t *kr) {
if (kr->canary_head != ZUPT_CANARY || kr->canary_tail != ZUPT_CANARY) {
fprintf(stderr, "FATAL: keyring buffer overflow detected (canary corrupted)\n");
/* Use exit(127) instead of abort() to avoid needing <stdlib.h> */
_exit(127);
}
}
typedef struct {
char **paths, **arc_paths;
int count, capacity;
@ -188,6 +209,11 @@ static inline uint64_t zupt_le64_get(const uint8_t *p) {
* SECURE MEMORY WIPE (resists dead-store elimination by compilers)
* */
/* FRAMA-C: Secure memory wipe — resists dead-store elimination */
/*@ requires \valid((uint8_t *)ptr + (0..len-1));
@ assigns ((uint8_t *)ptr)[0..len-1];
@ ensures \forall integer i; 0 <= i < len ==> ((uint8_t *)ptr)[i] == 0;
*/
static inline void zupt_secure_wipe(void *ptr, size_t len) {
#if defined(_WIN32)
SecureZeroMemory(ptr, len);
@ -244,6 +270,14 @@ uint8_t *zupt_encrypt_buffer(const zupt_keyring_t *kr, const uint8_t *plain, siz
uint8_t *zupt_decrypt_buffer(const zupt_keyring_t *kr, const uint8_t *pkg, size_t pkglen, uint64_t seq, size_t *olen);
void zupt_random_bytes(uint8_t *buf, size_t len);
/* ─── Memory locking for key material ─── */
int zupt_mlock_keys(void *ptr, size_t len);
void zupt_munlock_keys(void *ptr, size_t len);
/* ─── Adaptive compression: file type detection ─── */
/* Returns: -1=store (incompressible), 0=default, 5=medium, 9=max */
int zupt_detect_filetype(const uint8_t *header, size_t header_len);
/* ─── XXH64 ─── */
uint64_t zupt_xxh64(const void *data, size_t len, uint64_t seed);

View file

@ -7,6 +7,8 @@
*
* Calling convention: System V AMD64 ABI.
* Pointer args passed in RDI, RSI, RDX, RCX, R8, R9.
*
* v2.0.0: All 4 Jasmin functions wired and active.
*/
#ifndef ZUPT_JASMIN_H
#define ZUPT_JASMIN_H
@ -27,14 +29,34 @@ extern void zupt_ct_select_32(void *out, const void *a,
/* JASMIN-VERIFIED: CT conditional swap (4×u64 masked XOR swap).
* if cond==0: no-op. if cond==1: swaps ab in place.
* Replaces fe_cswap in zupt_x25519.c. */
* Replaces fe_cswap in zupt_x25519.c.
* NOTE: Requires 4×u64 field element layout (donna64). */
extern void zupt_fe_cswap(void *a, void *b, uint64_t cond);
/* NOTE: zupt_aes256_blk has an offset bug in the Jasmin-generated
* assembly (stack u128[15] indexing uses byte offset instead of
* element offset rk.[1] generates [rsp+1] not [rsp+16]).
* AES-NI path is NOT wired in until the .jazz source is fixed.
* C table-based AES remains the active path. */
/* JASMIN-VERIFIED: AES-256 single-block encrypt via AES-NI.
* out = AES-256-ECB(key, ctr) XOR in.
* FIX v2.0.0: Stack offset bug resolved round keys at correct
* 16-byte aligned offsets. Requires AES-NI (checked via CPUID).
*
* Args (System V ABI):
* out_ptr (RDI): destination for 16-byte result
* in_blk (RSI): pointer to 16-byte plaintext block
* key (RDX): pointer to 32-byte AES-256 key (two u128)
* ctr_blk (RCX): pointer to 16-byte counter block
*/
extern void zupt_aes256_blk(void *out, const void *in,
const void *key, const void *ctr);
/* JASMIN-VERIFIED: AES-256-CTR 4-block pipeline via AES-NI.
* Processes nblocks×16 bytes with 4-way interleaving.
* Counter is updated in-place (big-endian increment in bytes [8..15]).
* Requires AES-NI. Falls back to zupt_aes256_blk for remaining 1-3 blocks.
*
* Args: out(RDI), in(RSI), key(RDX), ctr(RCX), nblocks(R8)
*/
extern void zupt_aes256_ctr4(void *out, const void *in,
const void *key, void *ctr,
uint64_t nblocks);
#endif /* ZUPT_USE_JASMIN */
#endif /* ZUPT_JASMIN_H */