/* * OCaml bindings for SHA256 C implementation. * Uses custom blocks and bigarrays for zero-copy performance. */ #include #include #include #include #include #include #include #include "sha256.h" /* Custom block operations for SHA256_CTX */ static void oxsha_ctx_finalize(value v_ctx) { SHA256_CTX *ctx = (SHA256_CTX *)Data_custom_val(v_ctx); /* Just clear the memory for security */ memset(ctx, 0, sizeof(SHA256_CTX)); } static struct custom_operations oxsha_ctx_ops = { "com.oxsha.sha256_ctx", oxsha_ctx_finalize, custom_compare_default, custom_hash_default, custom_serialize_default, custom_deserialize_default, custom_compare_ext_default, custom_fixed_length_default }; /* Allocate and wrap a SHA256_CTX in an OCaml custom block */ static value alloc_oxsha_ctx(void) { value v_ctx = caml_alloc_custom(&oxsha_ctx_ops, sizeof(SHA256_CTX), 0, 1); return v_ctx; } /* Extract SHA256_CTX pointer from OCaml value */ #define Oxsha_ctx_val(v) ((SHA256_CTX *)Data_custom_val(v)) /* FFI Functions */ /* oxsha_create : unit -> t */ CAMLprim value oxsha_create(value unit) { CAMLparam1(unit); CAMLlocal1(v_ctx); v_ctx = alloc_oxsha_ctx(); SHA256_CTX *ctx = Oxsha_ctx_val(v_ctx); sha256_init(ctx); CAMLreturn(v_ctx); } /* oxsha_update : t -> bigarray -> unit */ CAMLprim value oxsha_update(value v_ctx, value v_data) { CAMLparam2(v_ctx, v_data); SHA256_CTX *ctx = Oxsha_ctx_val(v_ctx); /* Extract bigarray data pointer and length */ unsigned char *data = (unsigned char *)Caml_ba_data_val(v_data); size_t len = Caml_ba_array_val(v_data)->dim[0]; sha256_update(ctx, data, len); CAMLreturn(Val_unit); } /* oxsha_final : t -> bytes */ CAMLprim value oxsha_final(value v_ctx) { CAMLparam1(v_ctx); CAMLlocal1(v_digest); SHA256_CTX *ctx = Oxsha_ctx_val(v_ctx); /* Allocate bytes for the 32-byte digest */ v_digest = caml_alloc_string(SHA256_BLOCK_SIZE); unsigned char *digest = (unsigned char *)String_val(v_digest); sha256_final(ctx, digest); CAMLreturn(v_digest); }