-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bindings: Add C binding for SC::Hashing (sc_hashing)
- Loading branch information
Showing
8 changed files
with
261 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#include "../../Libraries/Testing/Testing.h" | ||
|
||
// Includes | ||
#include "sc_hashing/sc_hashing.h" | ||
|
||
// Tests | ||
extern "C" const char* sc_hashing_test(); | ||
|
||
namespace SC | ||
{ | ||
struct CBindingsTest; | ||
} | ||
|
||
struct SC::CBindingsTest : public SC::TestCase | ||
{ | ||
CBindingsTest(SC::TestReport& report) : TestCase(report, "CBindingsTest") | ||
{ | ||
using namespace SC; | ||
const char* res; | ||
if (test_section("Hashing")) | ||
{ | ||
res = sc_hashing_test(); | ||
recordExpectation(res ? StringView::fromNullTerminated(res, StringEncoding::Utf8) : "Hashing", | ||
res == nullptr); | ||
} | ||
} | ||
}; | ||
namespace SC | ||
{ | ||
void runCBindingsTest(SC::TestReport& report) { CBindingsTest test(report); } | ||
} // namespace SC |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
#include "sc_hashing.h" | ||
#include "../../../Libraries/Hashing/Hashing.h" | ||
|
||
SC::Hashing& sc_hashing_self(sc_hashing_t* hashing) | ||
{ | ||
static_assert(sizeof(sc_hashing_t::opaque) >= sizeof(SC::Hashing), "sc_hashing_t::opaque size"); | ||
static_assert(alignof(sc_hashing_t) >= alignof(SC::Hashing), "sc_hashing_t::opaque alignment"); | ||
return *reinterpret_cast<SC::Hashing*>(hashing->opaque); | ||
} | ||
|
||
extern "C" bool sc_hashing_init(sc_hashing_t* hashing, sc_hashing_type type) | ||
{ | ||
SC::Hashing& self = sc_hashing_self(hashing); | ||
placementNew(self); | ||
switch (type) | ||
{ | ||
case SC_HASHING_TYPE_MD5: return self.setType(SC::Hashing::TypeMD5); | ||
case SC_HASHING_TYPE_SHA1: return self.setType(SC::Hashing::TypeSHA1); | ||
case SC_HASHING_TYPE_SHA256: return self.setType(SC::Hashing::TypeSHA256); | ||
} | ||
return false; | ||
} | ||
|
||
extern "C" void sc_hashing_close(sc_hashing_t* hashing) { sc_hashing_self(hashing).~Hashing(); } | ||
|
||
extern "C" bool sc_hashing_add(sc_hashing_t* hashing, sc_hashing_span_t span) | ||
{ | ||
return sc_hashing_self(hashing).add({reinterpret_cast<const uint8_t*>(span.data), span.length}); | ||
} | ||
|
||
extern "C" bool sc_hashing_get(sc_hashing_t* hashing, sc_hashing_result_t* result) | ||
{ | ||
static_assert(sizeof(sc_hashing_result_t) == sizeof(SC::Hashing::Result), "sc_hashing_result_t size"); | ||
static_assert(alignof(sc_hashing_result_t) == alignof(SC::Hashing::Result), "sc_hashing_result_t alignment"); | ||
return sc_hashing_self(hashing).getHash(*reinterpret_cast<SC::Hashing::Result*>(result)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
// Copyright (c) Stefano Cristiano | ||
// SPDX-License-Identifier: MIT | ||
#if !defined(SANE_CPP_LIBRARIES_HASHING) | ||
#define SANE_CPP_LIBRARIES_HASHING 1 | ||
#include <stdbool.h> // bool | ||
#include <stddef.h> // size_t | ||
#include <stdint.h> // uint64_t | ||
|
||
//! @defgroup group_c_bindings C Bindings | ||
//! @brief C bindings for all libraries | ||
|
||
//! @defgroup group_sc_hashing sc_hashing | ||
//! @ingroup group_c_bindings | ||
|
||
//! @addtogroup group_sc_hashing | ||
//! @brief C bindings for @ref library_hashing library | ||
/// | ||
/// Sample usage: | ||
/// @code{.c} | ||
/// sc_hashing_t ctx; | ||
/// bool res; | ||
/// res = sc_hashing_init(&ctx, type); | ||
/// res = sc_hashing_add(&ctx, (sc_hashing_span_t){.data = "test", .length = strlen("test")}); | ||
/// res = sc_hashing_add(&ctx, (sc_hashing_span_t){.data = "data", .length = strlen("data")}); | ||
/// sc_hashing_result_t result; | ||
/// sc_hashing_get(&ctx, &result); | ||
/// //... use result.hash | ||
/// sc_hashing_close(&ctx); | ||
/// @endcode | ||
|
||
//! @{ | ||
|
||
#if _MSC_VER | ||
#define SANE_CPP_NO_DISCARD | ||
#else | ||
#define SANE_CPP_NO_DISCARD __attribute__((warn_unused_result)) | ||
#endif | ||
// clang-format off | ||
#ifdef __cplusplus | ||
extern "C" | ||
{ | ||
#endif | ||
|
||
/// @brief Type of hashing algorithm to use | ||
typedef enum | ||
{ | ||
SC_HASHING_TYPE_MD5, ///< Computes MD5 Hash | ||
SC_HASHING_TYPE_SHA1, ///< Computes SHA1 Hash | ||
SC_HASHING_TYPE_SHA256 ///< Computes SHA256 Hash | ||
} sc_hashing_type; | ||
|
||
/// @brief Opaque object holding state of hashing | ||
typedef struct | ||
{ | ||
uint64_t opaque[14]; | ||
} sc_hashing_t; | ||
|
||
/// @brief Hash result | ||
typedef struct | ||
{ | ||
uint8_t hash[32]; ///< Contains the computed hash of length size | ||
size_t size; ///< Length of the computed hash | ||
} sc_hashing_result_t; | ||
|
||
/// @brief Just a generic data span | ||
typedef struct | ||
{ | ||
const void* data; ///< Pointer to data | ||
size_t length; ///< Length of the data (in bytes) | ||
} sc_hashing_span_t; | ||
|
||
/// @brief Initializes OS objects to compute hash (call sc_hashing_close when done). | ||
SANE_CPP_NO_DISCARD bool sc_hashing_init(sc_hashing_t* hashing, sc_hashing_type type); | ||
|
||
/// @brief Releases os resources allocated by sc_hashing_init. | ||
void sc_hashing_close(sc_hashing_t* hashing); | ||
|
||
/// @brief Add data to hash computation. Can be called multiple times to hash data iteratively. | ||
SANE_CPP_NO_DISCARD bool sc_hashing_add(sc_hashing_t* hashing, sc_hashing_span_t span); | ||
|
||
/// @brief Obtain the actual hash of data added through sc_hashing_add. | ||
SANE_CPP_NO_DISCARD bool sc_hashing_get(sc_hashing_t* hashing, sc_hashing_result_t* result); | ||
|
||
#ifdef __cplusplus | ||
} // extern "C" | ||
#endif | ||
// clang-format on | ||
|
||
#undef SANE_CPP_NO_DISCARD | ||
//! @} | ||
|
||
#endif // SANE_CPP_LIBRARIES_HASHING |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
// Copyright (c) Stefano Cristiano | ||
// SPDX-License-Identifier: MIT | ||
#include "sc_hashing.h" | ||
#include <assert.h> | ||
#include <string.h> | ||
|
||
#define SC_TEST_EXPECT(a) \ | ||
if (!(a)) \ | ||
{ \ | ||
assert(a); \ | ||
return #a; \ | ||
} | ||
|
||
const char* sc_hashing_test_init(sc_hashing_type type, const uint8_t* expected, const size_t expected_size, bool update) | ||
{ | ||
sc_hashing_t ctx; | ||
SC_TEST_EXPECT(sc_hashing_init(&ctx, type)); | ||
SC_TEST_EXPECT(sc_hashing_add(&ctx, (sc_hashing_span_t){.data = "test", .length = strlen("test")})); | ||
if (update) | ||
{ | ||
SC_TEST_EXPECT(sc_hashing_add(&ctx, (sc_hashing_span_t){.data = "test", .length = strlen("test")})); | ||
} | ||
sc_hashing_result_t result; | ||
SC_TEST_EXPECT(sc_hashing_get(&ctx, &result)); | ||
SC_TEST_EXPECT(result.size == expected_size); | ||
SC_TEST_EXPECT(memcmp(result.hash, expected, result.size) == 0); | ||
sc_hashing_close(&ctx); | ||
return 0; | ||
} | ||
|
||
const char* sc_hashing_test(void) | ||
{ | ||
const char* res; | ||
const uint8_t md5_expected[] = {0x09, 0x8F, 0x6B, 0xCD, 0x46, 0x21, 0xD3, 0x73, | ||
0xCA, 0xDE, 0x4E, 0x83, 0x26, 0x27, 0xB4, 0xF6}; | ||
|
||
res = sc_hashing_test_init(SC_HASHING_TYPE_MD5, md5_expected, sizeof(md5_expected), false); | ||
if (res) | ||
return res; | ||
|
||
const uint8_t sha1_expected[] = {0xA9, 0x4A, 0x8F, 0xE5, 0xCC, 0xB1, 0x9B, 0xA6, 0x1C, 0x4C, | ||
0x08, 0x73, 0xD3, 0x91, 0xE9, 0x87, 0x98, 0x2F, 0xBB, 0xD3}; | ||
|
||
res = sc_hashing_test_init(SC_HASHING_TYPE_SHA1, sha1_expected, sizeof(sha1_expected), false); | ||
if (res) | ||
return res; | ||
|
||
const uint8_t sha256_expected[] = {0x9F, 0x86, 0xD0, 0x81, 0x88, 0x4C, 0x7D, 0x65, 0x9A, 0x2F, 0xEA, | ||
0xA0, 0xC5, 0x5A, 0xD0, 0x15, 0xA3, 0xBF, 0x4F, 0x1B, 0x2B, 0x0B, | ||
0x82, 0x2C, 0xD1, 0x5D, 0x6C, 0x15, 0xB0, 0xF0, 0x0A, 0x08}; | ||
|
||
res = sc_hashing_test_init(SC_HASHING_TYPE_SHA256, sha256_expected, sizeof(sha256_expected), false); | ||
if (res) | ||
return res; | ||
|
||
const uint8_t md5_expected2[] = {0x05, 0xA6, 0x71, 0xC6, 0x6A, 0xEF, 0xEA, 0x12, | ||
0x4C, 0xC0, 0x8B, 0x76, 0xEA, 0x6D, 0x30, 0xBB}; | ||
|
||
res = sc_hashing_test_init(SC_HASHING_TYPE_MD5, md5_expected2, sizeof(md5_expected2), true); | ||
if (res) | ||
return res; | ||
|
||
const uint8_t sha1_expected2[] = {0x51, 0xAB, 0xB9, 0x63, 0x60, 0x78, 0xDE, 0xFB, 0xF8, 0x88, | ||
0xD8, 0x45, 0x7A, 0x7C, 0x76, 0xF8, 0x5C, 0x8F, 0x11, 0x4C}; | ||
|
||
res = sc_hashing_test_init(SC_HASHING_TYPE_SHA1, sha1_expected2, sizeof(sha1_expected2), true); | ||
if (res) | ||
return res; | ||
|
||
const uint8_t sha256_expected2[] = {0x37, 0x26, 0x83, 0x35, 0xDD, 0x69, 0x31, 0x04, 0x5B, 0xDC, 0xDF, | ||
0x92, 0x62, 0x3F, 0xF8, 0x19, 0xA6, 0x42, 0x44, 0xB5, 0x3D, 0x0E, | ||
0x74, 0x6D, 0x43, 0x87, 0x97, 0x34, 0x9D, 0x4D, 0xA5, 0x78}; | ||
|
||
res = sc_hashing_test_init(SC_HASHING_TYPE_SHA256, sha256_expected2, sizeof(sha256_expected2), true); | ||
if (res) | ||
return res; | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters