#include #include "../lib.h" typedef uint16_t enc_t; typedef uint8_t plain_t; typedef int8_t sign_t; #define REPLICA_COUNT 3 #define check(vc, A, B) (((vc - B) % A) == 0) #define encode(v, A, B) ((((plain_t)v) * ((sign_t)A)) + ((sign_t)B)) #define decode(vc, A, B) ((vc - B) / A) #define equals(vc1, vc2, B1, B2) ((vc1 - vc2) == (B1 - B2)) #define THE_A 110 // CONSTANT Replica results signatures #define SIG_X 32 #define SIG_Y 23 #define SIG_Z 67 #define SIG_MAX SIG_Z // CONSTANT Voter Result Signatures #define SIG_s_XYZ ((SIG_X - SIG_Y) + (SIG_X - SIG_Z)) #define SIG_s_XY (SIG_X - SIG_Y) #define SIG_s_YZ (SIG_Y - SIG_Z) #define SIG_s_XZ (SIG_X - SIG_Z) #define XC sum_out[0] #define YC sum_out[1] #define ZC sum_out[2] static enc_t cored_res; static enc_t sum_out[REPLICA_COUNT]; static INLINE enc_t apply(enc_t vc, sign_t bdyn) { if (bdyn > SIG_MAX) { fail_marker_detected(); } return vc + bdyn; } static sign_t cored_vote(void) { if (equals(XC, YC, SIG_X, SIG_Y)) { if (equals(XC, ZC, SIG_X, SIG_Z)) { cored_res = apply(XC, (XC - YC) + (XC - ZC)); return SIG_s_XYZ; } else { cored_res = apply(XC, (XC - YC)); return SIG_s_XY; } } else if (equals(YC, ZC, SIG_Y, SIG_Z)) { cored_res = apply(YC, (YC - ZC)); return SIG_s_YZ; } else if (equals(XC, ZC, SIG_X, SIG_Z)) { cored_res = apply(XC, (XC - ZC)); return SIG_s_XZ; } else { fail_marker_detected(); return 0; } } template static INLINE void sum(void) { int sum = 0; for (int i = 0; i < 100; ++i) { sum += 1; } sum_out[N] = encode(sum, THE_A, S); } extern "C" int wasm_module(void) { XC = 0; YC = 0; ZC = 0; // TODO: Start trace from WASM? // - Simpler, as only a single wasm function has to be called for all // modules // - Doesn't inject wasm_runtime_call_wasm() setup fail_start_trace(); sum<0, SIG_X>(); sum<1, SIG_Y>(); sum<2, SIG_Z>(); sign_t static_sig = cored_vote(); fail_stop_trace(); sign_t vote_result_sig; switch (static_sig) { case SIG_s_XYZ: case SIG_s_XY: case SIG_s_XZ: vote_result_sig = SIG_X; break; case SIG_s_YZ: vote_result_sig = SIG_Y; break; default: break; } // Inversely apply constant program flow signature. cored_res -= static_sig; /* Validate Vote result */ if (!check(cored_res, THE_A, vote_result_sig)) { fail_marker_detected(); return 2; } plain_t res = decode(cored_res, THE_A, vote_result_sig); if (res == 100) { fail_marker_positive(); return 0; } else { fail_marker_negative(); return 1; } }