Merge lp:~rene-hummen/hipl/puzzle-fixes into lp:hipl
- puzzle-fixes
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~rene-hummen/hipl/puzzle-fixes |
Merge into: | lp:hipl |
Diff against target: |
901 lines (+416/-152) 17 files modified
Makefile.am (+1/-0) hipd/cookie.c (+11/-7) hipd/cookie.h (+2/-2) hipd/input.c (+10/-9) hipd/keymat.c (+10/-11) hipd/keymat.h (+3/-1) hipd/output.c (+4/-5) lib/core/builder.c (+5/-4) lib/core/builder.h (+2/-2) lib/core/protodefs.h (+7/-3) lib/core/solve.c (+162/-93) lib/core/solve.h (+15/-5) lib/core/state.h (+2/-2) lib/tool/pk.c (+10/-8) test/check_lib_core.c (+1/-0) test/lib/core/solve.c (+170/-0) test/lib/core/test_suites.h (+1/-0) |
To merge this branch: | bzr merge lp:~rene-hummen/hipl/puzzle-fixes |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Miika Komu | Needs Information | ||
Christof Mroz | Needs Fixing | ||
Review via email: mp+56811@code.launchpad.net |
This proposal has been superseded by a proposal from 2011-04-08.
Commit message
Description of the change
This branch refactors HIPL's puzzle handling functionality and generalizes the API for use with the midauth extension. It has been tested with unit tests and on virtual machines.
Christof Mroz (christof-mroz) wrote : | # |
On Thu, 07 Apr 2011 21:59:22 +0200, Christof Mroz
<email address hidden> wrote:
>> + /* we are interested in the 8 least significant bytes */
>> + truncated_digest = *(uint32_t *) &sha_digest[
>> sizeof(uint32_t)];
>
> The 8 least significant bytes have index 0..7. Also, sizeof(uint32_t) is
> 4, not 8.
Note: I'm aware that things look differently if you interpret the digest
as a big-endian number with SHA_DIGEST_LENGTH * 8 bits; what I'm trying to
say here is: if that's what you meant in the comment, then you should
state it more verbosely (i.e. mention byte order).
Miika Komu (miika-iki) wrote : | # |
The algorithm seems changed. Did you test it against the old, interoperable implementation?
- 5855. By René Hummen
-
remove write-only variables solved_puzzle and I
- 5859. By René Hummen
-
fix forward declaration in unit-tests for lib/core/solve.c
- 5860. By René Hummen
-
make difficulty > max_puzzle_
difficulty an error - 5861. By René Hummen
-
add missing doxygen documentation
- 5862. By René Hummen
-
replace uint64_t by uint8_t[8] for puzzle and solution values
puzzle and solution values are bit.fields and do not need to be
interpreted. Hence, uint64_t is not the correct data type and
leads to endianess problems for these values. - 5863. By René Hummen
-
allow for early exit for puzzle difficulty 0
- 5864. By René Hummen
-
reflect API changes in unit-tests
- 5865. By René Hummen
-
clarify comments of on endianness
- 5866. By René Hummen
-
merged with trunk revision 5854
- 5867. By René Hummen
-
fix comparison of solution and puzzle values
- 5868. By René Hummen
-
reorder includes as suggested by Diego
- 5869. By René Hummen
-
fix doxygen comments
- 5870. By René Hummen
-
convert HIP_IFEL into if statement
- 5871. By René Hummen
-
reorder parameters of hip_verify_
puzzle_ solution( ) - 5872. By René Hummen
-
change type of puzzle difficulty from int to uint8_t
The puzzle difficulty is transported as uint8_t on the wire.
- 5873. By René Hummen
-
address comments and improvements by Stefan
- 5874. By René Hummen
-
fix unit-tests according to previous changes
- 5875. By René Hummen
-
add solution verification unit-test for real/captured solution
- 5876. By René Hummen
-
replace ipv6_addr_copy() by simple assignment
- 5877. By René Hummen
-
declare sha_digest as a local variable
- 5878. By René Hummen
-
improve documentation of MAX_PUZZLE_
DIFFICULTY - 5879. By René Hummen
-
replace ipv6_addr_copy() by an assignment
- 5880. By René Hummen
-
minor change in local var ordering
- 5881. By René Hummen
-
change year of copyright
- 5882. By René Hummen
-
use struct puzzle_hash_input in puzzle api
- 5883. By René Hummen
-
fix doxygen
- 5884. By René Hummen
-
change output type from int to uint
- 5885. By René Hummen
-
directly exit hip_solve_puzzle instead of using break indirection
- 5886. By René Hummen
-
merge trunk revision 5878
Unmerged revisions
- 5886. By René Hummen
-
merge trunk revision 5878
- 5885. By René Hummen
-
directly exit hip_solve_puzzle instead of using break indirection
- 5884. By René Hummen
-
change output type from int to uint
- 5883. By René Hummen
-
fix doxygen
- 5882. By René Hummen
-
use struct puzzle_hash_input in puzzle api
- 5881. By René Hummen
-
change year of copyright
- 5880. By René Hummen
-
minor change in local var ordering
- 5879. By René Hummen
-
replace ipv6_addr_copy() by an assignment
- 5878. By René Hummen
-
improve documentation of MAX_PUZZLE_
DIFFICULTY - 5877. By René Hummen
-
declare sha_digest as a local variable
Preview Diff
1 | === modified file 'Makefile.am' |
2 | --- Makefile.am 2011-04-06 15:52:33 +0000 |
3 | +++ Makefile.am 2011-04-08 15:38:33 +0000 |
4 | @@ -207,6 +207,7 @@ |
5 | |
6 | test_check_lib_core_SOURCES = test/check_lib_core.c \ |
7 | test/lib/core/hit.c \ |
8 | + test/lib/core/solve.c \ |
9 | test/lib/core/straddr.c |
10 | |
11 | test_check_lib_tool_SOURCES = test/check_lib_tool.c \ |
12 | |
13 | === modified file 'hipd/cookie.c' |
14 | --- hipd/cookie.c 2011-04-05 16:44:22 +0000 |
15 | +++ hipd/cookie.c 2011-04-08 15:38:33 +0000 |
16 | @@ -56,7 +56,7 @@ |
17 | |
18 | #define HIP_R1TABLESIZE 3 /* precreate only this many R1s */ |
19 | |
20 | -static int hip_cookie_difficulty = 1ULL; /* a difficulty of i leads to approx. 2^(i-1) hash computations during BEX */ |
21 | +static int hip_cookie_difficulty = 0; /* a difficulty of i leads to approx. 2^(i-1) hash computations during BEX */ |
22 | |
23 | /** |
24 | * query for current puzzle difficulty |
25 | @@ -77,9 +77,9 @@ |
26 | */ |
27 | static int hip_set_cookie_difficulty(int k) |
28 | { |
29 | - if (k > HIP_PUZZLE_MAX_K || k < 1) { |
30 | + if (k > max_puzzle_difficulty || k < 0) { |
31 | HIP_ERROR("Bad cookie value (%d), min=%d, max=%d\n", |
32 | - k, 1, HIP_PUZZLE_MAX_K); |
33 | + k, 1, max_puzzle_difficulty); |
34 | return -1; |
35 | } |
36 | hip_cookie_difficulty = k; |
37 | @@ -347,7 +347,7 @@ |
38 | |
39 | HIP_IFEL(solution->K != result->Ck, -1, |
40 | "Solution's K did not match any sent Ks.\n"); |
41 | - HIP_IFEL(solution->I != result->Ci, -1, |
42 | + HIP_IFEL(memcmp(solution->I, result->Ci, PUZZLE_LENGTH), -1, |
43 | "Solution's I did not match the sent I\n"); |
44 | HIP_IFEL(memcmp(solution->opaque, result->Copaque, |
45 | HIP_PUZZLE_OPAQUE_LEN), -1, |
46 | @@ -356,15 +356,19 @@ |
47 | } else { |
48 | HIP_HEXDUMP("solution", solution, sizeof(*solution)); |
49 | HIP_HEXDUMP("puzzle", puzzle, sizeof(*puzzle)); |
50 | - HIP_IFEL(solution->I != puzzle->I, -1, |
51 | + HIP_IFEL(memcmp(solution->I, puzzle->I, PUZZLE_LENGTH), -1, |
52 | "Solution's I did not match the sent I\n"); |
53 | HIP_IFEL(memcmp(solution->opaque, puzzle->opaque, |
54 | HIP_PUZZLE_OPAQUE_LEN), -1, |
55 | "Solution's opaque data does not match the opaque data sent\n"); |
56 | } |
57 | |
58 | - HIP_IFEL(!hip_solve_puzzle(solution, hdr, HIP_VERIFY_PUZZLE), -1, |
59 | - "Puzzle incorrectly solved.\n"); |
60 | + HIP_IFEL(hip_verify_puzzle_solution(solution->I, |
61 | + solution->K, |
62 | + hdr->hits, |
63 | + hdr->hitr, |
64 | + solution->J), |
65 | + -1, "Puzzle incorrectly solved.\n"); |
66 | |
67 | out_err: |
68 | return err; |
69 | |
70 | === modified file 'hipd/cookie.h' |
71 | --- hipd/cookie.h 2011-01-10 13:12:17 +0000 |
72 | +++ hipd/cookie.h 2011-04-08 15:38:33 +0000 |
73 | @@ -34,9 +34,9 @@ |
74 | struct hip_r1entry { |
75 | struct hip_common *r1; |
76 | uint32_t generation; |
77 | - uint64_t Ci; |
78 | + uint8_t Ci[PUZZLE_LENGTH]; |
79 | uint8_t Ck; |
80 | - uint8_t Copaque[3]; |
81 | + uint8_t Copaque[HIP_PUZZLE_OPAQUE_LEN]; |
82 | }; |
83 | |
84 | struct hip_common *hip_get_r1(struct in6_addr *ip_i, |
85 | |
86 | === modified file 'hipd/input.c' |
87 | --- hipd/input.c 2011-04-08 08:47:50 +0000 |
88 | +++ hipd/input.c 2011-04-08 15:38:33 +0000 |
89 | @@ -235,8 +235,8 @@ |
90 | * @return zero on success, or negative on error. |
91 | */ |
92 | static int hip_produce_keying_material(struct hip_packet_context *ctx, |
93 | - uint64_t I, |
94 | - uint64_t J) |
95 | + const uint8_t I[PUZZLE_LENGTH], |
96 | + const uint8_t J[PUZZLE_LENGTH]) |
97 | { |
98 | char *dh_shared_key = NULL; |
99 | int hip_transf_length, hmac_transf_length; |
100 | @@ -868,16 +868,17 @@ |
101 | /* Solve puzzle: if this is a retransmission, we have to preserve |
102 | * the old solution. */ |
103 | if (!retransmission) { |
104 | - const struct hip_puzzle *pz2 = NULL; |
105 | + const struct hip_puzzle *pz = NULL; |
106 | |
107 | - HIP_IFEL(!(pz2 = hip_get_param(ctx->input_msg, HIP_PARAM_PUZZLE)), -EINVAL, |
108 | + HIP_IFEL(!(pz = hip_get_param(ctx->input_msg, HIP_PARAM_PUZZLE)), -EINVAL, |
109 | "Malformed R1 packet. PUZZLE parameter missing\n"); |
110 | - HIP_IFEL((ctx->hadb_entry->puzzle_solution = |
111 | - hip_solve_puzzle(pz2, |
112 | - ctx->input_msg, |
113 | - HIP_SOLVE_PUZZLE)) == 0, |
114 | + HIP_IFEL(hip_solve_puzzle(pz->I, |
115 | + pz->K, |
116 | + ctx->input_msg->hitr, |
117 | + ctx->input_msg->hits, |
118 | + ctx->hadb_entry->puzzle_solution), |
119 | -EINVAL, "Solving of puzzle failed\n"); |
120 | - ctx->hadb_entry->puzzle_i = pz2->I; |
121 | + memcpy(ctx->hadb_entry->puzzle_i, pz->I, PUZZLE_LENGTH); |
122 | } |
123 | |
124 | HIP_DEBUG("Build normal I2.\n"); |
125 | |
126 | === modified file 'hipd/keymat.c' |
127 | --- hipd/keymat.c 2011-01-11 13:59:46 +0000 |
128 | +++ hipd/keymat.c 2011-04-08 15:38:33 +0000 |
129 | @@ -58,19 +58,18 @@ |
130 | static uint8_t *hip_create_keymat_buffer(char *kij, size_t kij_len, size_t hash_len, |
131 | struct in6_addr *smaller_hit, |
132 | struct in6_addr *bigger_hit, |
133 | - uint64_t I, uint64_t J) |
134 | + const uint8_t I[PUZZLE_LENGTH], |
135 | + const uint8_t J[PUZZLE_LENGTH]) |
136 | |
137 | { |
138 | uint8_t *buffer = NULL, *cur = NULL; |
139 | size_t requiredmem; |
140 | |
141 | - HIP_DEBUG("\n"); |
142 | - /* 2*sizeof(uint64_t) added to take care of I and J. */ |
143 | if (2 * sizeof(struct in6_addr) < hash_len) { |
144 | - requiredmem = kij_len + hash_len + sizeof(uint8_t) + 2 * sizeof(uint64_t); |
145 | + requiredmem = kij_len + hash_len + sizeof(uint8_t) + 2 * PUZZLE_LENGTH; |
146 | } else { |
147 | requiredmem = kij_len + 2 * sizeof(struct in6_addr) + |
148 | - sizeof(uint8_t) + 2 * sizeof(uint64_t); |
149 | + sizeof(uint8_t) + 2 * PUZZLE_LENGTH; |
150 | } |
151 | buffer = malloc(requiredmem); |
152 | if (!buffer) { |
153 | @@ -85,10 +84,10 @@ |
154 | cur += sizeof(struct in6_addr); |
155 | memcpy(cur, (uint8_t *) bigger_hit, sizeof(struct in6_addr)); |
156 | cur += sizeof(struct in6_addr); |
157 | - memcpy(cur, &I, sizeof(uint64_t)); // XX CHECK: network byte order? |
158 | - cur += sizeof(uint64_t); |
159 | - memcpy(cur, &J, sizeof(uint64_t)); // XX CHECK: network byte order? |
160 | - cur += sizeof(uint64_t); |
161 | + memcpy(cur, I, PUZZLE_LENGTH); |
162 | + cur += PUZZLE_LENGTH; |
163 | + memcpy(cur, J, PUZZLE_LENGTH); |
164 | + cur += PUZZLE_LENGTH; |
165 | *(cur) = 1; |
166 | cur += sizeof(uint8_t); |
167 | |
168 | @@ -138,8 +137,8 @@ |
169 | struct in6_addr *hit1, |
170 | struct in6_addr *hit2, |
171 | uint8_t *calc_index, |
172 | - uint64_t I, |
173 | - uint64_t J) |
174 | + const uint8_t I[PUZZLE_LENGTH], |
175 | + const uint8_t J[PUZZLE_LENGTH]) |
176 | { |
177 | int bufsize; |
178 | uint8_t index_nbr = 1; |
179 | |
180 | === modified file 'hipd/keymat.h' |
181 | --- hipd/keymat.h 2010-10-15 15:29:14 +0000 |
182 | +++ hipd/keymat.h 2011-04-08 15:38:33 +0000 |
183 | @@ -37,7 +37,9 @@ |
184 | void hip_make_keymat(char *kij, size_t kij_len, |
185 | struct hip_keymat_keymat *keymat, |
186 | void *dstbuf, size_t dstbuflen, struct in6_addr *hit1, |
187 | - struct in6_addr *hit2, uint8_t *calc_index, uint64_t I, uint64_t J); |
188 | + struct in6_addr *hit2, uint8_t *calc_index, |
189 | + const uint8_t I[PUZZLE_LENGTH], |
190 | + const uint8_t J[PUZZLE_LENGTH]); |
191 | int hip_keymat_draw_and_copy(unsigned char *dst, |
192 | struct hip_keymat_keymat *keymat, |
193 | int len); |
194 | |
195 | === modified file 'hipd/output.c' |
196 | --- hipd/output.c 2011-04-06 09:07:51 +0000 |
197 | +++ hipd/output.c 2011-04-08 15:38:33 +0000 |
198 | @@ -636,8 +636,10 @@ |
199 | /********** R1_COUNTER (OPTIONAL) *********/ |
200 | |
201 | /********** PUZZLE ************/ |
202 | + const uint8_t zero_i[PUZZLE_LENGTH] = { 0 }; |
203 | + |
204 | HIP_IFEL(hip_build_param_puzzle(err, cookie_k, |
205 | - 42 /* 2^(42-32) sec lifetime */, 0, 0), |
206 | + 42 /* 2^(42-32) sec lifetime */, 0, zero_i), |
207 | NULL, "Cookies were burned. Bummer!\n"); |
208 | |
209 | /* Parameter Diffie-Hellman */ |
210 | @@ -702,7 +704,6 @@ |
211 | /* Fill puzzle parameters */ |
212 | { |
213 | struct hip_puzzle *pz; |
214 | - uint64_t random_i; |
215 | |
216 | HIP_IFEL(!(pz = hip_get_param_readwrite(err, HIP_PARAM_PUZZLE)), NULL, |
217 | "Internal error\n"); |
218 | @@ -711,9 +712,7 @@ |
219 | pz->opaque[0] = 'H'; |
220 | pz->opaque[1] = 'I'; |
221 | //pz->opaque[2] = 'P'; |
222 | - /** @todo Remove random_i variable. */ |
223 | - get_random_bytes(&random_i, sizeof(random_i)); |
224 | - pz->I = random_i; |
225 | + get_random_bytes(pz->I, PUZZLE_LENGTH); |
226 | } |
227 | |
228 | /* Packet ready */ |
229 | |
230 | === modified file 'lib/core/builder.c' |
231 | --- lib/core/builder.c 2011-04-07 16:58:58 +0000 |
232 | +++ lib/core/builder.c 2011-04-08 15:38:33 +0000 |
233 | @@ -2385,7 +2385,8 @@ |
234 | * @return zero for success, or non-zero on error |
235 | */ |
236 | int hip_build_param_puzzle(struct hip_common *msg, uint8_t val_K, |
237 | - uint8_t lifetime, uint32_t opaque, uint64_t random_i) |
238 | + uint8_t lifetime, uint32_t opaque, |
239 | + const uint8_t random_i[PUZZLE_LENGTH]) |
240 | { |
241 | struct hip_puzzle puzzle; |
242 | int err = 0; |
243 | @@ -2402,7 +2403,7 @@ |
244 | puzzle.lifetime = lifetime; |
245 | puzzle.opaque[0] = opaque & 0xFF; |
246 | puzzle.opaque[1] = (opaque & 0xFF00) >> 8; |
247 | - puzzle.I = random_i; |
248 | + memcpy(puzzle.I, random_i, PUZZLE_LENGTH); |
249 | |
250 | err = hip_build_generic_param(msg, &puzzle, |
251 | sizeof(struct hip_tlv_common), |
252 | @@ -2515,7 +2516,7 @@ |
253 | */ |
254 | int hip_build_param_solution(struct hip_common *msg, |
255 | const struct hip_puzzle *pz, |
256 | - uint64_t val_J) |
257 | + uint8_t val_J[PUZZLE_LENGTH]) |
258 | { |
259 | struct hip_solution cookie; |
260 | int err = 0; |
261 | @@ -2527,7 +2528,7 @@ |
262 | /* Type 2 (in R1) or 3 (in I2) */ |
263 | hip_set_param_type((struct hip_tlv_common *) &cookie, HIP_PARAM_SOLUTION); |
264 | |
265 | - cookie.J = val_J; |
266 | + memcpy(cookie.J, val_J, PUZZLE_LENGTH); |
267 | memcpy(&cookie.K, &pz->K, 12); /* copy: K (1), reserved (1), |
268 | * opaque (2) and I (8 bytes). */ |
269 | cookie.reserved = 0; |
270 | |
271 | === modified file 'lib/core/builder.h' |
272 | --- lib/core/builder.h 2011-04-02 20:38:36 +0000 |
273 | +++ lib/core/builder.h 2011-04-08 15:38:33 +0000 |
274 | @@ -130,7 +130,7 @@ |
275 | uint8_t, |
276 | uint8_t, |
277 | uint32_t, |
278 | - uint64_t); |
279 | + const uint8_t *); |
280 | |
281 | int hip_build_param_challenge_request(struct hip_common *, |
282 | uint8_t, |
283 | @@ -150,7 +150,7 @@ |
284 | uint8_t); |
285 | int hip_build_param_solution(struct hip_common *, |
286 | const struct hip_puzzle *, |
287 | - uint64_t); |
288 | + uint8_t *); |
289 | |
290 | int hip_build_param_challenge_response(struct hip_common *, |
291 | const struct hip_challenge_request *, |
292 | |
293 | === modified file 'lib/core/protodefs.h' |
294 | --- lib/core/protodefs.h 2011-02-04 14:44:37 +0000 |
295 | +++ lib/core/protodefs.h 2011-04-08 15:38:33 +0000 |
296 | @@ -737,13 +737,17 @@ |
297 | uint64_t generation; |
298 | } __attribute__ ((packed)); |
299 | |
300 | + |
301 | +/* puzzle and solutions are defined to have a length of 8 bytes */ |
302 | +#define PUZZLE_LENGTH 8 |
303 | + |
304 | struct hip_puzzle { |
305 | hip_tlv type; |
306 | hip_tlv_len length; |
307 | uint8_t K; |
308 | uint8_t lifetime; |
309 | uint8_t opaque[HIP_PUZZLE_OPAQUE_LEN]; |
310 | - uint64_t I; |
311 | + uint8_t I[PUZZLE_LENGTH]; |
312 | } __attribute__ ((packed)); |
313 | |
314 | struct hip_solution { |
315 | @@ -752,8 +756,8 @@ |
316 | uint8_t K; |
317 | uint8_t reserved; |
318 | uint8_t opaque[HIP_PUZZLE_OPAQUE_LEN]; |
319 | - uint64_t I; |
320 | - uint64_t J; |
321 | + uint8_t I[PUZZLE_LENGTH]; |
322 | + uint8_t J[PUZZLE_LENGTH]; |
323 | } __attribute__ ((packed)); |
324 | |
325 | |
326 | |
327 | === modified file 'lib/core/solve.c' |
328 | --- lib/core/solve.c 2011-01-24 10:21:17 +0000 |
329 | +++ lib/core/solve.c 2011-04-08 15:38:33 +0000 |
330 | @@ -28,11 +28,14 @@ |
331 | * @brief HIP computation puzzle solving algorithms |
332 | * |
333 | * @author Miika Komu <miika@iki.fi> |
334 | + * @author Rene Hummen |
335 | */ |
336 | |
337 | #include <errno.h> |
338 | +#include <openssl/rand.h> |
339 | #include <stdint.h> |
340 | #include <string.h> |
341 | +#include <strings.h> |
342 | |
343 | #include "config.h" |
344 | #include "builder.h" |
345 | @@ -43,104 +46,170 @@ |
346 | #include "protodefs.h" |
347 | #include "solve.h" |
348 | |
349 | +struct puzzle_common { |
350 | + uint8_t puzzle[PUZZLE_LENGTH]; |
351 | + hip_hit_t initiator_hit; |
352 | + hip_hit_t responder_hit; |
353 | + uint8_t solution[PUZZLE_LENGTH]; |
354 | +} __attribute__ ((packed)); |
355 | + |
356 | +// max. 2^max_puzzle_difficulty tries to solve a puzzle |
357 | +#define MAX_PUZZLE_SOLUTION_TRIES 1ULL << max_puzzle_difficulty |
358 | + |
359 | /** |
360 | - * solve a computational puzzle for HIP |
361 | - * |
362 | - * @param puzzle_or_solution Either a pointer to hip_puzzle or hip_solution structure |
363 | - * @param hdr The incoming R1/I2 packet header. |
364 | - * @param mode Either HIP_VERIFY_PUZZLE of HIP_SOLVE_PUZZLE |
365 | - * |
366 | - * @note The K and I is read from the @c puzzle_or_solution. |
367 | - * @note Regarding to return value of zero, I don't see why 0 couldn't solve the |
368 | - * puzzle too, but since the odds are 1/2^64 to try 0, I don't see the point |
369 | - * in improving this now. |
370 | - * @return The J that solves the puzzle is returned, or 0 to indicate an error. |
371 | + * Computes a single iteration for a computational puzzle |
372 | + * |
373 | + * @param compute_puzzle puzzle to be solved or verified |
374 | + * @param sha_digest buffer for hash digest |
375 | + * @param difficulty difficulty of the puzzle (number of leading zeros) |
376 | + * @return 0 when hash has >= #difficulty least significant bits as zeros, 1 |
377 | + * when hash has < #difficulty least significant bits as zeros, |
378 | + * -1 in case of an error |
379 | */ |
380 | -uint64_t hip_solve_puzzle(const void *puzzle_or_solution, |
381 | - const struct hip_common *hdr, |
382 | - int mode) |
383 | +static int hip_calculate_puzzle_solution(const struct puzzle_common *const compute_puzzle, |
384 | + unsigned char sha_digest[SHA_DIGEST_LENGTH], |
385 | + const int difficulty) |
386 | { |
387 | - uint64_t mask = 0; |
388 | - uint64_t randval = 0; |
389 | - uint64_t maxtries = 0; |
390 | - uint64_t digest = 0; |
391 | - uint8_t cookie[48]; |
392 | - int err = 0; |
393 | - const union { |
394 | - struct hip_puzzle pz; |
395 | - struct hip_solution sl; |
396 | - } *u; |
397 | - |
398 | - HIP_HEXDUMP("puzzle", puzzle_or_solution, |
399 | - (mode == HIP_VERIFY_PUZZLE ? sizeof(struct hip_solution) : |
400 | - sizeof(struct hip_puzzle))); |
401 | - |
402 | - /* pre-create cookie */ |
403 | - u = puzzle_or_solution; |
404 | - |
405 | - HIP_IFEL(u->pz.K > HIP_PUZZLE_MAX_K, 0, |
406 | - "Cookie K %u is higher than we are willing to calculate" |
407 | - " (current max K=%d)\n", u->pz.K, HIP_PUZZLE_MAX_K); |
408 | - |
409 | - mask = hton64((1ULL << u->pz.K) - 1); |
410 | - memcpy(cookie, &u->pz.I, sizeof(uint64_t)); |
411 | - |
412 | - HIP_DEBUG("(u->pz.I: 0x%llx\n", u->pz.I); |
413 | - |
414 | - if (mode == HIP_VERIFY_PUZZLE) { |
415 | - ipv6_addr_copy((hip_hit_t *) (cookie + 8), &hdr->hits); |
416 | - ipv6_addr_copy((hip_hit_t *) (cookie + 24), &hdr->hitr); |
417 | - randval = u->sl.J; |
418 | - maxtries = 1; |
419 | - } else if (mode == HIP_SOLVE_PUZZLE) { |
420 | - ipv6_addr_copy((hip_hit_t *) (cookie + 8), &hdr->hitr); |
421 | - ipv6_addr_copy((hip_hit_t *) (cookie + 24), &hdr->hits); |
422 | - maxtries = 1ULL << (u->pz.K + 3); |
423 | - get_random_bytes(&randval, sizeof(uint64_t)); |
424 | + uint32_t truncated_digest = 0; |
425 | + int err = -1; |
426 | + |
427 | + /* any puzzle solution is acceptable for difficulty 0 */ |
428 | + if (difficulty == 0) { |
429 | + return 0; |
430 | + } |
431 | + |
432 | + HIP_IFEL(difficulty > max_puzzle_difficulty, |
433 | + -1, "difficulty exceeds max. configured difficulty\n"); |
434 | + |
435 | + HIP_IFEL(hip_build_digest(HIP_DIGEST_SHA1, |
436 | + compute_puzzle, |
437 | + sizeof(struct puzzle_common), |
438 | + sha_digest), |
439 | + -1, "failed to compute hash digest\n"); |
440 | + |
441 | + /* we are interested in least significant bytes in network byte-order */ |
442 | + truncated_digest = *(uint32_t *) &sha_digest[SHA_DIGEST_LENGTH - sizeof(uint32_t)]; |
443 | + |
444 | + /* make sure to interpret the solution equally across platforms |
445 | + * (i.e., network byte-order), when calculating puzzle solution */ |
446 | + truncated_digest = htonl(truncated_digest); |
447 | + |
448 | + /* check if position of first least significant 1-bit is higher than |
449 | + * difficulty */ |
450 | + if (ffs(truncated_digest) > difficulty) { |
451 | + err = 0; |
452 | } else { |
453 | - HIP_OUT_ERR(0, "Unknown mode: %d\n", mode); |
454 | - } |
455 | - |
456 | - HIP_DEBUG("K=%u, maxtries (with k+2)=%llu\n", u->pz.K, maxtries); |
457 | - /* while loops should work even if the maxtries is unsigned |
458 | - * if maxtries = 1 ---> while(1 > 0) [maxtries == 0 now]... |
459 | - * the next round while (0 > 0) [maxtries > 0 now] |
460 | - */ |
461 | - while (maxtries-- > 0) { |
462 | - uint8_t sha_digest[HIP_AH_SHA_LEN]; |
463 | - |
464 | - /* must be 8 */ |
465 | - memcpy(cookie + 40, (uint8_t *) &randval, sizeof(uint64_t)); |
466 | - |
467 | - hip_build_digest(HIP_DIGEST_SHA1, cookie, 48, sha_digest); |
468 | - |
469 | - /* copy the last 8 bytes for checking */ |
470 | - memcpy(&digest, sha_digest + 12, sizeof(uint64_t)); |
471 | - |
472 | - /* now, in order to be able to do correctly the bitwise |
473 | - * AND-operation we have to remember that little endian |
474 | - * processors will interpret the digest and mask reversely. |
475 | - * digest is the last 64 bits of the sha1-digest.. how that is |
476 | - * ordered in processors registers etc.. does not matter to us. |
477 | - * If the last 64 bits of the sha1-digest is |
478 | - * 0x12345678DEADBEEF, whether we have 0xEFBEADDE78563412 |
479 | - * doesn't matter because the mask matters... if the mask is |
480 | - * 0x000000000000FFFF (or in other endianness |
481 | - * 0xFFFF000000000000). Either ways... the result is |
482 | - * 0x000000000000BEEF or 0xEFBE000000000000, which the cpu |
483 | - * interprets as 0xBEEF. The mask is converted to network byte |
484 | - * order (above). |
485 | - */ |
486 | - if ((digest & mask) == 0) { |
487 | - return randval; |
488 | + err = 1; |
489 | + } |
490 | + |
491 | +out_err: |
492 | + return err; |
493 | +} |
494 | + |
495 | +/** |
496 | + * Solve a computational puzzle for HIP |
497 | + * |
498 | + * @param puzzle puzzle to be solved |
499 | + * @param difficulty difficulty of the puzzle |
500 | + * @param initiator_hit initiator HIT of the message exchange |
501 | + * @param responder_hit responder HIT of the message exchange |
502 | + * @param solution computed puzzle solution |
503 | + * @return 0 when solution was found, 1 in case no solution was found after |
504 | + * MAX_PUZZLE_SOLUTION_TRIES, -1 in case of an error |
505 | + */ |
506 | +int hip_solve_puzzle(const uint8_t puzzle[PUZZLE_LENGTH], |
507 | + const int difficulty, |
508 | + const hip_hit_t initiator_hit, |
509 | + const hip_hit_t responder_hit, |
510 | + uint8_t solution[PUZZLE_LENGTH]) |
511 | +{ |
512 | + struct puzzle_common compute_puzzle; |
513 | + unsigned char sha_digest[SHA_DIGEST_LENGTH]; |
514 | + int err = -1; |
515 | + uint32_t i = 0; |
516 | + |
517 | + HIP_IFEL(!solution, -1, "invalid parameter passed (NULL)\n"); |
518 | + |
519 | + HIP_IFEL(difficulty > max_puzzle_difficulty, -1, |
520 | + "Cookie (K = %i) is higher than we are willing to calculate" |
521 | + " (current max K = %i)\n", difficulty, max_puzzle_difficulty); |
522 | + |
523 | + /* solution is correct iff: |
524 | + * 0 == V := Ltrunc( RHASH( I2.I | I2.hit_i | I2.hit_r | I2.J ), K ) |
525 | + * (RFC 5201 - Appendix A) */ |
526 | + memcpy(compute_puzzle.puzzle, puzzle, PUZZLE_LENGTH); |
527 | + ipv6_addr_copy(&compute_puzzle.initiator_hit, &initiator_hit); |
528 | + ipv6_addr_copy(&compute_puzzle.responder_hit, &responder_hit); |
529 | + RAND_bytes(compute_puzzle.solution, PUZZLE_LENGTH); |
530 | + |
531 | + // any puzzle solution is acceptable for difficulty 0 |
532 | + if (difficulty == 0) { |
533 | + return 0; |
534 | + } |
535 | + |
536 | + for (i = 0; i < MAX_PUZZLE_SOLUTION_TRIES; i++) { |
537 | + // now do the computations |
538 | + err = hip_calculate_puzzle_solution(&compute_puzzle, |
539 | + sha_digest, |
540 | + difficulty); |
541 | + if (err == 0) { |
542 | + memcpy(solution, compute_puzzle.solution, PUZZLE_LENGTH); |
543 | + break; |
544 | + } else if (err > 0) { |
545 | + // increase random value by one and try again |
546 | + (*(uint64_t *) compute_puzzle.solution)++; |
547 | + } else { |
548 | + memset(solution, 0, PUZZLE_LENGTH); |
549 | + break; |
550 | } |
551 | - |
552 | - /* It seems like the puzzle was not correctly solved */ |
553 | - HIP_IFEL(mode == HIP_VERIFY_PUZZLE, 0, "Puzzle incorrect\n"); |
554 | - randval++; |
555 | - } |
556 | - |
557 | - HIP_ERROR("Could not solve the puzzle, no solution found\n"); |
558 | + } |
559 | + |
560 | +out_err: |
561 | + if (i == MAX_PUZZLE_SOLUTION_TRIES) { |
562 | + HIP_ERROR("Could not solve the puzzle, no solution found\n"); |
563 | + } |
564 | + |
565 | + return err; |
566 | +} |
567 | + |
568 | +/** |
569 | + * Verify a computational puzzle for HIP |
570 | + * |
571 | + * @param puzzle puzzle to be verified |
572 | + * @param difficulty difficulty of the puzzle |
573 | + * @param initiator_hit initiator HIT of the message exchange |
574 | + * @param responder_hit responder HIT of the message exchange |
575 | + * @param solution puzzle solution to be verified |
576 | + * @return 0 when solution is correct, -1 otherwise |
577 | + */ |
578 | +int hip_verify_puzzle_solution(const uint8_t puzzle[PUZZLE_LENGTH], |
579 | + const uint8_t difficulty, |
580 | + const hip_hit_t initiator_hit, |
581 | + const hip_hit_t responder_hit, |
582 | + const uint8_t solution[PUZZLE_LENGTH]) |
583 | +{ |
584 | + struct puzzle_common compute_puzzle; |
585 | + unsigned char sha_digest[SHA_DIGEST_LENGTH]; |
586 | + int err = 0; |
587 | + |
588 | + // any puzzle solution is acceptable for difficulty 0 |
589 | + if (difficulty == 0) { |
590 | + return 0; |
591 | + } |
592 | + |
593 | + /* solution is correct iff: |
594 | + * 0 == V := Ltrunc( RHASH( I2.I | I2.hit_i | I2.hit_r | I2.J ), K ) |
595 | + * (RFC 5201 - Appendix A) */ |
596 | + memcpy(compute_puzzle.puzzle, puzzle, PUZZLE_LENGTH); |
597 | + ipv6_addr_copy(&compute_puzzle.initiator_hit, &initiator_hit); |
598 | + ipv6_addr_copy(&compute_puzzle.responder_hit, &responder_hit); |
599 | + memcpy(compute_puzzle.solution, solution, PUZZLE_LENGTH); |
600 | + |
601 | + HIP_IFEL(hip_calculate_puzzle_solution(&compute_puzzle, |
602 | + sha_digest, |
603 | + difficulty), |
604 | + -1, "failed to verify puzzle solution\n"); |
605 | + |
606 | out_err: |
607 | return err; |
608 | } |
609 | |
610 | === modified file 'lib/core/solve.h' |
611 | --- lib/core/solve.h 2010-10-15 15:29:14 +0000 |
612 | +++ lib/core/solve.h 2011-04-08 15:38:33 +0000 |
613 | @@ -30,10 +30,20 @@ |
614 | |
615 | #include "protodefs.h" |
616 | |
617 | -#define HIP_PUZZLE_MAX_K 28 |
618 | - |
619 | -uint64_t hip_solve_puzzle(const void *puzzle, |
620 | - const struct hip_common *hdr, int mode); |
621 | -int hip_solve_puzzle_m(struct hip_common *out, struct hip_common *in); |
622 | +/* right now we only support difficulties up to sizeof(int), as only ffs |
623 | + * is available on OpenWRT */ |
624 | +static const int max_puzzle_difficulty = sizeof(int) * 8 >= 28 ? 28 : sizeof(int) * 8; |
625 | + |
626 | +int hip_solve_puzzle(const uint8_t puzzle[PUZZLE_LENGTH], |
627 | + const int difficulty, |
628 | + const hip_hit_t initiator_hit, |
629 | + const hip_hit_t responder_hit, |
630 | + uint8_t solution[PUZZLE_LENGTH]); |
631 | + |
632 | +int hip_verify_puzzle_solution(const uint8_t puzzle[PUZZLE_LENGTH], |
633 | + const uint8_t difficulty, |
634 | + const hip_hit_t initiator_hit, |
635 | + const hip_hit_t responder_hit, |
636 | + const uint8_t solution[PUZZLE_LENGTH]); |
637 | |
638 | #endif /* HIP_LIB_CORE_SOLVE_H */ |
639 | |
640 | === modified file 'lib/core/state.h' |
641 | --- lib/core/state.h 2011-02-06 09:03:39 +0000 |
642 | +++ lib/core/state.h 2011-04-08 15:38:33 +0000 |
643 | @@ -294,13 +294,13 @@ |
644 | /** A function pointer to a function that verifies peer's host identity. */ |
645 | int (*verify)(void *, struct hip_common *); |
646 | /** For retransmission. */ |
647 | - uint64_t puzzle_solution; |
648 | + uint8_t puzzle_solution[PUZZLE_LENGTH]; |
649 | /** LOCATOR parameter. Just tmp save if sent in R1 no @c esp_info so |
650 | * keeping it here 'till the hip_update_locator_parameter can be done. |
651 | * @todo Remove this kludge. */ |
652 | struct hip_locator *locator; |
653 | /** For retransmission. */ |
654 | - uint64_t puzzle_i; |
655 | + uint8_t puzzle_i[PUZZLE_LENGTH]; |
656 | /** Used for UPDATE and CLOSE. When we sent multiple identical UPDATE |
657 | * packets between different address combinations, we don't modify |
658 | * the opaque data. */ |
659 | |
660 | === modified file 'lib/tool/pk.c' |
661 | --- lib/tool/pk.c 2011-04-04 13:59:21 +0000 |
662 | +++ lib/tool/pk.c 2011-04-08 15:38:33 +0000 |
663 | @@ -131,8 +131,8 @@ |
664 | uint8_t sha1_digest[HIP_AH_SHA_LEN]; |
665 | struct in6_addr tmpaddr; |
666 | struct hip_puzzle *pz = NULL; |
667 | - uint8_t opaque[3]; |
668 | - uint64_t randi = 0; |
669 | + uint8_t opaque[HIP_PUZZLE_OPAQUE_LEN]; |
670 | + uint8_t rand_i[PUZZLE_LENGTH]; |
671 | |
672 | ipv6_addr_copy(&tmpaddr, &msg->hitr); /* so update is handled, too */ |
673 | |
674 | @@ -146,11 +146,13 @@ |
675 | |
676 | HIP_IFEL(!(pz = hip_get_param_readwrite(msg, HIP_PARAM_PUZZLE)), |
677 | -ENOENT, "Illegal R1 packet (puzzle missing)\n"); |
678 | - memcpy(opaque, pz->opaque, sizeof(pz->opaque)); |
679 | - randi = pz->I; |
680 | |
681 | - memset(pz->opaque, 0, sizeof(pz->opaque)); |
682 | - pz->I = 0; |
683 | + /* temporarily store original puzzle values */ |
684 | + memcpy(opaque, pz->opaque, HIP_PUZZLE_OPAQUE_LEN); |
685 | + memcpy(rand_i, pz->I, PUZZLE_LENGTH); |
686 | + /* R1 signature is computed over zero values */ |
687 | + memset(pz->opaque, 0, HIP_PUZZLE_OPAQUE_LEN); |
688 | + memset(pz->I, 0, PUZZLE_LENGTH); |
689 | } else { |
690 | HIP_IFEL(!(sig = hip_get_param_readwrite(msg, HIP_PARAM_HIP_SIGNATURE)), |
691 | -ENOENT, "Could not find signature\n"); |
692 | @@ -182,8 +184,8 @@ |
693 | #endif |
694 | |
695 | if (hip_get_msg_type(msg) == HIP_R1) { |
696 | - memcpy(pz->opaque, opaque, sizeof(pz->opaque)); |
697 | - pz->I = randi; |
698 | + memcpy(pz->opaque, opaque, HIP_PUZZLE_OPAQUE_LEN); |
699 | + memcpy(pz->I, rand_i, PUZZLE_LENGTH); |
700 | } |
701 | |
702 | ipv6_addr_copy(&msg->hitr, &tmpaddr); |
703 | |
704 | === modified file 'test/check_lib_core.c' |
705 | --- test/check_lib_core.c 2011-02-18 14:39:38 +0000 |
706 | +++ test/check_lib_core.c 2011-04-08 15:38:33 +0000 |
707 | @@ -38,6 +38,7 @@ |
708 | { |
709 | int number_failed; |
710 | SRunner *sr = srunner_create(lib_core_hit()); |
711 | + srunner_add_suite(sr, lib_core_solve()); |
712 | srunner_add_suite(sr, lib_core_straddr()); |
713 | |
714 | srunner_run_all(sr, CK_NORMAL); |
715 | |
716 | === added file 'test/lib/core/solve.c' |
717 | --- test/lib/core/solve.c 1970-01-01 00:00:00 +0000 |
718 | +++ test/lib/core/solve.c 2011-04-08 15:38:33 +0000 |
719 | @@ -0,0 +1,170 @@ |
720 | +/* |
721 | + * Copyright (c) 2010 Aalto University and RWTH Aachen University. |
722 | + * |
723 | + * Permission is hereby granted, free of charge, to any person |
724 | + * obtaining a copy of this software and associated documentation |
725 | + * files (the "Software"), to deal in the Software without |
726 | + * restriction, including without limitation the rights to use, |
727 | + * copy, modify, merge, publish, distribute, sublicense, and/or sell |
728 | + * copies of the Software, and to permit persons to whom the |
729 | + * Software is furnished to do so, subject to the following |
730 | + * conditions: |
731 | + * |
732 | + * The above copyright notice and this permission notice shall be |
733 | + * included in all copies or substantial portions of the Software. |
734 | + * |
735 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
736 | + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
737 | + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
738 | + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
739 | + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
740 | + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
741 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
742 | + * OTHER DEALINGS IN THE SOFTWARE. |
743 | + */ |
744 | + |
745 | +/** |
746 | + * @file |
747 | + * @author Rene Hummen |
748 | + */ |
749 | + |
750 | +#include <check.h> |
751 | +#include <openssl/rand.h> |
752 | +#include <stdint.h> |
753 | + |
754 | +#include "lib/core/solve.h" |
755 | +#include "test_suites.h" |
756 | + |
757 | +START_TEST(test_hip_solve_puzzle_NULL_solution) |
758 | +{ |
759 | + uint8_t puzzle[PUZZLE_LENGTH] = { 0 }; |
760 | + int difficulty = 0; |
761 | + hip_hit_t initiator; |
762 | + hip_hit_t responder; |
763 | + |
764 | + RAND_bytes((unsigned char *)&puzzle, sizeof(uint64_t)); |
765 | + |
766 | + fail_unless(hip_solve_puzzle(puzzle, |
767 | + difficulty, |
768 | + initiator, |
769 | + responder, |
770 | + NULL) == -1, |
771 | + NULL); |
772 | +} |
773 | +END_TEST |
774 | + |
775 | +START_TEST(test_hip_solve_puzzle_0_K) |
776 | +{ |
777 | + uint8_t puzzle[PUZZLE_LENGTH] = { 0 }; |
778 | + int difficulty = 0; |
779 | + hip_hit_t initiator; |
780 | + hip_hit_t responder; |
781 | + uint8_t solution[PUZZLE_LENGTH] = { 0 }; |
782 | + |
783 | + RAND_bytes((unsigned char *)&puzzle, sizeof(PUZZLE_LENGTH)); |
784 | + |
785 | + fail_unless(hip_solve_puzzle(puzzle, |
786 | + difficulty, |
787 | + initiator, |
788 | + responder, |
789 | + solution) == 0, |
790 | + NULL); |
791 | +} |
792 | +END_TEST |
793 | + |
794 | +START_TEST(test_hip_solve_puzzle_5_K) |
795 | +{ |
796 | + uint8_t puzzle[PUZZLE_LENGTH] = { 0 }; |
797 | + int difficulty = 5; |
798 | + hip_hit_t initiator; |
799 | + hip_hit_t responder; |
800 | + uint8_t solution[PUZZLE_LENGTH] = { 0 }; |
801 | + |
802 | + RAND_bytes((unsigned char *)&puzzle, sizeof(uint64_t)); |
803 | + |
804 | + fail_unless(hip_solve_puzzle(puzzle, |
805 | + difficulty, |
806 | + initiator, |
807 | + responder, |
808 | + solution) == 0, |
809 | + NULL); |
810 | +} |
811 | +END_TEST |
812 | + |
813 | +START_TEST(test_hip_solve_puzzle_exceeding_K) |
814 | +{ |
815 | + uint8_t puzzle[PUZZLE_LENGTH] = { 0 }; |
816 | + int difficulty = max_puzzle_difficulty + 1; |
817 | + hip_hit_t initiator; |
818 | + hip_hit_t responder; |
819 | + uint8_t solution[PUZZLE_LENGTH] = { 0 }; |
820 | + |
821 | + RAND_bytes((unsigned char *)&puzzle, sizeof(uint64_t)); |
822 | + |
823 | + fail_unless(hip_solve_puzzle(puzzle, |
824 | + difficulty, |
825 | + initiator, |
826 | + responder, |
827 | + solution) == -1, |
828 | + NULL); |
829 | +} |
830 | +END_TEST |
831 | + |
832 | +START_TEST(test_hip_solve_puzzle_invalid) |
833 | +{ |
834 | + uint8_t puzzle[PUZZLE_LENGTH] = { 1 }; |
835 | + int difficulty = 20; |
836 | + hip_hit_t initiator; |
837 | + hip_hit_t responder; |
838 | + uint8_t solution[PUZZLE_LENGTH] = { 0 }; |
839 | + |
840 | + fail_unless(hip_verify_puzzle_solution(puzzle, |
841 | + difficulty, |
842 | + initiator, |
843 | + responder, |
844 | + solution) == -1, |
845 | + NULL); |
846 | +} |
847 | +END_TEST |
848 | + |
849 | +START_TEST(test_hip_solve_puzzle_valid) |
850 | +{ |
851 | + uint8_t puzzle[PUZZLE_LENGTH] = { 0 }; |
852 | + int difficulty = 8; |
853 | + hip_hit_t initiator; |
854 | + hip_hit_t responder; |
855 | + uint8_t solution[PUZZLE_LENGTH] = { 0 }; |
856 | + |
857 | + RAND_bytes((unsigned char *)&puzzle, sizeof(uint64_t)); |
858 | + |
859 | + fail_unless(hip_solve_puzzle(puzzle, |
860 | + difficulty, |
861 | + initiator, |
862 | + responder, |
863 | + solution) == 0, |
864 | + NULL); |
865 | + |
866 | + fail_unless(hip_verify_puzzle_solution(puzzle, |
867 | + difficulty, |
868 | + initiator, |
869 | + responder, |
870 | + solution) == 0, |
871 | + NULL); |
872 | +} |
873 | +END_TEST |
874 | + |
875 | +Suite *lib_core_solve(void) |
876 | +{ |
877 | + Suite *s = suite_create("lib/core/solve"); |
878 | + |
879 | + TCase *tc_core = tcase_create("Core"); |
880 | + tcase_add_test(tc_core, test_hip_solve_puzzle_NULL_solution); |
881 | + tcase_add_test(tc_core, test_hip_solve_puzzle_0_K); |
882 | + tcase_add_test(tc_core, test_hip_solve_puzzle_5_K); |
883 | + tcase_add_test(tc_core, test_hip_solve_puzzle_exceeding_K); |
884 | + tcase_add_test(tc_core, test_hip_solve_puzzle_invalid); |
885 | + tcase_add_test(tc_core, test_hip_solve_puzzle_valid); |
886 | + suite_add_tcase(s, tc_core); |
887 | + |
888 | + return s; |
889 | +} |
890 | |
891 | === modified file 'test/lib/core/test_suites.h' |
892 | --- test/lib/core/test_suites.h 2011-02-18 14:39:38 +0000 |
893 | +++ test/lib/core/test_suites.h 2011-04-08 15:38:33 +0000 |
894 | @@ -29,6 +29,7 @@ |
895 | #include <check.h> |
896 | |
897 | Suite *lib_core_hit(void); |
898 | +Suite *lib_core_solve(void); |
899 | Suite *lib_core_straddr(void); |
900 | |
901 | #endif /* HIP_TEST_LIB_CORE_TEST_SUITES_H */ |
Overall, this is definately cleaner than the old code.
There is one piece of code that does not match its corresponding comment; as soon as this is clarified (or fixed), I'll approve.
Would be nice if you could address the other points too (mainly missing documentation for newly added functions).
> +static int hip_calculate_ puzzle_ solution( const struct puzzle_common *const compute_puzzle, SHA_DIGEST_ LENGTH] , "puzzle" , puzzle_or_solution, "(u->pz. I: 0x%llx\n", u->pz.I); copy((hip_ hit_t *) (cookie + 8), &hdr->hits); copy((hip_ hit_t *) (cookie + 24), &hdr->hitr); copy((hip_ hit_t *) (cookie + 8), &hdr->hitr); copy((hip_ hit_t *) (cookie + 24), &hdr->hits); bytes(& randval, sizeof(uint64_t)); difficulty, hip_build_ digest( HIP_DIGEST_ SHA1,
> + unsigned char sha_digest[
> + const int difficulty)
> {
> - uint64_t mask = 0;
> - uint64_t randval = 0;
> - uint64_t maxtries = 0;
> - uint64_t digest = 0;
> - uint8_t cookie[48];
> - int err = 0;
> - const union {
> - struct hip_puzzle pz;
> - struct hip_solution sl;
> - } *u;
> -
> - HIP_HEXDUMP(
> - (mode == HIP_VERIFY_PUZZLE ? sizeof(struct hip_solution) :
> - sizeof(struct hip_puzzle)));
> -
> - /* pre-create cookie */
> - u = puzzle_or_solution;
> -
> - HIP_IFEL(u->pz.K > HIP_PUZZLE_MAX_K, 0,
> - "Cookie K %u is higher than we are willing to calculate"
> - " (current max K=%d)\n", u->pz.K, HIP_PUZZLE_MAX_K);
> -
> - mask = hton64((1ULL << u->pz.K) - 1);
> - memcpy(cookie, &u->pz.I, sizeof(uint64_t));
> -
> - HIP_DEBUG(
> -
> - if (mode == HIP_VERIFY_PUZZLE) {
> - ipv6_addr_
> - ipv6_addr_
> - randval = u->sl.J;
> - maxtries = 1;
> - } else if (mode == HIP_SOLVE_PUZZLE) {
> - ipv6_addr_
> - ipv6_addr_
> - maxtries = 1ULL << (u->pz.K + 3);
> - get_random_
> + uint32_t truncated_digest = 0;
> + int err = -1;
> +
> + HIP_IFEL(difficulty > max_puzzle_
> + 1, "difficulty exceeds max. configured difficulty\n");
> +
> + HIP_IFEL(
> + compute_puzzle,
> + sizeof(struct puzzle_common),
> + sha_digest),
> + -1, "failed to compute hash digest\n");
You could return early with a (successful) solution of zero if difficulty == 0.
If the caller is responsible of taking that shortcut, I'd add an assertion here to catch future callers who forget about this.
> + /* we are interested in the 8 least significant bytes */ SHA_DIGEST_ LENGTH - sizeof(uint32_t)];
> + truncated_digest = *(uint32_t *) &sha_digest[
The 8 least significant bytes have index 0..7. Also, sizeof(uint32_t) is 4, not 8.
> +int hip_solve_ puzzle( const uint64_t puzzle,
> + const int difficulty,
> + const hip_hit_t initiator_hit,
> + const hip_hit_t responder_hit,
> + uint64_t *solution)
> +{
> + struct puzzle_common compute_puzzle;
> + unsigned char sha_digest[SHA...