| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | /* sha3.c - an implementation of Secure Hash Algorithm 3 (Keccak). | 
| 2 |  |  |  |  |  |  | * based on the | 
| 3 |  |  |  |  |  |  | * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011 | 
| 4 |  |  |  |  |  |  | * by Guido Bertoni, Joan Daemen, Michaƫl Peeters and Gilles Van Assche | 
| 5 |  |  |  |  |  |  | * | 
| 6 |  |  |  |  |  |  | * Copyright: 2013 Aleksey Kravchenko | 
| 7 |  |  |  |  |  |  | * | 
| 8 |  |  |  |  |  |  | * Permission is hereby granted,  free of charge,  to any person  obtaining a | 
| 9 |  |  |  |  |  |  | * copy of this software and associated documentation files (the "Software"), | 
| 10 |  |  |  |  |  |  | * to deal in the Software without restriction,  including without limitation | 
| 11 |  |  |  |  |  |  | * the rights to  use, copy, modify,  merge, publish, distribute, sublicense, | 
| 12 |  |  |  |  |  |  | * and/or sell copies  of  the Software,  and to permit  persons  to whom the | 
| 13 |  |  |  |  |  |  | * Software is furnished to do so. | 
| 14 |  |  |  |  |  |  | * | 
| 15 |  |  |  |  |  |  | * This program  is  distributed  in  the  hope  that it will be useful,  but | 
| 16 |  |  |  |  |  |  | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | 
| 17 |  |  |  |  |  |  | * or FITNESS FOR A PARTICULAR PURPOSE.  Use this program  at  your own risk! | 
| 18 |  |  |  |  |  |  | */ | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | #include | 
| 21 |  |  |  |  |  |  | #include | 
| 22 |  |  |  |  |  |  | #include "byte_order.h" | 
| 23 |  |  |  |  |  |  | #include "sha3.h" | 
| 24 |  |  |  |  |  |  |  | 
| 25 |  |  |  |  |  |  | /* constants */ | 
| 26 |  |  |  |  |  |  | #define NumberOfRounds 24 | 
| 27 |  |  |  |  |  |  |  | 
| 28 |  |  |  |  |  |  | /* SHA3 (Keccak) constants for 24 rounds */ | 
| 29 |  |  |  |  |  |  | static uint64_t keccak_round_constants[NumberOfRounds] = { | 
| 30 |  |  |  |  |  |  | I64(0x0000000000000001), I64(0x0000000000008082), I64(0x800000000000808A), I64(0x8000000080008000), | 
| 31 |  |  |  |  |  |  | I64(0x000000000000808B), I64(0x0000000080000001), I64(0x8000000080008081), I64(0x8000000000008009), | 
| 32 |  |  |  |  |  |  | I64(0x000000000000008A), I64(0x0000000000000088), I64(0x0000000080008009), I64(0x000000008000000A), | 
| 33 |  |  |  |  |  |  | I64(0x000000008000808B), I64(0x800000000000008B), I64(0x8000000000008089), I64(0x8000000000008003), | 
| 34 |  |  |  |  |  |  | I64(0x8000000000008002), I64(0x8000000000000080), I64(0x000000000000800A), I64(0x800000008000000A), | 
| 35 |  |  |  |  |  |  | I64(0x8000000080008081), I64(0x8000000000008080), I64(0x0000000080000001), I64(0x8000000080008008) | 
| 36 |  |  |  |  |  |  | }; | 
| 37 |  |  |  |  |  |  |  | 
| 38 |  |  |  |  |  |  | /* Initializing a sha3 context for given number of output bits */ | 
| 39 | 8 |  |  |  |  |  | static void rhash_keccak_init(sha3_ctx *ctx, unsigned bits) | 
| 40 |  |  |  |  |  |  | { | 
| 41 |  |  |  |  |  |  | /* NB: The Keccak capacity parameter = bits * 2 */ | 
| 42 | 8 |  |  |  |  |  | unsigned rate = 1600 - bits * 2; | 
| 43 |  |  |  |  |  |  |  | 
| 44 | 8 |  |  |  |  |  | memset(ctx, 0, sizeof(sha3_ctx)); | 
| 45 | 8 |  |  |  |  |  | ctx->block_size = rate / 8; | 
| 46 | 8 | 50 |  |  |  |  | assert(rate <= 1600 && (rate % 64) == 0); | 
|  |  | 50 |  |  |  |  |  | 
| 47 | 8 |  |  |  |  |  | } | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | /** | 
| 50 |  |  |  |  |  |  | * Initialize context before calculating hash. | 
| 51 |  |  |  |  |  |  | * | 
| 52 |  |  |  |  |  |  | * @param ctx context to initialize | 
| 53 |  |  |  |  |  |  | */ | 
| 54 | 2 |  |  |  |  |  | void rhash_sha3_224_init(sha3_ctx *ctx) | 
| 55 |  |  |  |  |  |  | { | 
| 56 | 2 |  |  |  |  |  | rhash_keccak_init(ctx, 224); | 
| 57 | 2 |  |  |  |  |  | } | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | /** | 
| 60 |  |  |  |  |  |  | * Initialize context before calculating hash. | 
| 61 |  |  |  |  |  |  | * | 
| 62 |  |  |  |  |  |  | * @param ctx context to initialize | 
| 63 |  |  |  |  |  |  | */ | 
| 64 | 2 |  |  |  |  |  | void rhash_sha3_256_init(sha3_ctx *ctx) | 
| 65 |  |  |  |  |  |  | { | 
| 66 | 2 |  |  |  |  |  | rhash_keccak_init(ctx, 256); | 
| 67 | 2 |  |  |  |  |  | } | 
| 68 |  |  |  |  |  |  |  | 
| 69 |  |  |  |  |  |  | /** | 
| 70 |  |  |  |  |  |  | * Initialize context before calculating hash. | 
| 71 |  |  |  |  |  |  | * | 
| 72 |  |  |  |  |  |  | * @param ctx context to initialize | 
| 73 |  |  |  |  |  |  | */ | 
| 74 | 2 |  |  |  |  |  | void rhash_sha3_384_init(sha3_ctx *ctx) | 
| 75 |  |  |  |  |  |  | { | 
| 76 | 2 |  |  |  |  |  | rhash_keccak_init(ctx, 384); | 
| 77 | 2 |  |  |  |  |  | } | 
| 78 |  |  |  |  |  |  |  | 
| 79 |  |  |  |  |  |  | /** | 
| 80 |  |  |  |  |  |  | * Initialize context before calculating hash. | 
| 81 |  |  |  |  |  |  | * | 
| 82 |  |  |  |  |  |  | * @param ctx context to initialize | 
| 83 |  |  |  |  |  |  | */ | 
| 84 | 2 |  |  |  |  |  | void rhash_sha3_512_init(sha3_ctx *ctx) | 
| 85 |  |  |  |  |  |  | { | 
| 86 | 2 |  |  |  |  |  | rhash_keccak_init(ctx, 512); | 
| 87 | 2 |  |  |  |  |  | } | 
| 88 |  |  |  |  |  |  |  | 
| 89 |  |  |  |  |  |  | /* Keccak theta() transformation */ | 
| 90 | 192 |  |  |  |  |  | static void keccak_theta(uint64_t *A) | 
| 91 |  |  |  |  |  |  | { | 
| 92 |  |  |  |  |  |  | unsigned int x; | 
| 93 |  |  |  |  |  |  | uint64_t C[5], D[5]; | 
| 94 |  |  |  |  |  |  |  | 
| 95 | 1152 | 100 |  |  |  |  | for (x = 0; x < 5; x++) { | 
| 96 | 960 |  |  |  |  |  | C[x] = A[x] ^ A[x + 5] ^ A[x + 10] ^ A[x + 15] ^ A[x + 20]; | 
| 97 |  |  |  |  |  |  | } | 
| 98 | 192 |  |  |  |  |  | D[0] = ROTL64(C[1], 1) ^ C[4]; | 
| 99 | 192 |  |  |  |  |  | D[1] = ROTL64(C[2], 1) ^ C[0]; | 
| 100 | 192 |  |  |  |  |  | D[2] = ROTL64(C[3], 1) ^ C[1]; | 
| 101 | 192 |  |  |  |  |  | D[3] = ROTL64(C[4], 1) ^ C[2]; | 
| 102 | 192 |  |  |  |  |  | D[4] = ROTL64(C[0], 1) ^ C[3]; | 
| 103 |  |  |  |  |  |  |  | 
| 104 | 1152 | 100 |  |  |  |  | for (x = 0; x < 5; x++) { | 
| 105 | 960 |  |  |  |  |  | A[x]      ^= D[x]; | 
| 106 | 960 |  |  |  |  |  | A[x + 5]  ^= D[x]; | 
| 107 | 960 |  |  |  |  |  | A[x + 10] ^= D[x]; | 
| 108 | 960 |  |  |  |  |  | A[x + 15] ^= D[x]; | 
| 109 | 960 |  |  |  |  |  | A[x + 20] ^= D[x]; | 
| 110 |  |  |  |  |  |  | } | 
| 111 | 192 |  |  |  |  |  | } | 
| 112 |  |  |  |  |  |  |  | 
| 113 |  |  |  |  |  |  | /* Keccak pi() transformation */ | 
| 114 | 192 |  |  |  |  |  | static void keccak_pi(uint64_t *A) | 
| 115 |  |  |  |  |  |  | { | 
| 116 |  |  |  |  |  |  | uint64_t A1; | 
| 117 | 192 |  |  |  |  |  | A1 = A[1]; | 
| 118 | 192 |  |  |  |  |  | A[ 1] = A[ 6]; | 
| 119 | 192 |  |  |  |  |  | A[ 6] = A[ 9]; | 
| 120 | 192 |  |  |  |  |  | A[ 9] = A[22]; | 
| 121 | 192 |  |  |  |  |  | A[22] = A[14]; | 
| 122 | 192 |  |  |  |  |  | A[14] = A[20]; | 
| 123 | 192 |  |  |  |  |  | A[20] = A[ 2]; | 
| 124 | 192 |  |  |  |  |  | A[ 2] = A[12]; | 
| 125 | 192 |  |  |  |  |  | A[12] = A[13]; | 
| 126 | 192 |  |  |  |  |  | A[13] = A[19]; | 
| 127 | 192 |  |  |  |  |  | A[19] = A[23]; | 
| 128 | 192 |  |  |  |  |  | A[23] = A[15]; | 
| 129 | 192 |  |  |  |  |  | A[15] = A[ 4]; | 
| 130 | 192 |  |  |  |  |  | A[ 4] = A[24]; | 
| 131 | 192 |  |  |  |  |  | A[24] = A[21]; | 
| 132 | 192 |  |  |  |  |  | A[21] = A[ 8]; | 
| 133 | 192 |  |  |  |  |  | A[ 8] = A[16]; | 
| 134 | 192 |  |  |  |  |  | A[16] = A[ 5]; | 
| 135 | 192 |  |  |  |  |  | A[ 5] = A[ 3]; | 
| 136 | 192 |  |  |  |  |  | A[ 3] = A[18]; | 
| 137 | 192 |  |  |  |  |  | A[18] = A[17]; | 
| 138 | 192 |  |  |  |  |  | A[17] = A[11]; | 
| 139 | 192 |  |  |  |  |  | A[11] = A[ 7]; | 
| 140 | 192 |  |  |  |  |  | A[ 7] = A[10]; | 
| 141 | 192 |  |  |  |  |  | A[10] = A1; | 
| 142 |  |  |  |  |  |  | /* note: A[ 0] is left as is */ | 
| 143 | 192 |  |  |  |  |  | } | 
| 144 |  |  |  |  |  |  |  | 
| 145 |  |  |  |  |  |  | /* Keccak chi() transformation */ | 
| 146 | 192 |  |  |  |  |  | static void keccak_chi(uint64_t *A) | 
| 147 |  |  |  |  |  |  | { | 
| 148 |  |  |  |  |  |  | int i; | 
| 149 | 1152 | 100 |  |  |  |  | for (i = 0; i < 25; i += 5) { | 
| 150 | 960 |  |  |  |  |  | uint64_t A0 = A[0 + i], A1 = A[1 + i]; | 
| 151 | 960 |  |  |  |  |  | A[0 + i] ^= ~A1 & A[2 + i]; | 
| 152 | 960 |  |  |  |  |  | A[1 + i] ^= ~A[2 + i] & A[3 + i]; | 
| 153 | 960 |  |  |  |  |  | A[2 + i] ^= ~A[3 + i] & A[4 + i]; | 
| 154 | 960 |  |  |  |  |  | A[3 + i] ^= ~A[4 + i] & A0; | 
| 155 | 960 |  |  |  |  |  | A[4 + i] ^= ~A0 & A1; | 
| 156 |  |  |  |  |  |  | } | 
| 157 | 192 |  |  |  |  |  | } | 
| 158 |  |  |  |  |  |  |  | 
| 159 | 8 |  |  |  |  |  | static void rhash_sha3_permutation(uint64_t *state) | 
| 160 |  |  |  |  |  |  | { | 
| 161 |  |  |  |  |  |  | int round; | 
| 162 | 200 | 100 |  |  |  |  | for (round = 0; round < NumberOfRounds; round++) | 
| 163 |  |  |  |  |  |  | { | 
| 164 | 192 |  |  |  |  |  | keccak_theta(state); | 
| 165 |  |  |  |  |  |  |  | 
| 166 |  |  |  |  |  |  | /* apply Keccak rho() transformation */ | 
| 167 | 192 |  |  |  |  |  | state[ 1] = ROTL64(state[ 1],  1); | 
| 168 | 192 |  |  |  |  |  | state[ 2] = ROTL64(state[ 2], 62); | 
| 169 | 192 |  |  |  |  |  | state[ 3] = ROTL64(state[ 3], 28); | 
| 170 | 192 |  |  |  |  |  | state[ 4] = ROTL64(state[ 4], 27); | 
| 171 | 192 |  |  |  |  |  | state[ 5] = ROTL64(state[ 5], 36); | 
| 172 | 192 |  |  |  |  |  | state[ 6] = ROTL64(state[ 6], 44); | 
| 173 | 192 |  |  |  |  |  | state[ 7] = ROTL64(state[ 7],  6); | 
| 174 | 192 |  |  |  |  |  | state[ 8] = ROTL64(state[ 8], 55); | 
| 175 | 192 |  |  |  |  |  | state[ 9] = ROTL64(state[ 9], 20); | 
| 176 | 192 |  |  |  |  |  | state[10] = ROTL64(state[10],  3); | 
| 177 | 192 |  |  |  |  |  | state[11] = ROTL64(state[11], 10); | 
| 178 | 192 |  |  |  |  |  | state[12] = ROTL64(state[12], 43); | 
| 179 | 192 |  |  |  |  |  | state[13] = ROTL64(state[13], 25); | 
| 180 | 192 |  |  |  |  |  | state[14] = ROTL64(state[14], 39); | 
| 181 | 192 |  |  |  |  |  | state[15] = ROTL64(state[15], 41); | 
| 182 | 192 |  |  |  |  |  | state[16] = ROTL64(state[16], 45); | 
| 183 | 192 |  |  |  |  |  | state[17] = ROTL64(state[17], 15); | 
| 184 | 192 |  |  |  |  |  | state[18] = ROTL64(state[18], 21); | 
| 185 | 192 |  |  |  |  |  | state[19] = ROTL64(state[19],  8); | 
| 186 | 192 |  |  |  |  |  | state[20] = ROTL64(state[20], 18); | 
| 187 | 192 |  |  |  |  |  | state[21] = ROTL64(state[21],  2); | 
| 188 | 192 |  |  |  |  |  | state[22] = ROTL64(state[22], 61); | 
| 189 | 192 |  |  |  |  |  | state[23] = ROTL64(state[23], 56); | 
| 190 | 192 |  |  |  |  |  | state[24] = ROTL64(state[24], 14); | 
| 191 |  |  |  |  |  |  |  | 
| 192 | 192 |  |  |  |  |  | keccak_pi(state); | 
| 193 | 192 |  |  |  |  |  | keccak_chi(state); | 
| 194 |  |  |  |  |  |  |  | 
| 195 |  |  |  |  |  |  | /* apply iota(state, round) */ | 
| 196 | 192 |  |  |  |  |  | *state ^= keccak_round_constants[round]; | 
| 197 |  |  |  |  |  |  | } | 
| 198 | 8 |  |  |  |  |  | } | 
| 199 |  |  |  |  |  |  |  | 
| 200 |  |  |  |  |  |  | /** | 
| 201 |  |  |  |  |  |  | * The core transformation. Process the specified block of data. | 
| 202 |  |  |  |  |  |  | * | 
| 203 |  |  |  |  |  |  | * @param hash the algorithm state | 
| 204 |  |  |  |  |  |  | * @param block the message block to process | 
| 205 |  |  |  |  |  |  | * @param block_size the size of the processed block in bytes | 
| 206 |  |  |  |  |  |  | */ | 
| 207 | 8 |  |  |  |  |  | static void rhash_sha3_process_block(uint64_t hash[25], const uint64_t *block, size_t block_size) | 
| 208 |  |  |  |  |  |  | { | 
| 209 |  |  |  |  |  |  | /* expanded loop */ | 
| 210 | 8 |  |  |  |  |  | hash[ 0] ^= le2me_64(block[ 0]); | 
| 211 | 8 |  |  |  |  |  | hash[ 1] ^= le2me_64(block[ 1]); | 
| 212 | 8 |  |  |  |  |  | hash[ 2] ^= le2me_64(block[ 2]); | 
| 213 | 8 |  |  |  |  |  | hash[ 3] ^= le2me_64(block[ 3]); | 
| 214 | 8 |  |  |  |  |  | hash[ 4] ^= le2me_64(block[ 4]); | 
| 215 | 8 |  |  |  |  |  | hash[ 5] ^= le2me_64(block[ 5]); | 
| 216 | 8 |  |  |  |  |  | hash[ 6] ^= le2me_64(block[ 6]); | 
| 217 | 8 |  |  |  |  |  | hash[ 7] ^= le2me_64(block[ 7]); | 
| 218 | 8 |  |  |  |  |  | hash[ 8] ^= le2me_64(block[ 8]); | 
| 219 |  |  |  |  |  |  | /* if not sha3-512 */ | 
| 220 | 8 | 100 |  |  |  |  | if (block_size > 72) { | 
| 221 | 6 |  |  |  |  |  | hash[ 9] ^= le2me_64(block[ 9]); | 
| 222 | 6 |  |  |  |  |  | hash[10] ^= le2me_64(block[10]); | 
| 223 | 6 |  |  |  |  |  | hash[11] ^= le2me_64(block[11]); | 
| 224 | 6 |  |  |  |  |  | hash[12] ^= le2me_64(block[12]); | 
| 225 |  |  |  |  |  |  | /* if not sha3-384 */ | 
| 226 | 6 | 100 |  |  |  |  | if (block_size > 104) { | 
| 227 | 4 |  |  |  |  |  | hash[13] ^= le2me_64(block[13]); | 
| 228 | 4 |  |  |  |  |  | hash[14] ^= le2me_64(block[14]); | 
| 229 | 4 |  |  |  |  |  | hash[15] ^= le2me_64(block[15]); | 
| 230 | 4 |  |  |  |  |  | hash[16] ^= le2me_64(block[16]); | 
| 231 |  |  |  |  |  |  | /* if not sha3-256 */ | 
| 232 | 4 | 100 |  |  |  |  | if (block_size > 136) { | 
| 233 | 2 |  |  |  |  |  | hash[17] ^= le2me_64(block[17]); | 
| 234 |  |  |  |  |  |  | #ifdef FULL_SHA3_FAMILY_SUPPORT | 
| 235 |  |  |  |  |  |  | /* if not sha3-224 */ | 
| 236 |  |  |  |  |  |  | if (block_size > 144) { | 
| 237 |  |  |  |  |  |  | hash[18] ^= le2me_64(block[18]); | 
| 238 |  |  |  |  |  |  | hash[19] ^= le2me_64(block[19]); | 
| 239 |  |  |  |  |  |  | hash[20] ^= le2me_64(block[20]); | 
| 240 |  |  |  |  |  |  | hash[21] ^= le2me_64(block[21]); | 
| 241 |  |  |  |  |  |  | hash[22] ^= le2me_64(block[22]); | 
| 242 |  |  |  |  |  |  | hash[23] ^= le2me_64(block[23]); | 
| 243 |  |  |  |  |  |  | hash[24] ^= le2me_64(block[24]); | 
| 244 |  |  |  |  |  |  | } | 
| 245 |  |  |  |  |  |  | #endif | 
| 246 |  |  |  |  |  |  | } | 
| 247 |  |  |  |  |  |  | } | 
| 248 |  |  |  |  |  |  | } | 
| 249 |  |  |  |  |  |  | /* make a permutation of the hash */ | 
| 250 | 8 |  |  |  |  |  | rhash_sha3_permutation(hash); | 
| 251 | 8 |  |  |  |  |  | } | 
| 252 |  |  |  |  |  |  |  | 
| 253 |  |  |  |  |  |  | #define SHA3_FINALIZED 0x80000000 | 
| 254 |  |  |  |  |  |  |  | 
| 255 |  |  |  |  |  |  | /** | 
| 256 |  |  |  |  |  |  | * Calculate message hash. | 
| 257 |  |  |  |  |  |  | * Can be called repeatedly with chunks of the message to be hashed. | 
| 258 |  |  |  |  |  |  | * | 
| 259 |  |  |  |  |  |  | * @param ctx the algorithm context containing current hashing state | 
| 260 |  |  |  |  |  |  | * @param msg message chunk | 
| 261 |  |  |  |  |  |  | * @param size length of the message chunk | 
| 262 |  |  |  |  |  |  | */ | 
| 263 | 8 |  |  |  |  |  | void rhash_sha3_update(sha3_ctx *ctx, const unsigned char *msg, size_t size) | 
| 264 |  |  |  |  |  |  | { | 
| 265 | 8 |  |  |  |  |  | size_t index = (size_t)ctx->rest; | 
| 266 | 8 |  |  |  |  |  | size_t block_size = (size_t)ctx->block_size; | 
| 267 |  |  |  |  |  |  |  | 
| 268 | 8 | 50 |  |  |  |  | if (ctx->rest & SHA3_FINALIZED) return; /* too late for additional input */ | 
| 269 | 8 |  |  |  |  |  | ctx->rest = (unsigned)((ctx->rest + size) % block_size); | 
| 270 |  |  |  |  |  |  |  | 
| 271 |  |  |  |  |  |  | /* fill partial block */ | 
| 272 | 8 | 50 |  |  |  |  | if (index) { | 
| 273 | 0 |  |  |  |  |  | size_t left = block_size - index; | 
| 274 | 0 |  |  |  |  |  | memcpy((char*)ctx->message + index, msg, (size < left ? size : left)); | 
| 275 | 0 | 0 |  |  |  |  | if (size < left) return; | 
| 276 |  |  |  |  |  |  |  | 
| 277 |  |  |  |  |  |  | /* process partial block */ | 
| 278 | 0 |  |  |  |  |  | rhash_sha3_process_block(ctx->hash, ctx->message, block_size); | 
| 279 | 0 |  |  |  |  |  | msg  += left; | 
| 280 | 0 |  |  |  |  |  | size -= left; | 
| 281 |  |  |  |  |  |  | } | 
| 282 | 8 | 50 |  |  |  |  | while (size >= block_size) { | 
| 283 |  |  |  |  |  |  | uint64_t* aligned_message_block; | 
| 284 | 0 | 0 |  |  |  |  | if (IS_ALIGNED_64(msg)) { | 
| 285 |  |  |  |  |  |  | /* the most common case is processing of an already aligned message | 
| 286 |  |  |  |  |  |  | without copying it */ | 
| 287 | 0 |  |  |  |  |  | aligned_message_block = (uint64_t*)msg; | 
| 288 |  |  |  |  |  |  | } else { | 
| 289 | 0 |  |  |  |  |  | memcpy(ctx->message, msg, block_size); | 
| 290 | 0 |  |  |  |  |  | aligned_message_block = ctx->message; | 
| 291 |  |  |  |  |  |  | } | 
| 292 |  |  |  |  |  |  |  | 
| 293 | 0 |  |  |  |  |  | rhash_sha3_process_block(ctx->hash, aligned_message_block, block_size); | 
| 294 | 0 |  |  |  |  |  | msg  += block_size; | 
| 295 | 0 |  |  |  |  |  | size -= block_size; | 
| 296 |  |  |  |  |  |  | } | 
| 297 | 8 | 50 |  |  |  |  | if (size) { | 
| 298 | 8 |  |  |  |  |  | memcpy(ctx->message, msg, size); /* save leftovers */ | 
| 299 |  |  |  |  |  |  | } | 
| 300 |  |  |  |  |  |  | } | 
| 301 |  |  |  |  |  |  |  | 
| 302 |  |  |  |  |  |  | /** | 
| 303 |  |  |  |  |  |  | * Store calculated hash into the given array. | 
| 304 |  |  |  |  |  |  | * | 
| 305 |  |  |  |  |  |  | * @param ctx the algorithm context containing current hashing state | 
| 306 |  |  |  |  |  |  | * @param result calculated hash in binary form | 
| 307 |  |  |  |  |  |  | */ | 
| 308 | 8 |  |  |  |  |  | void rhash_sha3_final(sha3_ctx *ctx, unsigned char* result) | 
| 309 |  |  |  |  |  |  | { | 
| 310 | 8 |  |  |  |  |  | size_t digest_length = 100 - ctx->block_size / 2; | 
| 311 | 8 |  |  |  |  |  | const size_t block_size = ctx->block_size; | 
| 312 |  |  |  |  |  |  |  | 
| 313 | 8 | 50 |  |  |  |  | if (!(ctx->rest & SHA3_FINALIZED)) | 
| 314 |  |  |  |  |  |  | { | 
| 315 |  |  |  |  |  |  | /* clear the rest of the data queue */ | 
| 316 | 8 |  |  |  |  |  | memset((char*)ctx->message + ctx->rest, 0, block_size - ctx->rest); | 
| 317 | 8 |  |  |  |  |  | ((char*)ctx->message)[ctx->rest] |= 0x06; | 
| 318 | 8 |  |  |  |  |  | ((char*)ctx->message)[block_size - 1] |= 0x80; | 
| 319 |  |  |  |  |  |  |  | 
| 320 |  |  |  |  |  |  | /* process final block */ | 
| 321 | 8 |  |  |  |  |  | rhash_sha3_process_block(ctx->hash, ctx->message, block_size); | 
| 322 | 8 |  |  |  |  |  | ctx->rest = SHA3_FINALIZED; /* mark context as finalized */ | 
| 323 |  |  |  |  |  |  | } | 
| 324 |  |  |  |  |  |  |  | 
| 325 | 8 | 50 |  |  |  |  | assert(block_size > digest_length); | 
| 326 | 8 | 50 |  |  |  |  | if (result) me64_to_le_str(result, ctx->hash, digest_length); | 
| 327 | 8 |  |  |  |  |  | } | 
| 328 |  |  |  |  |  |  |  | 
| 329 |  |  |  |  |  |  | #ifdef USE_KECCAK | 
| 330 |  |  |  |  |  |  | /** | 
| 331 |  |  |  |  |  |  | * Store calculated hash into the given array. | 
| 332 |  |  |  |  |  |  | * | 
| 333 |  |  |  |  |  |  | * @param ctx the algorithm context containing current hashing state | 
| 334 |  |  |  |  |  |  | * @param result calculated hash in binary form | 
| 335 |  |  |  |  |  |  | */ | 
| 336 |  |  |  |  |  |  | void rhash_keccak_final(sha3_ctx *ctx, unsigned char* result) | 
| 337 |  |  |  |  |  |  | { | 
| 338 |  |  |  |  |  |  | size_t digest_length = 100 - ctx->block_size / 2; | 
| 339 |  |  |  |  |  |  | const size_t block_size = ctx->block_size; | 
| 340 |  |  |  |  |  |  |  | 
| 341 |  |  |  |  |  |  | if (!(ctx->rest & SHA3_FINALIZED)) | 
| 342 |  |  |  |  |  |  | { | 
| 343 |  |  |  |  |  |  | /* clear the rest of the data queue */ | 
| 344 |  |  |  |  |  |  | memset((char*)ctx->message + ctx->rest, 0, block_size - ctx->rest); | 
| 345 |  |  |  |  |  |  | ((char*)ctx->message)[ctx->rest] |= 0x01; | 
| 346 |  |  |  |  |  |  | ((char*)ctx->message)[block_size - 1] |= 0x80; | 
| 347 |  |  |  |  |  |  |  | 
| 348 |  |  |  |  |  |  | /* process final block */ | 
| 349 |  |  |  |  |  |  | rhash_sha3_process_block(ctx->hash, ctx->message, block_size); | 
| 350 |  |  |  |  |  |  | ctx->rest = SHA3_FINALIZED; /* mark context as finalized */ | 
| 351 |  |  |  |  |  |  | } | 
| 352 |  |  |  |  |  |  |  | 
| 353 |  |  |  |  |  |  | assert(block_size > digest_length); | 
| 354 |  |  |  |  |  |  | if (result) me64_to_le_str(result, ctx->hash, digest_length); | 
| 355 |  |  |  |  |  |  | } | 
| 356 |  |  |  |  |  |  | #endif /* USE_KECCAK */ |