File Coverage

_tth.c
Criterion Covered Total %
statement 30 49 61.2
branch 9 20 45.0
condition n/a
subroutine n/a
pod n/a
total 39 69 56.5


line stmt bran cond sub pod time code
1             /* tth.c - calculate TTH (Tiger Tree Hash) function.
2             *
3             * Copyright: 2007-2012 Aleksey Kravchenko
4             *
5             * Permission is hereby granted, free of charge, to any person obtaining a
6             * copy of this software and associated documentation files (the "Software"),
7             * to deal in the Software without restriction, including without limitation
8             * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9             * and/or sell copies of the Software, and to permit persons to whom the
10             * Software is furnished to do so.
11             *
12             * This program is distributed in the hope that it will be useful, but
13             * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14             * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
15             */
16              
17             #include
18             #include "byte_order.h"
19             #include "tth.h"
20              
21             /**
22             * Initialize context before calculaing hash.
23             *
24             * @param ctx context to initialize
25             */
26 4           void rhash_tth_init(tth_ctx *ctx)
27             {
28 4           rhash_tiger_init(&ctx->tiger);
29 4           ctx->tiger.message[ ctx->tiger.length++ ] = 0x00;
30 4           ctx->block_count = 0;
31 4           }
32              
33             /**
34             * The core transformation.
35             *
36             * @param ctx algorithm state
37             */
38 4           static void rhash_tth_process_block(tth_ctx *ctx)
39             {
40             uint64_t it;
41 4           unsigned pos = 0;
42             unsigned char msg[24];
43              
44 4 50         for (it = 1; it & ctx->block_count; it <<= 1) {
45 0           rhash_tiger_final(&ctx->tiger, msg);
46 0           rhash_tiger_init(&ctx->tiger);
47 0           ctx->tiger.message[ctx->tiger.length++] = 0x01;
48 0           rhash_tiger_update(&ctx->tiger, (unsigned char*)(ctx->stack + pos), 24);
49             /* note: we can cut this step, if the previous rhash_tiger_final saves directly to ctx->tiger.message+25; */
50 0           rhash_tiger_update(&ctx->tiger, msg, 24);
51 0           pos += 3;
52             }
53 4           rhash_tiger_final(&ctx->tiger, (unsigned char*)(ctx->stack + pos));
54 4           ctx->block_count++;
55 4           }
56              
57             /**
58             * Calculate message hash.
59             * Can be called repeatedly with chunks of the message to be hashed.
60             *
61             * @param ctx the algorithm context containing current hashing state
62             * @param msg message chunk
63             * @param size length of the message chunk
64             */
65 3           void rhash_tth_update(tth_ctx *ctx, const unsigned char* msg, size_t size)
66             {
67 3           size_t rest = 1025 - (size_t)ctx->tiger.length;
68             for (;;) {
69 3 50         if (size < rest) rest = size;
70 3           rhash_tiger_update(&ctx->tiger, msg, rest);
71 3           msg += rest;
72 3           size -= rest;
73 3 50         if (ctx->tiger.length < 1025) {
74 3           return;
75             }
76              
77             /* process block hash */
78 0           rhash_tth_process_block(ctx);
79              
80             /* init block hash */
81 0           rhash_tiger_init(&ctx->tiger);
82 0           ctx->tiger.message[ ctx->tiger.length++ ] = 0x00;
83 0           rest = 1024;
84 0           }
85             }
86              
87             /**
88             * Store calculated hash into the given array.
89             *
90             * @param ctx the algorithm context containing current hashing state
91             * @param result calculated hash in binary form
92             */
93 4           void rhash_tth_final(tth_ctx *ctx, unsigned char result[24])
94             {
95 4           uint64_t it = 1;
96 4           unsigned pos = 0;
97             unsigned char msg[24];
98             const unsigned char* last_message;
99              
100             /* process the bytes left in the context buffer */
101 4 100         if (ctx->tiger.length > 1 || ctx->block_count == 0) {
    50          
102 4           rhash_tth_process_block(ctx);
103             }
104              
105 4 50         for (; it < ctx->block_count && (it & ctx->block_count) == 0; it <<= 1) pos += 3;
    0          
106 4           last_message = (unsigned char*)(ctx->stack + pos);
107              
108 4 50         for (it <<= 1; it <= ctx->block_count; it <<= 1) {
109             /* merge TTH sums in the tree */
110 0           pos += 3;
111 0 0         if (it & ctx->block_count) {
112 0           rhash_tiger_init(&ctx->tiger);
113 0           ctx->tiger.message[ ctx->tiger.length++ ] = 0x01;
114 0           rhash_tiger_update(&ctx->tiger, (unsigned char*)(ctx->stack + pos), 24);
115 0           rhash_tiger_update(&ctx->tiger, last_message, 24);
116              
117 0           rhash_tiger_final(&ctx->tiger, msg);
118 0           last_message = msg;
119             }
120             }
121              
122             /* save result hash */
123 4           memcpy(ctx->tiger.hash, last_message, tiger_hash_length);
124 4 50         if (result) memcpy(result, last_message, tiger_hash_length);
125 4           }