#include "proof.h" #include #include #define MAX_HASH_LENGTH 64 static const uint8_t treeDepth = 5; #define PROOF_INITIALIZED_MAGIC 0x1234 struct proof_s { uint8_t currentStep; uint8_t hash[MAX_HASH_LENGTH]; size_t hashLength; hash_fn_t hashFn; uint16_t isInitialized; }; const uint8_t treeRoot[] = {0x25, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x25, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x25, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x25, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34}; proof_t *proof_create() { return malloc(sizeof(proof_t)); } bool proof_init(proof_t *proof, const uint8_t *data, size_t dataLength, const hash_fn_t hashFn) { explicit_bzero(&proof, sizeof(proof)); proof->isInitialized = PROOF_INITIALIZED_MAGIC; proof->hashFn = hashFn; proof->hashLength = sizeof(proof->hash); if (!proof->hashFn(data, dataLength, proof->hash, &proof->hashLength)) { return false; }; proof->currentStep = 1; return true; } /* In C it is fair to use macros if it makes code easier to read and/or less error prone. My favourite error is missing break in switch statement. Tote that macros can be used to affect build in features of the language. But care is necessary, there are various traps. */ #define CHECK_INITIALIZED(proof) {if ((proof)->isInitialized != PROOF_INITIALIZED_MAGIC) {return false;};} bool proof_step(proof_t *proof, const uint8_t *data, size_t dataLength) { CHECK_INITIALIZED(proof); // TODO: We check if the stored hash is in the list proof->hashLength = sizeof(proof->hash); if (!proof->hashFn(data, dataLength, proof->hash, &proof->hashLength)) { return false; }; proof->currentStep++; return true; } bool proof_finish(struct proof_s *proof) { return (proof->currentStep == treeDepth) && (sizeof(treeRoot) == proof->hashLength) && !memcmp(proof->hash, treeRoot, sizeof(treeRoot)); } void proof_release(proof_t *proof) { free(proof); } // Note the parenthesis, you may need them if, e.g. a is variable1 | variable 2 (bitwise or) #define MAX(a, b) ((a)>(b) ? (a):(b)) void macros_example() { uint8_t a_x=5; uint8_t a_y=1; uint8_t z = MAX(a_x++, a_y); //x increments twice switch (z) { //this is to avoid missing breaks / other errors #define CASE(g, h, i) case (g): {a_ ## i =(h); break;} CASE(1, 1, x); CASE(5, 5, y); CASE(6, 60, x); CASE(7, 70, y); #undef CASE default: a_x = 0; a_y = 0; } }