604 lines
30 KiB
C
604 lines
30 KiB
C
/*
|
|
* libzuptsdk — Public C ABI for the ZUPT backup compression library
|
|
*
|
|
* Copyright (c) 2026 Cristian Cezar Moisés
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*
|
|
* Repository: https://github.com/cristiancmoises/zupt
|
|
* Contact: sac@securityops.co
|
|
*
|
|
* --------------------------------------------------------------------------
|
|
* STABILITY GUARANTEE
|
|
* --------------------------------------------------------------------------
|
|
* Every symbol declared in this header is part of the stable v1.0 ABI and
|
|
* is gated behind the linker version tag ZUPTSDK_1.0. New symbols may be
|
|
* added in minor versions (1.1, 1.2, ...) under new tags (ZUPTSDK_1.1, ...).
|
|
* Existing symbols will never change signature within v1.x. Breaking
|
|
* changes require a major version bump (libzuptsdk.so.2).
|
|
*
|
|
* No symbol prefixed with anything other than `zuptsdk_` or `ZUPTSDK_` is
|
|
* part of this ABI. Do not link against internal `zupt_*` symbols even if
|
|
* they appear in the static archive — they will disappear without notice.
|
|
*
|
|
* --------------------------------------------------------------------------
|
|
* THREAD SAFETY
|
|
* --------------------------------------------------------------------------
|
|
* Every function that takes a `zuptsdk_ctx_t *` operates only on that
|
|
* context's state and on caller-provided buffers. Concurrent calls on
|
|
* DISTINCT contexts are safe (MT-Safe). Concurrent calls on the SAME
|
|
* context are NOT safe (MT-Unsafe-Same-Context) unless explicitly
|
|
* documented otherwise.
|
|
*
|
|
* --------------------------------------------------------------------------
|
|
* MEMORY OWNERSHIP
|
|
* --------------------------------------------------------------------------
|
|
* Every function documents ownership using these conventions in the param
|
|
* comments:
|
|
* [in] caller owns, library reads only
|
|
* [out] caller owns, library writes
|
|
* [in,out] caller owns, library reads and writes
|
|
* [transfers] ownership moves caller -> library (or library -> caller)
|
|
* [borrowed] pointer valid only for the duration of the call
|
|
*
|
|
* Any function that returns a heap-allocated value via an output pointer
|
|
* documents the corresponding zuptsdk_*_destroy() or zuptsdk_free() call
|
|
* the caller must invoke. Calling free() on libc-allocated memory from a
|
|
* different allocator is undefined; always use the documented destroyer.
|
|
*
|
|
* --------------------------------------------------------------------------
|
|
* ERROR HANDLING
|
|
* --------------------------------------------------------------------------
|
|
* Functions return `int` where 0 == ZUPTSDK_OK and negative values are
|
|
* `zuptsdk_error_t` codes. Use zuptsdk_strerror() for a static description
|
|
* and zuptsdk_last_error_detail(ctx) for a thread-local detailed message
|
|
* including filename, line number, and underlying errno where applicable.
|
|
*
|
|
* The library never calls abort(), exit(), or _exit(). It never writes to
|
|
* stdout or stderr unless the caller explicitly enables logging via
|
|
* zuptsdk_ctx_set_log_callback().
|
|
*
|
|
* --------------------------------------------------------------------------
|
|
* SECURE MEMORY
|
|
* --------------------------------------------------------------------------
|
|
* Inputs and outputs containing secret material (passwords, raw keys,
|
|
* decrypted plaintext keys) MUST be passed via `zuptsdk_secure_buffer_t`
|
|
* to ensure mlock()-backed storage and explicit_bzero() on destroy.
|
|
* Passing such material via plain `const uint8_t *` is allowed for
|
|
* convenience but the library cannot guarantee zeroization of caller
|
|
* memory in that case.
|
|
*/
|
|
|
|
#ifndef ZUPTSDK_H
|
|
#define ZUPTSDK_H
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* ════════════════════════════════════════════════════════════════════════
|
|
* VERSION
|
|
* ════════════════════════════════════════════════════════════════════════ */
|
|
|
|
#define ZUPTSDK_VERSION_MAJOR 1
|
|
#define ZUPTSDK_VERSION_MINOR 0
|
|
#define ZUPTSDK_VERSION_PATCH 0
|
|
#define ZUPTSDK_VERSION_STRING "1.0.0"
|
|
|
|
/* Compile-time version check helper (negative if header older than required) */
|
|
#define ZUPTSDK_VERSION_AT_LEAST(maj, min, pat) \
|
|
((ZUPTSDK_VERSION_MAJOR > (maj)) || \
|
|
(ZUPTSDK_VERSION_MAJOR == (maj) && ZUPTSDK_VERSION_MINOR > (min)) || \
|
|
(ZUPTSDK_VERSION_MAJOR == (maj) && ZUPTSDK_VERSION_MINOR == (min) && \
|
|
ZUPTSDK_VERSION_PATCH >= (pat)))
|
|
|
|
/**
|
|
* Return the runtime version string of the linked library, e.g. "1.0.0".
|
|
* The returned pointer is to static storage and must NOT be freed.
|
|
*
|
|
* Use this with the compile-time ZUPTSDK_VERSION_STRING to detect mismatch
|
|
* between header and library at runtime.
|
|
*/
|
|
const char *zuptsdk_version_string(void);
|
|
|
|
/**
|
|
* Verify that the linked library is at least the requested version.
|
|
* Returns 0 if compatible, ZUPTSDK_ERR_VERSION_MISMATCH otherwise.
|
|
* Call this once at startup before any other zuptsdk_* function.
|
|
*/
|
|
int zuptsdk_version_check(int major, int minor, int patch);
|
|
|
|
/* ════════════════════════════════════════════════════════════════════════
|
|
* ERRORS
|
|
* ════════════════════════════════════════════════════════════════════════ */
|
|
|
|
typedef enum {
|
|
ZUPTSDK_OK = 0,
|
|
ZUPTSDK_ERR_INVALID_ARG = -1, /* NULL pointer, bad size, bad enum value */
|
|
ZUPTSDK_ERR_NO_MEMORY = -2, /* malloc/calloc/realloc returned NULL */
|
|
ZUPTSDK_ERR_IO = -3, /* read/write error; see errno detail */
|
|
ZUPTSDK_ERR_BAD_ARCHIVE = -4, /* Magic mismatch or truncated header */
|
|
ZUPTSDK_ERR_BAD_PASSWORD = -5, /* MAC verification failed */
|
|
ZUPTSDK_ERR_BAD_KEY = -6, /* PQ key file malformed or wrong type */
|
|
ZUPTSDK_ERR_BAD_MAC = -7, /* HMAC mismatch — archive corrupted or tampered */
|
|
ZUPTSDK_ERR_BAD_VERSION = -8, /* Archive format version not supported */
|
|
ZUPTSDK_ERR_BAD_CHECKSUM = -9, /* Block checksum mismatch */
|
|
ZUPTSDK_ERR_BUFFER_TOO_SMALL = -10, /* Output buffer insufficient */
|
|
ZUPTSDK_ERR_NOT_ENCRYPTED = -11, /* Tried to decrypt unencrypted archive */
|
|
ZUPTSDK_ERR_PASSWORD_REQUIRED = -12, /* Archive needs password but none supplied */
|
|
ZUPTSDK_ERR_PQ_KEY_REQUIRED = -13, /* Archive needs PQ key but none supplied */
|
|
ZUPTSDK_ERR_UNSUPPORTED = -14, /* Feature not supported on this platform */
|
|
ZUPTSDK_ERR_VERSION_MISMATCH = -15, /* Library older than requested */
|
|
ZUPTSDK_ERR_PATH_TRAVERSAL = -16, /* "../" or absolute path in archive */
|
|
ZUPTSDK_ERR_TOO_LARGE = -17, /* Decompressed size exceeds limit */
|
|
ZUPTSDK_ERR_CRYPTO_FAIL = -18, /* Underlying crypto primitive failed */
|
|
ZUPTSDK_ERR_CANCELLED = -19, /* Caller cancelled via progress callback */
|
|
ZUPTSDK_ERR_INTERNAL = -99 /* Bug in library — please report */
|
|
} zuptsdk_error_t;
|
|
|
|
/**
|
|
* Static error description for a zuptsdk_error_t value.
|
|
* Returned pointer is static and must not be freed. Always non-NULL.
|
|
*/
|
|
const char *zuptsdk_strerror(int err);
|
|
|
|
/**
|
|
* Thread-local detailed error message from the most recent failed call.
|
|
* The string includes file:line of the failure point and underlying errno
|
|
* description where applicable. Returned pointer is to thread-local
|
|
* storage, valid until the next failed zuptsdk_* call on this thread.
|
|
* Returns "" if no error has been recorded on this thread.
|
|
*/
|
|
const char *zuptsdk_last_error_detail(void);
|
|
|
|
/* ════════════════════════════════════════════════════════════════════════
|
|
* OPAQUE TYPES (forward declarations only — no struct layout exposed)
|
|
* ════════════════════════════════════════════════════════════════════════ */
|
|
|
|
typedef struct zuptsdk_ctx zuptsdk_ctx_t;
|
|
typedef struct zuptsdk_options zuptsdk_options_t;
|
|
typedef struct zuptsdk_archive_info zuptsdk_archive_info_t;
|
|
typedef struct zuptsdk_secure_buf zuptsdk_secure_buf_t;
|
|
typedef struct zuptsdk_keypair zuptsdk_keypair_t;
|
|
typedef struct zuptsdk_pubkey zuptsdk_pubkey_t;
|
|
typedef struct zuptsdk_privkey zuptsdk_privkey_t;
|
|
|
|
/* ════════════════════════════════════════════════════════════════════════
|
|
* ENUMS
|
|
* ════════════════════════════════════════════════════════════════════════ */
|
|
|
|
typedef enum {
|
|
ZUPTSDK_CODEC_AUTO = 0, /* Hardware-adaptive (VaptVupt on AVX2, LZHP otherwise) */
|
|
ZUPTSDK_CODEC_VAPTVUPT = 1, /* VaptVupt LZ + ANS entropy */
|
|
ZUPTSDK_CODEC_LZHP = 2, /* LZ77 + Huffman + Byte Prediction */
|
|
ZUPTSDK_CODEC_LZH = 3, /* LZ77 + Huffman */
|
|
ZUPTSDK_CODEC_LZ = 4, /* LZ77 only */
|
|
ZUPTSDK_CODEC_STORE = 5 /* No compression */
|
|
} zuptsdk_codec_t;
|
|
|
|
typedef enum {
|
|
ZUPTSDK_ENC_NONE = 0, /* No encryption */
|
|
ZUPTSDK_ENC_PASSWORD = 1, /* PBKDF2 → AES-256-CTR + HMAC-SHA256 */
|
|
ZUPTSDK_ENC_PQ_HYBRID = 2 /* ML-KEM-768 + X25519 hybrid KEM */
|
|
} zuptsdk_encryption_t;
|
|
|
|
typedef enum {
|
|
ZUPTSDK_LOG_ERROR = 0,
|
|
ZUPTSDK_LOG_WARN = 1,
|
|
ZUPTSDK_LOG_INFO = 2,
|
|
ZUPTSDK_LOG_DEBUG = 3
|
|
} zuptsdk_log_level_t;
|
|
|
|
/* ════════════════════════════════════════════════════════════════════════
|
|
* CALLBACKS
|
|
* ════════════════════════════════════════════════════════════════════════ */
|
|
|
|
/**
|
|
* Streaming read callback. Library calls this to obtain input bytes.
|
|
* @param userdata [in] opaque pointer supplied at stream init
|
|
* @param buf [out] destination buffer
|
|
* @param max_bytes max bytes to read into buf
|
|
* @return Number of bytes actually read (0 == EOF, < 0 == error).
|
|
*/
|
|
typedef int64_t (*zuptsdk_read_fn)(void *userdata, uint8_t *buf, size_t max_bytes);
|
|
|
|
/**
|
|
* Streaming write callback. Library calls this to deliver output bytes.
|
|
* @param userdata [in] opaque pointer supplied at stream init
|
|
* @param buf [in] data to write
|
|
* @param bytes number of bytes in buf
|
|
* @return Number of bytes actually written (must equal `bytes` on success).
|
|
*/
|
|
typedef int64_t (*zuptsdk_write_fn)(void *userdata, const uint8_t *buf, size_t bytes);
|
|
|
|
/**
|
|
* Progress callback. Library invokes periodically during long operations.
|
|
* Return non-zero to cancel the operation; the in-flight call will then
|
|
* return ZUPTSDK_ERR_CANCELLED.
|
|
* @param userdata [in] opaque pointer set via zuptsdk_ctx_set_progress_callback
|
|
* @param processed bytes processed so far
|
|
* @param total total bytes (0 if unknown)
|
|
* @return 0 to continue, non-zero to cancel.
|
|
*/
|
|
typedef int (*zuptsdk_progress_fn)(void *userdata, uint64_t processed, uint64_t total);
|
|
|
|
/**
|
|
* Log callback. Receives diagnostic messages from the library.
|
|
* Set via zuptsdk_ctx_set_log_callback(). NULL means no logging (default).
|
|
* The string is null-terminated and valid only for the duration of the call.
|
|
*/
|
|
typedef void (*zuptsdk_log_fn)(void *userdata, zuptsdk_log_level_t level, const char *msg);
|
|
|
|
/**
|
|
* Custom allocator hooks. Set globally via zuptsdk_set_allocator().
|
|
* If any function is NULL, libc malloc/free/realloc is used.
|
|
* realloc_fn must accept (NULL, n) as malloc(n) and (p, 0) as free(p).
|
|
*/
|
|
typedef struct {
|
|
void *(*malloc_fn)(void *userdata, size_t size);
|
|
void (*free_fn)(void *userdata, void *ptr);
|
|
void *(*realloc_fn)(void *userdata, void *ptr, size_t size);
|
|
void *userdata;
|
|
} zuptsdk_allocator_t;
|
|
|
|
/* ════════════════════════════════════════════════════════════════════════
|
|
* GLOBAL CONFIG
|
|
* ════════════════════════════════════════════════════════════════════════ */
|
|
|
|
/**
|
|
* Install a custom allocator. Must be called before any other zuptsdk_*
|
|
* function. Calling after contexts have been created is undefined.
|
|
* Pass NULL to revert to libc allocator (only valid before first use).
|
|
*
|
|
* @param alloc [in,borrowed] allocator hooks; copied internally
|
|
* @return ZUPTSDK_OK or ZUPTSDK_ERR_INVALID_ARG
|
|
*/
|
|
int zuptsdk_set_allocator(const zuptsdk_allocator_t *alloc);
|
|
|
|
/* ════════════════════════════════════════════════════════════════════════
|
|
* CONTEXT
|
|
* ════════════════════════════════════════════════════════════════════════ */
|
|
|
|
/**
|
|
* Create a new SDK context. Each context holds its own thread pool,
|
|
* progress callback, log callback, and error state. Contexts are
|
|
* cheap to create — a few KB plus the configured thread count.
|
|
*
|
|
* @param ctx_out [out,transfers] pointer to receive new context
|
|
* @return ZUPTSDK_OK on success, ZUPTSDK_ERR_NO_MEMORY on alloc failure.
|
|
* On error, *ctx_out is set to NULL.
|
|
*/
|
|
int zuptsdk_ctx_create(zuptsdk_ctx_t **ctx_out);
|
|
|
|
/**
|
|
* Destroy a context. Frees all owned resources including thread pool.
|
|
* Safe to call with NULL. After this call, the pointer is invalid.
|
|
*/
|
|
void zuptsdk_ctx_destroy(zuptsdk_ctx_t *ctx);
|
|
|
|
/**
|
|
* Set worker thread count. 0 == auto (one per CPU). Default is auto.
|
|
* Returns ZUPTSDK_ERR_INVALID_ARG if ctx is NULL or threads > 256.
|
|
*/
|
|
int zuptsdk_ctx_set_threads(zuptsdk_ctx_t *ctx, int threads);
|
|
|
|
/**
|
|
* Set progress callback for long-running operations on this context.
|
|
* Pass NULL fn to clear. userdata is opaque to the library.
|
|
*/
|
|
int zuptsdk_ctx_set_progress_callback(zuptsdk_ctx_t *ctx,
|
|
zuptsdk_progress_fn fn,
|
|
void *userdata);
|
|
|
|
/**
|
|
* Set log callback for diagnostic messages on this context.
|
|
* Pass NULL fn to disable logging (default).
|
|
*/
|
|
int zuptsdk_ctx_set_log_callback(zuptsdk_ctx_t *ctx,
|
|
zuptsdk_log_fn fn,
|
|
zuptsdk_log_level_t min_level,
|
|
void *userdata);
|
|
|
|
/* ════════════════════════════════════════════════════════════════════════
|
|
* OPTIONS
|
|
* ════════════════════════════════════════════════════════════════════════ */
|
|
|
|
/**
|
|
* Create a default-initialized options bag for compress/encrypt operations.
|
|
* Defaults: codec=AUTO, level=7, no encryption, no dedup, no solid mode.
|
|
*/
|
|
int zuptsdk_options_create(zuptsdk_options_t **opts_out);
|
|
void zuptsdk_options_destroy(zuptsdk_options_t *opts);
|
|
|
|
int zuptsdk_options_set_codec(zuptsdk_options_t *opts, zuptsdk_codec_t codec);
|
|
int zuptsdk_options_set_level(zuptsdk_options_t *opts, int level /* 1..9 */);
|
|
int zuptsdk_options_set_dedup(zuptsdk_options_t *opts, int enabled);
|
|
int zuptsdk_options_set_solid(zuptsdk_options_t *opts, int enabled);
|
|
int zuptsdk_options_set_block_size(zuptsdk_options_t *opts, size_t bytes);
|
|
|
|
/**
|
|
* Maximum decompressed output size. Decompression aborts with
|
|
* ZUPTSDK_ERR_TOO_LARGE if exceeded. 0 == unlimited (NOT recommended
|
|
* for untrusted input — zip-bomb attack vector). Default: 16 GiB.
|
|
*/
|
|
int zuptsdk_options_set_max_decompressed(zuptsdk_options_t *opts,
|
|
uint64_t max_bytes);
|
|
|
|
/* ════════════════════════════════════════════════════════════════════════
|
|
* SECURE BUFFERS (for passwords and key material)
|
|
* ════════════════════════════════════════════════════════════════════════ */
|
|
|
|
/**
|
|
* Allocate a secure buffer: backing memory is mlock()ed (locked into RAM,
|
|
* never swapped to disk) and explicit_bzero()ed on destroy.
|
|
*
|
|
* @param size requested size in bytes (1..65536)
|
|
* @param buf_out [out,transfers] receives buffer handle
|
|
* @return ZUPTSDK_OK on success.
|
|
*/
|
|
int zuptsdk_secure_buf_create(size_t size, zuptsdk_secure_buf_t **buf_out);
|
|
|
|
/**
|
|
* Destroy a secure buffer. Memory is zeroed and unlocked before free.
|
|
* Safe to call with NULL.
|
|
*/
|
|
void zuptsdk_secure_buf_destroy(zuptsdk_secure_buf_t *buf);
|
|
|
|
/**
|
|
* Get raw pointer to the secure buffer's storage. Pointer is valid until
|
|
* zuptsdk_secure_buf_destroy() is called. Caller may read or write up to
|
|
* the buffer's size.
|
|
*
|
|
* @param buf [in]
|
|
* @param data_out [out,borrowed] receives pointer to storage
|
|
* @param size_out [out] receives buffer size
|
|
*/
|
|
int zuptsdk_secure_buf_get(zuptsdk_secure_buf_t *buf,
|
|
uint8_t **data_out, size_t *size_out);
|
|
|
|
/**
|
|
* Convenience: copy data into a new secure buffer.
|
|
* Useful when migrating an existing plain buffer to secure storage.
|
|
*/
|
|
int zuptsdk_secure_buf_from_data(const uint8_t *data, size_t size,
|
|
zuptsdk_secure_buf_t **buf_out);
|
|
|
|
/* ════════════════════════════════════════════════════════════════════════
|
|
* KEYS (PQ hybrid: ML-KEM-768 + X25519)
|
|
* ════════════════════════════════════════════════════════════════════════ */
|
|
|
|
/**
|
|
* Generate a fresh hybrid keypair. Uses the system CSPRNG.
|
|
*
|
|
* @param ctx [in]
|
|
* @param kp_out [out,transfers] receives new keypair
|
|
* @return ZUPTSDK_OK on success, ZUPTSDK_ERR_CRYPTO_FAIL on RNG failure.
|
|
*/
|
|
int zuptsdk_keypair_generate(zuptsdk_ctx_t *ctx, zuptsdk_keypair_t **kp_out);
|
|
|
|
void zuptsdk_keypair_destroy(zuptsdk_keypair_t *kp);
|
|
|
|
/**
|
|
* Save private key to a file. The file is written with mode 0600 on POSIX.
|
|
* Recommended extension: ".key".
|
|
*/
|
|
int zuptsdk_keypair_save_private(const zuptsdk_keypair_t *kp, const char *path);
|
|
|
|
/**
|
|
* Save public key to a file. World-readable.
|
|
* Recommended extension: ".pub" or "_public.key".
|
|
*/
|
|
int zuptsdk_keypair_save_public(const zuptsdk_keypair_t *kp, const char *path);
|
|
|
|
/**
|
|
* Load a private key from a file.
|
|
* @param path [in]
|
|
* @param key_out [out,transfers]
|
|
*/
|
|
int zuptsdk_privkey_load(const char *path, zuptsdk_privkey_t **key_out);
|
|
void zuptsdk_privkey_destroy(zuptsdk_privkey_t *key);
|
|
|
|
/**
|
|
* Load a public key from a file.
|
|
*/
|
|
int zuptsdk_pubkey_load(const char *path, zuptsdk_pubkey_t **key_out);
|
|
void zuptsdk_pubkey_destroy(zuptsdk_pubkey_t *key);
|
|
|
|
/**
|
|
* Derive public key from private key (no I/O).
|
|
*/
|
|
int zuptsdk_privkey_get_public(const zuptsdk_privkey_t *priv,
|
|
zuptsdk_pubkey_t **pub_out);
|
|
|
|
/* ════════════════════════════════════════════════════════════════════════
|
|
* COMPRESS / DECOMPRESS — buffer mode (for small archives)
|
|
* ════════════════════════════════════════════════════════════════════════ */
|
|
|
|
/**
|
|
* Compress an in-memory file list into a single archive buffer.
|
|
*
|
|
* @param ctx [in]
|
|
* @param opts [in,borrowed] compression and encryption options
|
|
* @param file_paths [in] array of filesystem paths to add
|
|
* @param file_count number of paths in file_paths
|
|
* @param password [in,nullable] password as a secure buffer; NULL for no pw
|
|
* @param recipient_pk [in,nullable] PQ public key for encryption; NULL for no PQ
|
|
* @param archive_out [out,transfers] receives malloc'd archive bytes;
|
|
* caller must free with zuptsdk_free()
|
|
* @param archive_sz [out] size of returned archive
|
|
* @return ZUPTSDK_OK on success.
|
|
*/
|
|
int zuptsdk_compress_files(zuptsdk_ctx_t *ctx,
|
|
const zuptsdk_options_t *opts,
|
|
const char *const *file_paths,
|
|
size_t file_count,
|
|
zuptsdk_secure_buf_t *password,
|
|
const zuptsdk_pubkey_t *recipient_pk,
|
|
uint8_t **archive_out,
|
|
size_t *archive_sz);
|
|
|
|
/**
|
|
* Compress a single in-memory data buffer. Useful for SDK consumers that
|
|
* have data in memory and want a self-contained archive.
|
|
*
|
|
* @param logical_name [in] name to record inside the archive (e.g. "data.bin")
|
|
*/
|
|
int zuptsdk_compress_buffer(zuptsdk_ctx_t *ctx,
|
|
const zuptsdk_options_t *opts,
|
|
const char *logical_name,
|
|
const uint8_t *data, size_t data_sz,
|
|
zuptsdk_secure_buf_t *password,
|
|
const zuptsdk_pubkey_t *recipient_pk,
|
|
uint8_t **archive_out,
|
|
size_t *archive_sz);
|
|
|
|
/**
|
|
* Extract an archive into a directory.
|
|
*
|
|
* @param dest_dir [in] target directory; created if missing
|
|
* @param password [in,nullable]
|
|
* @param recipient_sk [in,nullable] PQ private key
|
|
*/
|
|
int zuptsdk_extract_to_dir(zuptsdk_ctx_t *ctx,
|
|
const uint8_t *archive, size_t archive_sz,
|
|
const char *dest_dir,
|
|
zuptsdk_secure_buf_t *password,
|
|
const zuptsdk_privkey_t *recipient_sk);
|
|
|
|
/**
|
|
* Extract a single-file archive (one created with zuptsdk_compress_buffer)
|
|
* back into a memory buffer.
|
|
*
|
|
* @param data_out [out,transfers] caller frees with zuptsdk_free()
|
|
* @param data_sz [out]
|
|
*/
|
|
int zuptsdk_extract_buffer(zuptsdk_ctx_t *ctx,
|
|
const uint8_t *archive, size_t archive_sz,
|
|
zuptsdk_secure_buf_t *password,
|
|
const zuptsdk_privkey_t *recipient_sk,
|
|
uint8_t **data_out, size_t *data_sz);
|
|
|
|
/* ════════════════════════════════════════════════════════════════════════
|
|
* COMPRESS / DECOMPRESS — streaming mode (for large archives)
|
|
* ════════════════════════════════════════════════════════════════════════ */
|
|
|
|
/**
|
|
* Compress from a read callback to a write callback. Streaming version
|
|
* with no archive size limit — suitable for piping to network sockets,
|
|
* encrypted volumes, or any backend with a write_fn.
|
|
*
|
|
* @param input [in] read callback supplying source bytes
|
|
* @param input_ud [in] userdata passed to read callback
|
|
* @param input_name [in] logical filename to record in archive
|
|
* @param input_total total bytes to read; 0 if unknown
|
|
* @param output [in] write callback receiving archive bytes
|
|
* @param output_ud [in] userdata passed to write callback
|
|
*/
|
|
int zuptsdk_compress_stream(zuptsdk_ctx_t *ctx,
|
|
const zuptsdk_options_t *opts,
|
|
zuptsdk_read_fn input, void *input_ud,
|
|
const char *input_name, uint64_t input_total,
|
|
zuptsdk_write_fn output, void *output_ud,
|
|
zuptsdk_secure_buf_t *password,
|
|
const zuptsdk_pubkey_t *recipient_pk);
|
|
|
|
/**
|
|
* Decompress an archive read from a callback, writing extracted single-file
|
|
* content to a write callback.
|
|
*/
|
|
int zuptsdk_decompress_stream(zuptsdk_ctx_t *ctx,
|
|
zuptsdk_read_fn input, void *input_ud,
|
|
zuptsdk_write_fn output, void *output_ud,
|
|
zuptsdk_secure_buf_t *password,
|
|
const zuptsdk_privkey_t *recipient_sk);
|
|
|
|
/* ════════════════════════════════════════════════════════════════════════
|
|
* VERIFY / INFO
|
|
* ════════════════════════════════════════════════════════════════════════ */
|
|
|
|
/**
|
|
* Verify all block checksums and (if encrypted) HMAC of an archive.
|
|
* No data is written to disk. Returns ZUPTSDK_OK if every block validates.
|
|
*/
|
|
int zuptsdk_verify(zuptsdk_ctx_t *ctx,
|
|
const uint8_t *archive, size_t archive_sz,
|
|
zuptsdk_secure_buf_t *password,
|
|
const zuptsdk_privkey_t *recipient_sk);
|
|
|
|
/**
|
|
* Read archive metadata without password or key. Returns header info only;
|
|
* does not decrypt block contents.
|
|
*
|
|
* @param info_out [out,transfers] receives info object;
|
|
* caller must zuptsdk_archive_info_destroy()
|
|
*/
|
|
int zuptsdk_archive_info_read(zuptsdk_ctx_t *ctx,
|
|
const uint8_t *archive, size_t archive_sz,
|
|
zuptsdk_archive_info_t **info_out);
|
|
|
|
void zuptsdk_archive_info_destroy(zuptsdk_archive_info_t *info);
|
|
|
|
/* Getters — opaque struct, all fields accessed via these functions. */
|
|
int zuptsdk_archive_info_format_major(const zuptsdk_archive_info_t *info);
|
|
int zuptsdk_archive_info_format_minor(const zuptsdk_archive_info_t *info);
|
|
const char *zuptsdk_archive_info_uuid(const zuptsdk_archive_info_t *info);
|
|
int64_t zuptsdk_archive_info_created_unix(const zuptsdk_archive_info_t *info);
|
|
uint64_t zuptsdk_archive_info_size(const zuptsdk_archive_info_t *info);
|
|
uint32_t zuptsdk_archive_info_block_count(const zuptsdk_archive_info_t *info);
|
|
int zuptsdk_archive_info_is_encrypted(const zuptsdk_archive_info_t *info);
|
|
int zuptsdk_archive_info_is_pq_hybrid(const zuptsdk_archive_info_t *info);
|
|
int zuptsdk_archive_info_is_solid(const zuptsdk_archive_info_t *info);
|
|
int zuptsdk_archive_info_is_dedup(const zuptsdk_archive_info_t *info);
|
|
int zuptsdk_archive_info_is_disk_image(const zuptsdk_archive_info_t *info);
|
|
|
|
/* ════════════════════════════════════════════════════════════════════════
|
|
* DISK BACKUP / RESTORE
|
|
* ════════════════════════════════════════════════════════════════════════ */
|
|
|
|
/**
|
|
* Backup a block device or disk image file to an archive.
|
|
* REQUIRES root/admin privileges to read raw block devices on most OSes.
|
|
*/
|
|
int zuptsdk_disk_backup(zuptsdk_ctx_t *ctx,
|
|
const zuptsdk_options_t *opts,
|
|
const char *source_device_or_image,
|
|
const char *output_archive_path,
|
|
zuptsdk_secure_buf_t *password,
|
|
const zuptsdk_pubkey_t *recipient_pk);
|
|
|
|
/**
|
|
* Restore a disk backup archive to a block device or image file.
|
|
* DESTRUCTIVE: target is overwritten without confirmation.
|
|
*/
|
|
int zuptsdk_disk_restore(zuptsdk_ctx_t *ctx,
|
|
const char *archive_path,
|
|
const char *target_device_or_image,
|
|
zuptsdk_secure_buf_t *password,
|
|
const zuptsdk_privkey_t *recipient_sk);
|
|
|
|
/* ════════════════════════════════════════════════════════════════════════
|
|
* MISC
|
|
* ════════════════════════════════════════════════════════════════════════ */
|
|
|
|
/**
|
|
* Free memory returned by the library via [transfers] output pointers.
|
|
* Safe to call with NULL.
|
|
*
|
|
* Always use this — never free() — for SDK-allocated memory, since the
|
|
* library may have been built with a custom allocator.
|
|
*/
|
|
void zuptsdk_free(void *ptr);
|
|
|
|
/**
|
|
* Best-effort secure zero of a buffer. Resistant to dead-store elimination
|
|
* by the optimizer. Use for caller-managed sensitive memory.
|
|
*/
|
|
void zuptsdk_secure_zero(void *buf, size_t bytes);
|
|
|
|
#ifdef __cplusplus
|
|
} /* extern "C" */
|
|
#endif
|
|
|
|
#endif /* ZUPTSDK_H */
|