commit f0383c92942287433ee06f314b50593a13663077 Author: Stanislav N Mikhailov Date: Mon Mar 9 18:35:43 2026 +0300 Initial SHA256 test harness diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9bbf35a --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +build/* +!build/Debug/ +build/Debug/* +!build/Debug/*.exe +!build/Debug/*.dll diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..bb8a657 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.20) +project(sha256_client_c LANGUAGES C) + +if(NOT WIN32) + message(FATAL_ERROR "This sample is intended for Win64 (DLL import).") +endif() + +add_executable(sha256_client + src/main.c +) + +target_include_directories(sha256_client PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/include +) + +target_link_libraries(sha256_client PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/dll/sha-256.lib +) + +add_custom_command(TARGET sha256_client POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${CMAKE_CURRENT_SOURCE_DIR}/dll/sha-256.dll + $/sha-256.dll +) diff --git a/build/Debug/sha-256.dll b/build/Debug/sha-256.dll new file mode 100644 index 0000000..a4863bc Binary files /dev/null and b/build/Debug/sha-256.dll differ diff --git a/build/Debug/sha256_client.exe b/build/Debug/sha256_client.exe new file mode 100644 index 0000000..834c41c Binary files /dev/null and b/build/Debug/sha256_client.exe differ diff --git a/dll/sha-256.dll b/dll/sha-256.dll new file mode 100644 index 0000000..a4863bc Binary files /dev/null and b/dll/sha-256.dll differ diff --git a/dll/sha-256.lib b/dll/sha-256.lib new file mode 100644 index 0000000..d66ca90 Binary files /dev/null and b/dll/sha-256.lib differ diff --git a/include/sha.h b/include/sha.h new file mode 100644 index 0000000..dbe8084 --- /dev/null +++ b/include/sha.h @@ -0,0 +1,48 @@ +#ifndef SHA256_SHA_H +#define SHA256_SHA_H + +#include +#include + +#ifdef _WIN32 + #ifdef SHA256_EXPORTS + #define SHA256_API __declspec(dllexport) + #else + #define SHA256_API __declspec(dllimport) + #endif +#else + #define SHA256_API +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint32_t sha256_digest_t[8]; + +SHA256_API int TestHello(void); + +/* + * Returns NULL (0) on success according to assembly comments. + * data_addr - pointer to current data chunk. + * full_size - total message/file size in bytes. + * current_size - current chunk size in bytes. + * digest - 32-byte state/result buffer (8 x uint32_t). + * is_last_chunk - 1 if this is the last chunk, otherwise 0. + */ +SHA256_API void *Sha256( + const void *data_addr, + uint64_t full_size, + uint64_t current_size, + sha256_digest_t digest, + uint64_t is_last_chunk +); + +/* Initializes digest and internal K constants. */ +SHA256_API void Sha256Init(sha256_digest_t digest); + +#ifdef __cplusplus +} +#endif + +#endif /* SHA256_SHA_H */ diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..d116190 --- /dev/null +++ b/src/main.c @@ -0,0 +1,95 @@ +#include +#include +#include +#include + +#include "sha.h" + +static void print_digest_words(const sha256_digest_t digest) { + for (int i = 0; i < 8; ++i) { + printf("%08x", digest[i]); + } + putchar('\n'); +} + +int main(void) { + char path[4096] = {0}; + sha256_digest_t digest = {0}; + + if (fgets(path, (int)sizeof(path), stdin) == NULL) { + fprintf(stderr, "Failed to read file path from stdin\n"); + return 1; + } + + path[strcspn(path, "\r\n")] = '\0'; + if (path[0] == '\0') { + fprintf(stderr, "Empty file path\n"); + return 1; + } + + FILE *fp = fopen(path, "rb"); + if (fp == NULL) { + fprintf(stderr, "Failed to open file: %s\n", path); + return 1; + } + + if (_fseeki64(fp, 0, SEEK_END) != 0) { + fprintf(stderr, "Failed to seek file end: %s\n", path); + fclose(fp); + return 1; + } + + const long long file_size_ll = _ftelli64(fp); + if (file_size_ll < 0) { + fprintf(stderr, "Failed to get file size: %s\n", path); + fclose(fp); + return 1; + } + + if (_fseeki64(fp, 0, SEEK_SET) != 0) { + fprintf(stderr, "Failed to seek file start: %s\n", path); + fclose(fp); + return 1; + } + + const uint64_t full_size = (uint64_t)file_size_ll; + size_t alloc_size = (size_t)full_size; + if ((uint64_t)alloc_size != full_size) { + fprintf(stderr, "File is too large for this client: %s\n", path); + fclose(fp); + return 1; + } + if (alloc_size == 0) { + alloc_size = 1; + } + + unsigned char *data = (unsigned char *)malloc(alloc_size); + if (data == NULL) { + fprintf(stderr, "Out of memory while reading: %s\n", path); + fclose(fp); + return 1; + } + + if (full_size > 0) { + const size_t read_size = fread(data, 1, (size_t)full_size, fp); + if (read_size != (size_t)full_size) { + fprintf(stderr, "Failed to read file: %s\n", path); + free(data); + fclose(fp); + return 1; + } + } + fclose(fp); + + void *rc = Sha256(data, full_size, full_size, digest, 1); + free(data); + if (rc != 0) { + fprintf(stderr, "Sha256 failed, rc=%p\n", rc); + return 1; + } + + printf("Digest (library word order): "); + print_digest_words(digest); + + return 0; +}