diff options
author | Micah Elizabeth Scott <beth@torproject.org> | 2023-05-25 17:37:52 -0700 |
---|---|---|
committer | Micah Elizabeth Scott <beth@torproject.org> | 2023-05-28 20:02:02 -0700 |
commit | 5a4f92ea7b9f743548e4dba8843b13fb258a7321 (patch) | |
tree | 705889ea50e26974c28be6469c927c0d163ee741 /src/ext/equix/hashx/include | |
parent | 6fd5ca491405807c0ac92ff9f343377b1c11a5c8 (diff) | |
download | tor-5a4f92ea7b9f743548e4dba8843b13fb258a7321.tar.gz tor-5a4f92ea7b9f743548e4dba8843b13fb258a7321.zip |
hashx: API changes to allow recovery from late compile failures
This is an API breaking change to hashx, which modifies the error
handling strategy. The main goal here is to allow unproblematic
recovery from hashx_compile failures.
hashx_alloc can no longer fail for reasons other than memory
allocation. All platform-specific compile failures are now reported via
hashx_make(), in order to both allow later failure and avoid requiring
users of the API to maintain and test multiple failure paths.
Note that late failures may be more common in actual use than early
failures. Early failures represent architectures other than x86_64 and
aarch64. Late failures could represent a number of system configurations
where syscalls are restricted.
The definition of a hashx context no longer tries to overlay storage for
the different types of program, and instead allows one context to always
contain an interpretable description of the program as well as an optional
buffer for compiled code.
The hashx_type enum is now used to mean either a specific type of hash
function or a type of hashx context. You can allocate a context for use
only with interpreted or compiled functions, or you can use
HASHX_TRY_COMPILE to prefer the compiler with an automatic fallback on
the interpreter. After calling hashx_make(), the new hashx_query_type()
can be used if needed to determine which implementation was actually
chosen.
The error return types have been overhauled so that everyone uses the
hashx_result enum, and seed failures vs compile failures are always
clearly distinguishable.
Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
Diffstat (limited to 'src/ext/equix/hashx/include')
-rw-r--r-- | src/ext/equix/hashx/include/hashx.h | 72 |
1 files changed, 54 insertions, 18 deletions
diff --git a/src/ext/equix/hashx/include/hashx.h b/src/ext/equix/hashx/include/hashx.h index 0d5521177a..2910515d9a 100644 --- a/src/ext/equix/hashx/include/hashx.h +++ b/src/ext/equix/hashx/include/hashx.h @@ -15,14 +15,13 @@ int main() { char seed[] = "this is a seed that will generate a hash function"; char hash[HASHX_SIZE]; - hashx_ctx* ctx = hashx_alloc(HASHX_COMPILED); - if (ctx == HASHX_NOTSUPP) - ctx = hashx_alloc(HASHX_INTERPRETED); + hashx_ctx* ctx = hashx_alloc(HASHX_TRY_COMPILE); if (ctx == NULL) return 1; - if (!hashx_make(ctx, seed, sizeof(seed))) + if (hashx_make(ctx, seed, sizeof(seed)) != EQUIX_OK) + return 1; + if (hashx_exec(ctx, 123456789, hash) != EQUIX_OK) return 1; - hashx_exec(ctx, 123456789, hash); hashx_free(ctx); for (unsigned i = 0; i < HASHX_SIZE; ++i) printf("%02x", hash[i] & 0xff); @@ -58,14 +57,21 @@ /* Opaque struct representing a HashX instance */ typedef struct hashx_ctx hashx_ctx; -/* Type of hash function */ +/* Type of hash context / type of compiled function */ typedef enum hashx_type { - HASHX_INTERPRETED, - HASHX_COMPILED + HASHX_TYPE_INTERPRETED = 1, /* Only the interpreted implementation */ + HASHX_TYPE_COMPILED, /* Require the compiler, fail if unavailable */ + HASHX_TRY_COMPILE, /* (hashx_alloc) Try compiler, don't require */ } hashx_type; -/* Sentinel value used to indicate unsupported type */ -#define HASHX_NOTSUPP ((hashx_ctx*)-1) +/* Result code for hashx_make and hashx_exec */ +typedef enum hashx_result { + HASHX_OK = 0, + HASHX_FAIL_UNPREPARED, /* Trying to run an unmade hash funciton */ + HASHX_FAIL_UNDEFINED, /* Unrecognized hashx_type enum value */ + HASHX_FAIL_SEED, /* Can't construct a hash function from this seed */ + HASHX_FAIL_COMPILE, /* Can't compile, and no fallback is enabled. */ +} hashx_result; #if defined(_WIN32) || defined(__CYGWIN__) #define HASHX_WIN @@ -100,35 +106,65 @@ extern "C" { * @param type is the type of instance to be created. * * @return pointer to a new HashX instance. Returns NULL on memory allocation - * failure and HASHX_NOTSUPP if the requested type is not supported. -*/ + * failures only. Other failures are reported in hashx_make. + */ HASHX_API hashx_ctx* hashx_alloc(hashx_type type); /* - * Create a new HashX function from seed. + * Create a new HashX function from a variable-length seed value. + * + * The seed value will be hashed internally in order to initialize the state + * of the HashX program generator and create a new unique hash function. * * @param ctx is pointer to a HashX instance. * @param seed is a pointer to the seed value. * @param size is the size of the seed. * - * @return 1 on success, 0 on failure. + * @return HASHX_OK on success, HASHX_FAIL_SEED if the specific seed is + * not associated with a valid hash program, and HASHX_FAIL_COMPILE + * if the compiler failed for OS-specific reasons and the interpreter + * fallback was disabled by allocating the context with + * HASHX_TYPE_COMPILED rather than HASHX_TRY_COMPILE. + */ +HASHX_API hashx_result hashx_make(hashx_ctx* ctx, + const void* seed, size_t size); + +/* + * Asks the specific implementation of a function created with hashx_make. + * + * This will equal the parameter to hashx_alloc() if a specific type was + * chosen there, but a context allocated with HASHX_TRY_COMPILE will allow + * the implementation to vary dynamically during hashx_make. + * + * @param ctx is pointer to a HashX instance. + * @param type_out is a pointer to which, on success, we write + * a HASHX_TYPE_* value. + * + * @return HASHX_OK on success, or HASHX_FAIL_UNPREPARED if hashx_make has not + * been invoked successfully on this context. */ -HASHX_API int hashx_make(hashx_ctx* ctx, const void* seed, size_t size); +HASHX_API hashx_result hashx_query_type(hashx_ctx* ctx, hashx_type *type_out); /* * Execute the HashX function. * * @param ctx is pointer to a HashX instance. A HashX function must have - * been previously created by calling hashx_make. + * been previously created by invoking hashx_make successfully. * @param HASHX_INPUT is the input to be hashed (see definition above). * @param output is a pointer to the result buffer. HASHX_SIZE bytes will be * written. - s*/ -HASHX_API void hashx_exec(const hashx_ctx* ctx, HASHX_INPUT, void* output); + * + * @return HASHX_OK on success, or HASHX_FAIL_UNPREPARED if hashx_make has not + * been invoked successfully on this context. + */ +HASHX_API hashx_result hashx_exec(const hashx_ctx* ctx, + HASHX_INPUT, void* output); /* * Free a HashX instance. * + * Has no effect if ctx is NULL. + * * @param ctx is pointer to a HashX instance. */ HASHX_API void hashx_free(hashx_ctx* ctx); |