Tor 0.4.9.2-alpha-dev
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
equix.c
1/* Copyright (c) 2020 tevador <tevador@gmail.com> */
2/* See LICENSE for licensing information */
3
4#include <stdlib.h>
5#include <stdbool.h>
6#include <string.h>
7#include <assert.h>
8
9#include <equix.h>
10#include <hashx.h>
11#include "context.h"
12#include "solver.h"
13#include <hashx_endian.h>
14
15static bool verify_order(const equix_solution* solution) {
16 return
17 tree_cmp4(&solution->idx[0], &solution->idx[4]) &&
18 tree_cmp2(&solution->idx[0], &solution->idx[2]) &&
19 tree_cmp2(&solution->idx[4], &solution->idx[6]) &&
20 tree_cmp1(&solution->idx[0], &solution->idx[1]) &&
21 tree_cmp1(&solution->idx[2], &solution->idx[3]) &&
22 tree_cmp1(&solution->idx[4], &solution->idx[5]) &&
23 tree_cmp1(&solution->idx[6], &solution->idx[7]);
24}
25
26static uint64_t sum_pair(hashx_ctx* hash_func, equix_idx left, equix_idx right) {
27 uint8_t hash_left[HASHX_SIZE];
28 uint8_t hash_right[HASHX_SIZE];
29 hashx_result r_left = hashx_exec(hash_func, left, hash_left);
30 hashx_result r_right = hashx_exec(hash_func, right, hash_right);
31 if (r_left == HASHX_OK && r_right == HASHX_OK) {
32 return load64(hash_left) + load64(hash_right);
33 }
34 assert(false);
35 return ~(uint64_t)0;
36}
37
38static equix_result verify_internal(hashx_ctx* hash_func, const equix_solution* solution) {
39 uint64_t pair0 = sum_pair(hash_func, solution->idx[0], solution->idx[1]);
40 if (pair0 & EQUIX_STAGE1_MASK) {
41 return EQUIX_FAIL_PARTIAL_SUM;
42 }
43 uint64_t pair1 = sum_pair(hash_func, solution->idx[2], solution->idx[3]);
44 if (pair1 & EQUIX_STAGE1_MASK) {
45 return EQUIX_FAIL_PARTIAL_SUM;
46 }
47 uint64_t pair4 = pair0 + pair1;
48 if (pair4 & EQUIX_STAGE2_MASK) {
49 return EQUIX_FAIL_PARTIAL_SUM;
50 }
51 uint64_t pair2 = sum_pair(hash_func, solution->idx[4], solution->idx[5]);
52 if (pair2 & EQUIX_STAGE1_MASK) {
53 return EQUIX_FAIL_PARTIAL_SUM;
54 }
55 uint64_t pair3 = sum_pair(hash_func, solution->idx[6], solution->idx[7]);
56 if (pair3 & EQUIX_STAGE1_MASK) {
57 return EQUIX_FAIL_PARTIAL_SUM;
58 }
59 uint64_t pair5 = pair2 + pair3;
60 if (pair5 & EQUIX_STAGE2_MASK) {
61 return EQUIX_FAIL_PARTIAL_SUM;
62 }
63 uint64_t pair6 = pair4 + pair5;
64 if (pair6 & EQUIX_FULL_MASK) {
65 return EQUIX_FAIL_FINAL_SUM;
66 }
67 return EQUIX_OK;
68}
69
70static equix_result equix_hashx_make(
71 equix_ctx* ctx,
72 const void* challenge,
73 size_t challenge_size)
74{
75 switch (hashx_make(ctx->hash_func, challenge, challenge_size)) {
76 case HASHX_OK:
77 return EQUIX_OK;
78 case HASHX_FAIL_SEED:
79 return EQUIX_FAIL_CHALLENGE;
80 case HASHX_FAIL_COMPILE:
81 return EQUIX_FAIL_COMPILE;
82 case HASHX_FAIL_UNDEFINED:
83 case HASHX_FAIL_UNPREPARED:
84 default:
85 return EQUIX_FAIL_INTERNAL;
86 }
87}
88
89equix_result equix_solve(
90 equix_ctx* ctx,
91 const void* challenge,
92 size_t challenge_size,
94{
95 if ((ctx->flags & EQUIX_CTX_SOLVE) == 0) {
96 return EQUIX_FAIL_NO_SOLVER;
97 }
98
99 equix_result result = equix_hashx_make(ctx, challenge, challenge_size);
100 if (result != EQUIX_OK) {
101 return result;
102 }
103
104 output->flags = 0;
105 hashx_type func_type;
106 if (hashx_query_type(ctx->hash_func, &func_type) == HASHX_OK &&
107 func_type == HASHX_TYPE_COMPILED) {
108 output->flags |= EQUIX_SOLVER_DID_USE_COMPILER;
109 }
110
111 output->count = equix_solver_solve(ctx->hash_func, ctx->heap, output->sols);
112 return EQUIX_OK;
113}
114
115equix_result equix_verify(
116 equix_ctx* ctx,
117 const void* challenge,
118 size_t challenge_size,
119 const equix_solution* solution)
120{
121 if (!verify_order(solution)) {
122 return EQUIX_FAIL_ORDER;
123 }
124
125 equix_result result = equix_hashx_make(ctx, challenge, challenge_size);
126 if (result != EQUIX_OK) {
127 return result;
128 }
129
130 return verify_internal(ctx->hash_func, solution);
131}