diff --git a/common/BigInteger.cpp b/common/BigInteger.cpp new file mode 100644 index 0000000..761457c --- /dev/null +++ b/common/BigInteger.cpp @@ -0,0 +1,87 @@ +#include "common/BigInteger.hpp" +#include +#include + +void BigIntegerAdd(void* a, void* b, void* c) { + SBigAdd(static_cast(a), static_cast(b), static_cast(c)); +} + +void BigIntegerAddInt(void* a, void* b, uint32_t c) { + BigData* c_; + SBigNew(&c_); + SBigFromUnsigned(c_, c); + + SBigAdd(static_cast(a), static_cast(b), c_); + + SBigDel(c_); +} + +uint32_t BigIntegerBitLen(void* num) { + uint32_t len; + SBigBitLen(static_cast(num), &len); + + return len; +} + +int32_t BigIntegerCmp(void* a, void* b) { + return SBigCompare(static_cast(a), static_cast(b)); +} + +int32_t BigIntegerCmpInt(void* a, uint32_t b) { + BigData* b_; + SBigNew(&b_); + SBigFromUnsigned(b_, b); + + auto result = SBigCompare(static_cast(a), b_); + + SBigDel(b_); + + return result; +} + +void BigIntegerFree(void* num) { + SBigDel(static_cast(num)); +} + +void* BigIntegerFromBytes(const uint8_t* data, uint32_t bytes) { + BigData* num; + SBigNew(&num); + SBigFromBinary(num, data, bytes); + + return num; +} + +void* BigIntegerFromInt(uint32_t val) { + BigData* num; + SBigNew(&num); + SBigFromUnsigned(num, val); + + return num; +} + +void BigIntegerMod(void* a, void* b, void* c) { + SBigMod(static_cast(a), static_cast(b), static_cast(c)); +} + +void BigIntegerModExp(void* a, void* b, void* c, void* d) { + SBigPowMod(static_cast(a), static_cast(b), static_cast(c), static_cast(d)); +} + +void BigIntegerMul(void* a, void* b, void* c) { + SBigMul(static_cast(a), static_cast(b), static_cast(c)); +} + +void BigIntegerSub(void* a, void* b, void* c) { + SBigSub(static_cast(a), static_cast(b), static_cast(c)); +} + +uint32_t BigIntegerToBytes(void* num, uint8_t* bytes, uint32_t maxBytes) { + uint32_t copiedBytes; + SBigToBinaryBuffer(static_cast(num), bytes, maxBytes, &copiedBytes); + + if (maxBytes > copiedBytes) { + memset(&bytes[copiedBytes], 0, maxBytes - copiedBytes); + } + + return copiedBytes; +} diff --git a/common/BigInteger.hpp b/common/BigInteger.hpp new file mode 100644 index 0000000..308c60b --- /dev/null +++ b/common/BigInteger.hpp @@ -0,0 +1,32 @@ +#ifndef COMMON_BIG_INTEGER_HPP +#define COMMON_BIG_INTEGER_HPP + +#include + +void BigIntegerAdd(void* a, void* b, void* c); + +void BigIntegerAddInt(void* a, void* b, uint32_t c); + +uint32_t BigIntegerBitLen(void* num); + +int32_t BigIntegerCmp(void* a, void* b); + +int32_t BigIntegerCmpInt(void* a, uint32_t b); + +void BigIntegerFree(void* num); + +void* BigIntegerFromBytes(const uint8_t* bytes, uint32_t len); + +void* BigIntegerFromInt(uint32_t val); + +void BigIntegerMod(void* a, void* b, void* c); + +void BigIntegerModExp(void* a, void* b, void* c, void* d); + +void BigIntegerMul(void* a, void* b, void* c); + +void BigIntegerSub(void* a, void* b, void* c); + +uint32_t BigIntegerToBytes(void* num, uint8_t* bytes, uint32_t maxBytes); + +#endif diff --git a/test/BigInteger.cpp b/test/BigInteger.cpp new file mode 100644 index 0000000..5bb35e2 --- /dev/null +++ b/test/BigInteger.cpp @@ -0,0 +1,177 @@ +#include "common/BigInteger.hpp" +#include "test/Test.hpp" + +TEST_CASE("BigIntegerAdd", "[biginteger]") { + SECTION("adds 0x10 to 0xFFFFFFFF") { + auto a = BigIntegerFromInt(0); + auto b = BigIntegerFromInt(0xFFFFFFFF); + auto c = BigIntegerFromInt(0x10); + + BigIntegerAdd(a, b, c); + + uint64_t a_; + BigIntegerToBytes(a, reinterpret_cast(&a_), sizeof(a_)); + + CHECK(a_ == 0x10000000F); + + BigIntegerFree(a); + BigIntegerFree(b); + BigIntegerFree(c); + } +} + +TEST_CASE("BigIntegerAddInt", "[biginteger]") { + SECTION("adds 0x10 to 0xFFFFFFFF") { + auto a = BigIntegerFromInt(0); + auto b = BigIntegerFromInt(0xFFFFFFFF); + + BigIntegerAddInt(a, b, 0x10); + + uint64_t a_; + BigIntegerToBytes(a, reinterpret_cast(&a_), sizeof(a_)); + + CHECK(a_ == 0x10000000F); + + BigIntegerFree(a); + BigIntegerFree(b); + } +} + +TEST_CASE("BigIntegerBitLen", "[biginteger]") { + SECTION("returns bit length of 0x1234567890") { + uint64_t bytes = 0x1234567890; + auto num = BigIntegerFromBytes(reinterpret_cast(&bytes), sizeof(bytes)); + + CHECK(BigIntegerBitLen(num) == 37); + + BigIntegerFree(num); + } +} + +TEST_CASE("BigIntegerCmp", "[biginteger]") { + SECTION("compares 10 and 1") { + auto a = BigIntegerFromInt(10); + auto b = BigIntegerFromInt(1); + + CHECK(BigIntegerCmp(a, b) == 1); + + BigIntegerFree(a); + BigIntegerFree(b); + } +} + +TEST_CASE("BigIntegerCmpInt", "[biginteger]") { + SECTION("compares 10 and 1") { + auto a = BigIntegerFromInt(10); + auto b = 1; + + CHECK(BigIntegerCmpInt(a, b) == 1); + + BigIntegerFree(a); + } +} + +TEST_CASE("BigIntegerFromBytes", "[biginteger]") { + SECTION("creates new biginteger from bytes") { + uint64_t bytes = 0x1234567890; + auto num = BigIntegerFromBytes(reinterpret_cast(&bytes), sizeof(bytes)); + + uint64_t num_; + BigIntegerToBytes(num, reinterpret_cast(&num_), sizeof(num_)); + + CHECK(num_ == 0x1234567890); + + BigIntegerFree(num); + } +} + +TEST_CASE("BigIntegerFromInt", "[biginteger]") { + SECTION("creates new biginteger from integer") { + auto num = BigIntegerFromInt(4); + + uint32_t num_; + BigIntegerToBytes(num, reinterpret_cast(&num_), sizeof(num_)); + + CHECK(num_ == 4); + + BigIntegerFree(num); + } +} + +TEST_CASE("BigIntegerMod", "[biginteger]") { + SECTION("mods 7 by 4") { + auto a = BigIntegerFromInt(0); + auto b = BigIntegerFromInt(7); + auto c = BigIntegerFromInt(4); + + BigIntegerMod(a, b, c); + + uint32_t a_; + BigIntegerToBytes(a, reinterpret_cast(&a_), sizeof(a_)); + + CHECK(a_ == 3); + + BigIntegerFree(a); + BigIntegerFree(b); + BigIntegerFree(c); + } +} + +TEST_CASE("BigIntegerModExp", "[biginteger]") { + SECTION("takes 256 to the 8th power and mods the result by 999") { + auto a = BigIntegerFromInt(0); + auto b = BigIntegerFromInt(256); + auto c = BigIntegerFromInt(8); + auto d = BigIntegerFromInt(999); + + BigIntegerModExp(a, b, c, d); + + uint32_t a_; + BigIntegerToBytes(a, reinterpret_cast(&a_), sizeof(a_)); + + CHECK(a_ == 160); + + BigIntegerFree(a); + BigIntegerFree(b); + BigIntegerFree(c); + BigIntegerFree(d); + } +} + +TEST_CASE("BigIntegerMul", "[biginteger]") { + SECTION("multiplies 0xFFFFFFFF and 0x100") { + auto a = BigIntegerFromInt(0); + auto b = BigIntegerFromInt(0xFFFFFFFF); + auto c = BigIntegerFromInt(0x100); + + BigIntegerMul(a, b, c); + + uint64_t a_; + BigIntegerToBytes(a, reinterpret_cast(&a_), sizeof(a_)); + + CHECK(a_ == 0xFFFFFFFF00); + + BigIntegerFree(a); + BigIntegerFree(b); + BigIntegerFree(c); + } +} + +TEST_CASE("BigIntegerSub", "[biginteger]") { + SECTION("subtracts 0xFF from 0xFFFF") { + auto a = BigIntegerFromInt(0); + auto b = BigIntegerFromInt(0xFFFF); + auto c = BigIntegerFromInt(0xFF); + + BigIntegerSub(a, b, c); + + uint32_t a_; + BigIntegerToBytes(a, reinterpret_cast(&a_), sizeof(a_)); + + CHECK(a_ == 0xFF00); + + BigIntegerFree(a); + BigIntegerFree(b); + BigIntegerFree(c); + } +}