| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | /* algorithms.c - the algorithms supported by the rhash library | 
| 2 |  |  |  |  |  |  | * | 
| 3 |  |  |  |  |  |  | * Copyright (c) 2011, Aleksey Kravchenko | 
| 4 |  |  |  |  |  |  | * | 
| 5 |  |  |  |  |  |  | * Permission to use, copy, modify, and/or distribute this software for any | 
| 6 |  |  |  |  |  |  | * purpose with or without fee is hereby granted. | 
| 7 |  |  |  |  |  |  | * | 
| 8 |  |  |  |  |  |  | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | 
| 9 |  |  |  |  |  |  | * REGARD TO THIS SOFTWARE  INCLUDING ALL IMPLIED WARRANTIES OF  MERCHANTABILITY | 
| 10 |  |  |  |  |  |  | * AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | 
| 11 |  |  |  |  |  |  | * INDIRECT,  OR CONSEQUENTIAL DAMAGES  OR ANY DAMAGES WHATSOEVER RESULTING FROM | 
| 12 |  |  |  |  |  |  | * LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION OF CONTRACT,  NEGLIGENCE | 
| 13 |  |  |  |  |  |  | * OR OTHER TORTIOUS ACTION,  ARISING OUT OF  OR IN CONNECTION  WITH THE USE  OR | 
| 14 |  |  |  |  |  |  | * PERFORMANCE OF THIS SOFTWARE. | 
| 15 |  |  |  |  |  |  | */ | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | #include | 
| 18 |  |  |  |  |  |  | #include | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | #include "byte_order.h" | 
| 21 |  |  |  |  |  |  | #include "rhash.h" | 
| 22 |  |  |  |  |  |  | #include "algorithms.h" | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  | /* header files of all supported hash sums */ | 
| 25 |  |  |  |  |  |  | #include "aich.h" | 
| 26 |  |  |  |  |  |  | #include "crc32.h" | 
| 27 |  |  |  |  |  |  | #include "ed2k.h" | 
| 28 |  |  |  |  |  |  | #include "edonr.h" | 
| 29 |  |  |  |  |  |  | #include "gost12.h" | 
| 30 |  |  |  |  |  |  | #include "gost94.h" | 
| 31 |  |  |  |  |  |  | #include "has160.h" | 
| 32 |  |  |  |  |  |  | #include "md4.h" | 
| 33 |  |  |  |  |  |  | #include "md5.h" | 
| 34 |  |  |  |  |  |  | #include "ripemd-160.h" | 
| 35 |  |  |  |  |  |  | #include "snefru.h" | 
| 36 |  |  |  |  |  |  | #include "sha1.h" | 
| 37 |  |  |  |  |  |  | #include "sha256.h" | 
| 38 |  |  |  |  |  |  | #include "sha512.h" | 
| 39 |  |  |  |  |  |  | #include "sha3.h" | 
| 40 |  |  |  |  |  |  | #include "tiger.h" | 
| 41 |  |  |  |  |  |  | #include "torrent.h" | 
| 42 |  |  |  |  |  |  | #include "tth.h" | 
| 43 |  |  |  |  |  |  | #include "whirlpool.h" | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  | #ifdef USE_OPENSSL | 
| 46 |  |  |  |  |  |  | /* note: BTIH and AICH depends on the used SHA1 algorithm */ | 
| 47 |  |  |  |  |  |  | # define NEED_OPENSSL_INIT (RHASH_MD4 | RHASH_MD5 | \ | 
| 48 |  |  |  |  |  |  | RHASH_SHA1 | RHASH_SHA224 | RHASH_SHA256 | RHASH_SHA384 | RHASH_SHA512 | \ | 
| 49 |  |  |  |  |  |  | RHASH_BTIH | RHASH_AICH | RHASH_RIPEMD160 | RHASH_WHIRLPOOL) | 
| 50 |  |  |  |  |  |  | #else | 
| 51 |  |  |  |  |  |  | # define NEED_OPENSSL_INIT 0 | 
| 52 |  |  |  |  |  |  | #endif /* USE_OPENSSL */ | 
| 53 |  |  |  |  |  |  | #ifdef GENERATE_GOST94_LOOKUP_TABLE | 
| 54 |  |  |  |  |  |  | # define NEED_GOST94_INIT (RHASH_GOST94 | RHASH_GOST94_CRYPTOPRO) | 
| 55 |  |  |  |  |  |  | #else | 
| 56 |  |  |  |  |  |  | # define NEED_GOST94_INIT 0 | 
| 57 |  |  |  |  |  |  | #endif /* GENERATE_GOST94_LOOKUP_TABLE */ | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | #define RHASH_NEED_INIT_ALG (NEED_GOST94_INIT | NEED_OPENSSL_INIT) | 
| 60 |  |  |  |  |  |  | unsigned rhash_uninitialized_algorithms = RHASH_NEED_INIT_ALG; | 
| 61 |  |  |  |  |  |  |  | 
| 62 |  |  |  |  |  |  | rhash_hash_info* rhash_info_table = rhash_hash_info_default; | 
| 63 |  |  |  |  |  |  | int rhash_info_size = RHASH_HASH_COUNT; | 
| 64 |  |  |  |  |  |  |  | 
| 65 |  |  |  |  |  |  | static void rhash_crc32_init(uint32_t* crc32); | 
| 66 |  |  |  |  |  |  | static void rhash_crc32_update(uint32_t* crc32, const unsigned char* msg, size_t size); | 
| 67 |  |  |  |  |  |  | static void rhash_crc32_final(uint32_t* crc32, unsigned char* result); | 
| 68 |  |  |  |  |  |  | static void rhash_crc32c_init(uint32_t* crc32); | 
| 69 |  |  |  |  |  |  | static void rhash_crc32c_update(uint32_t* crc32, const unsigned char* msg, size_t size); | 
| 70 |  |  |  |  |  |  | static void rhash_crc32c_final(uint32_t* crc32, unsigned char* result); | 
| 71 |  |  |  |  |  |  |  | 
| 72 |  |  |  |  |  |  | rhash_info info_crc32  = { RHASH_CRC32,  F_BE32, 4, "CRC32", "crc32" }; | 
| 73 |  |  |  |  |  |  | rhash_info info_crc32c = { RHASH_CRC32C, F_BE32, 4, "CRC32C", "crc32c" }; | 
| 74 |  |  |  |  |  |  | rhash_info info_md4 = { RHASH_MD4, F_LE32, 16, "MD4", "md4" }; | 
| 75 |  |  |  |  |  |  | rhash_info info_md5 = { RHASH_MD5, F_LE32, 16, "MD5", "md5" }; | 
| 76 |  |  |  |  |  |  | rhash_info info_sha1 = { RHASH_SHA1,      F_BE32, 20, "SHA1", "sha1" }; | 
| 77 |  |  |  |  |  |  | rhash_info info_tiger = { RHASH_TIGER,    F_LE64, 24, "TIGER", "tiger" }; | 
| 78 |  |  |  |  |  |  | rhash_info info_tth  = { RHASH_TTH,       F_BS32, 24, "TTH", "tree:tiger" }; | 
| 79 |  |  |  |  |  |  | rhash_info info_btih = { RHASH_BTIH,      0, 20, "BTIH", "btih" }; | 
| 80 |  |  |  |  |  |  | rhash_info info_ed2k = { RHASH_ED2K,      F_LE32, 16, "ED2K", "ed2k" }; | 
| 81 |  |  |  |  |  |  | rhash_info info_aich = { RHASH_AICH,      F_BS32, 20, "AICH", "aich" }; | 
| 82 |  |  |  |  |  |  | rhash_info info_whirlpool = { RHASH_WHIRLPOOL, F_BE64, 64, "WHIRLPOOL", "whirlpool" }; | 
| 83 |  |  |  |  |  |  | rhash_info info_rmd160 = { RHASH_RIPEMD160,  F_LE32, 20, "RIPEMD-160", "ripemd160" }; | 
| 84 |  |  |  |  |  |  | rhash_info info_gost12_256 = { RHASH_GOST12_256, F_LE64, 32, "GOST12-256", "gost12-256" }; | 
| 85 |  |  |  |  |  |  | rhash_info info_gost12_512 = { RHASH_GOST12_512, F_LE64, 64, "GOST12-512", "gost12-512" }; | 
| 86 |  |  |  |  |  |  | rhash_info info_gost94 = { RHASH_GOST94,       F_LE32, 32, "GOST94", "gost94" }; | 
| 87 |  |  |  |  |  |  | rhash_info info_gost94pro = { RHASH_GOST94_CRYPTOPRO, F_LE32, 32, "GOST94-CRYPTOPRO", "gost94-cryptopro" }; | 
| 88 |  |  |  |  |  |  | rhash_info info_has160 = { RHASH_HAS160,     F_LE32, 20, "HAS-160", "has160" }; | 
| 89 |  |  |  |  |  |  | rhash_info info_snf128 = { RHASH_SNEFRU128,  F_BE32, 16, "SNEFRU-128", "snefru128" }; | 
| 90 |  |  |  |  |  |  | rhash_info info_snf256 = { RHASH_SNEFRU256,  F_BE32, 32, "SNEFRU-256", "snefru256" }; | 
| 91 |  |  |  |  |  |  | rhash_info info_sha224 = { RHASH_SHA224,     F_BE32, 28, "SHA-224", "sha224" }; | 
| 92 |  |  |  |  |  |  | rhash_info info_sha256 = { RHASH_SHA256,     F_BE32, 32, "SHA-256", "sha256" }; | 
| 93 |  |  |  |  |  |  | rhash_info info_sha384 = { RHASH_SHA384,     F_BE64, 48, "SHA-384", "sha384" }; | 
| 94 |  |  |  |  |  |  | rhash_info info_sha512 = { RHASH_SHA512,     F_BE64, 64, "SHA-512", "sha512" }; | 
| 95 |  |  |  |  |  |  | rhash_info info_edr256 = { RHASH_EDONR256,   F_LE32, 32, "EDON-R256", "edon-r256" }; | 
| 96 |  |  |  |  |  |  | rhash_info info_edr512 = { RHASH_EDONR512,   F_LE64, 64, "EDON-R512", "edon-r512" }; | 
| 97 |  |  |  |  |  |  | rhash_info info_sha3_224 = { RHASH_SHA3_224, F_LE64, 28, "SHA3-224", "sha3-224" }; | 
| 98 |  |  |  |  |  |  | rhash_info info_sha3_256 = { RHASH_SHA3_256, F_LE64, 32, "SHA3-256", "sha3-256" }; | 
| 99 |  |  |  |  |  |  | rhash_info info_sha3_384 = { RHASH_SHA3_384, F_LE64, 48, "SHA3-384", "sha3-384" }; | 
| 100 |  |  |  |  |  |  | rhash_info info_sha3_512 = { RHASH_SHA3_512, F_LE64, 64, "SHA3-512", "sha3-512" }; | 
| 101 |  |  |  |  |  |  |  | 
| 102 |  |  |  |  |  |  | /* some helper macros */ | 
| 103 |  |  |  |  |  |  | #define dgshft(name) (((char*)&((name##_ctx*)0)->hash) - (char*)0) | 
| 104 |  |  |  |  |  |  | #define dgshft2(name, field) (((char*)&((name##_ctx*)0)->field) - (char*)0) | 
| 105 |  |  |  |  |  |  | #define ini(name) ((pinit_t)(name##_init)) | 
| 106 |  |  |  |  |  |  | #define upd(name) ((pupdate_t)(name##_update)) | 
| 107 |  |  |  |  |  |  | #define fin(name) ((pfinal_t)(name##_final)) | 
| 108 |  |  |  |  |  |  | #define iuf(name) ini(name), upd(name), fin(name) | 
| 109 |  |  |  |  |  |  | #define iuf2(name1, name2) ini(name1), upd(name2), fin(name2) | 
| 110 |  |  |  |  |  |  | #define diuf(name) dgshft(name), ini(name), upd(name), fin(name) | 
| 111 |  |  |  |  |  |  |  | 
| 112 |  |  |  |  |  |  | /* information about all supported hash functions */ | 
| 113 |  |  |  |  |  |  | rhash_hash_info rhash_hash_info_default[RHASH_HASH_COUNT] = | 
| 114 |  |  |  |  |  |  | { | 
| 115 |  |  |  |  |  |  | { &info_crc32, sizeof(uint32_t), 0, iuf(rhash_crc32), 0 }, /* 32 bit */ | 
| 116 |  |  |  |  |  |  | { &info_md4, sizeof(md4_ctx), dgshft(md4), iuf(rhash_md4), 0 }, /* 128 bit */ | 
| 117 |  |  |  |  |  |  | { &info_md5, sizeof(md5_ctx), dgshft(md5), iuf(rhash_md5), 0 }, /* 128 bit */ | 
| 118 |  |  |  |  |  |  | { &info_sha1, sizeof(sha1_ctx), dgshft(sha1), iuf(rhash_sha1), 0 }, /* 160 bit */ | 
| 119 |  |  |  |  |  |  | { &info_tiger, sizeof(tiger_ctx), dgshft(tiger), iuf(rhash_tiger), 0 }, /* 192 bit */ | 
| 120 |  |  |  |  |  |  | { &info_tth, sizeof(tth_ctx), dgshft2(tth, tiger.hash), iuf(rhash_tth), 0 }, /* 192 bit */ | 
| 121 |  |  |  |  |  |  | { &info_btih, sizeof(torrent_ctx), dgshft2(torrent, btih), iuf(bt), (pcleanup_t)bt_cleanup }, /* 160 bit */ | 
| 122 |  |  |  |  |  |  | { &info_ed2k, sizeof(ed2k_ctx), dgshft2(ed2k, md4_context_inner.hash), iuf(rhash_ed2k), 0 }, /* 128 bit */ | 
| 123 |  |  |  |  |  |  | { &info_aich, sizeof(aich_ctx), dgshft2(aich, sha1_context.hash), iuf(rhash_aich), (pcleanup_t)rhash_aich_cleanup }, /* 160 bit */ | 
| 124 |  |  |  |  |  |  | { &info_whirlpool, sizeof(whirlpool_ctx), dgshft(whirlpool), iuf(rhash_whirlpool), 0 }, /* 512 bit */ | 
| 125 |  |  |  |  |  |  | { &info_rmd160, sizeof(ripemd160_ctx), dgshft(ripemd160), iuf(rhash_ripemd160), 0 }, /* 160 bit */ | 
| 126 |  |  |  |  |  |  | { &info_gost94, sizeof(gost94_ctx), dgshft(gost94), iuf(rhash_gost94), 0 }, /* 256 bit */ | 
| 127 |  |  |  |  |  |  | { &info_gost94pro, sizeof(gost94_ctx), dgshft(gost94), iuf2(rhash_gost94_cryptopro, rhash_gost94), 0 }, /* 256 bit */ | 
| 128 |  |  |  |  |  |  | { &info_has160, sizeof(has160_ctx), dgshft(has160), iuf(rhash_has160), 0 }, /* 160 bit */ | 
| 129 |  |  |  |  |  |  | { &info_gost12_256, sizeof(gost12_ctx), dgshft2(gost12, h) + 32, iuf2(rhash_gost12_256, rhash_gost12), 0 }, /* 256 bit */ | 
| 130 |  |  |  |  |  |  | { &info_gost12_512, sizeof(gost12_ctx), dgshft2(gost12, h), iuf2(rhash_gost12_512, rhash_gost12), 0 }, /* 512 bit */ | 
| 131 |  |  |  |  |  |  | { &info_sha224, sizeof(sha256_ctx), dgshft(sha256), iuf2(rhash_sha224, rhash_sha256), 0 }, /* 224 bit */ | 
| 132 |  |  |  |  |  |  | { &info_sha256, sizeof(sha256_ctx), dgshft(sha256), iuf(rhash_sha256), 0 },  /* 256 bit */ | 
| 133 |  |  |  |  |  |  | { &info_sha384, sizeof(sha512_ctx), dgshft(sha512), iuf2(rhash_sha384, rhash_sha512), 0 }, /* 384 bit */ | 
| 134 |  |  |  |  |  |  | { &info_sha512, sizeof(sha512_ctx), dgshft(sha512), iuf(rhash_sha512), 0 },  /* 512 bit */ | 
| 135 |  |  |  |  |  |  | { &info_edr256, sizeof(edonr_ctx),  dgshft2(edonr, u.data256.hash) + 32, iuf(rhash_edonr256), 0 },  /* 256 bit */ | 
| 136 |  |  |  |  |  |  | { &info_edr512, sizeof(edonr_ctx),  dgshft2(edonr, u.data512.hash) + 64, iuf(rhash_edonr512), 0 },  /* 512 bit */ | 
| 137 |  |  |  |  |  |  | { &info_sha3_224, sizeof(sha3_ctx), dgshft(sha3), iuf2(rhash_sha3_224, rhash_sha3), 0 }, /* 224 bit */ | 
| 138 |  |  |  |  |  |  | { &info_sha3_256, sizeof(sha3_ctx), dgshft(sha3), iuf2(rhash_sha3_256, rhash_sha3), 0 }, /* 256 bit */ | 
| 139 |  |  |  |  |  |  | { &info_sha3_384, sizeof(sha3_ctx), dgshft(sha3), iuf2(rhash_sha3_384, rhash_sha3), 0 }, /* 384 bit */ | 
| 140 |  |  |  |  |  |  | { &info_sha3_512, sizeof(sha3_ctx), dgshft(sha3), iuf2(rhash_sha3_512, rhash_sha3), 0 }, /* 512 bit */ | 
| 141 |  |  |  |  |  |  | { &info_crc32c, sizeof(uint32_t), 0, iuf(rhash_crc32c), 0 }, /* 32 bit */ | 
| 142 |  |  |  |  |  |  | { &info_snf128, sizeof(snefru_ctx), dgshft(snefru), iuf2(rhash_snefru128, rhash_snefru), 0 }, /* 128 bit */ | 
| 143 |  |  |  |  |  |  | { &info_snf256, sizeof(snefru_ctx), dgshft(snefru), iuf2(rhash_snefru256, rhash_snefru), 0 }, /* 256 bit */ | 
| 144 |  |  |  |  |  |  | }; | 
| 145 |  |  |  |  |  |  |  | 
| 146 |  |  |  |  |  |  | /** | 
| 147 |  |  |  |  |  |  | * Initialize requested algorithms. | 
| 148 |  |  |  |  |  |  | * | 
| 149 |  |  |  |  |  |  | * @param mask ids of hash sums to initialize | 
| 150 |  |  |  |  |  |  | */ | 
| 151 | 3 |  |  |  |  |  | void rhash_init_algorithms(unsigned mask) | 
| 152 |  |  |  |  |  |  | { | 
| 153 |  |  |  |  |  |  | (void)mask; /* unused now */ | 
| 154 |  |  |  |  |  |  |  | 
| 155 |  |  |  |  |  |  | /* verify that RHASH_HASH_COUNT is the index of the major bit of RHASH_ALL_HASHES */ | 
| 156 |  |  |  |  |  |  | assert(1 == (RHASH_ALL_HASHES >> (RHASH_HASH_COUNT - 1))); | 
| 157 |  |  |  |  |  |  |  | 
| 158 |  |  |  |  |  |  | #ifdef GENERATE_GOST94_LOOKUP_TABLE | 
| 159 |  |  |  |  |  |  | rhash_gost94_init_table(); | 
| 160 |  |  |  |  |  |  | #endif | 
| 161 | 3 |  |  |  |  |  | rhash_uninitialized_algorithms = 0; | 
| 162 | 3 |  |  |  |  |  | } | 
| 163 |  |  |  |  |  |  |  | 
| 164 |  |  |  |  |  |  | /** | 
| 165 |  |  |  |  |  |  | * Returns information about a hash function by its hash_id. | 
| 166 |  |  |  |  |  |  | * | 
| 167 |  |  |  |  |  |  | * @param hash_id the id of hash algorithm | 
| 168 |  |  |  |  |  |  | * @return pointer to the rhash_info structure containing the information | 
| 169 |  |  |  |  |  |  | */ | 
| 170 | 65 |  |  |  |  |  | const rhash_info* rhash_info_by_id(unsigned hash_id) | 
| 171 |  |  |  |  |  |  | { | 
| 172 | 65 |  |  |  |  |  | hash_id &= RHASH_ALL_HASHES; | 
| 173 |  |  |  |  |  |  | /* check that one and only one bit is set */ | 
| 174 | 65 | 50 |  |  |  |  | if (!hash_id || (hash_id & (hash_id - 1)) != 0) return NULL; | 
|  |  | 50 |  |  |  |  |  | 
| 175 | 65 |  |  |  |  |  | return rhash_info_table[rhash_ctz(hash_id)].info; | 
| 176 |  |  |  |  |  |  | } | 
| 177 |  |  |  |  |  |  |  | 
| 178 |  |  |  |  |  |  | /* CRC32 helper functions */ | 
| 179 |  |  |  |  |  |  |  | 
| 180 |  |  |  |  |  |  | /** | 
| 181 |  |  |  |  |  |  | * Initialize crc32 hash. | 
| 182 |  |  |  |  |  |  | * | 
| 183 |  |  |  |  |  |  | * @param crc32 pointer to the hash to initialize | 
| 184 |  |  |  |  |  |  | */ | 
| 185 | 3 |  |  |  |  |  | static void rhash_crc32_init(uint32_t* crc32) | 
| 186 |  |  |  |  |  |  | { | 
| 187 | 3 |  |  |  |  |  | *crc32 = 0; /* note: context size is sizeof(uint32_t) */ | 
| 188 | 3 |  |  |  |  |  | } | 
| 189 |  |  |  |  |  |  |  | 
| 190 |  |  |  |  |  |  | /** | 
| 191 |  |  |  |  |  |  | * Calculate message CRC32 hash. | 
| 192 |  |  |  |  |  |  | * Can be called repeatedly with chunks of the message to be hashed. | 
| 193 |  |  |  |  |  |  | * | 
| 194 |  |  |  |  |  |  | * @param crc32 pointer to the hash | 
| 195 |  |  |  |  |  |  | * @param msg message chunk | 
| 196 |  |  |  |  |  |  | * @param size length of the message chunk | 
| 197 |  |  |  |  |  |  | */ | 
| 198 | 3 |  |  |  |  |  | static void rhash_crc32_update(uint32_t* crc32, const unsigned char* msg, size_t size) | 
| 199 |  |  |  |  |  |  | { | 
| 200 | 3 |  |  |  |  |  | *crc32 = rhash_get_crc32(*crc32, msg, size); | 
| 201 | 3 |  |  |  |  |  | } | 
| 202 |  |  |  |  |  |  |  | 
| 203 |  |  |  |  |  |  | /** | 
| 204 |  |  |  |  |  |  | * Store calculated hash into the given array. | 
| 205 |  |  |  |  |  |  | * | 
| 206 |  |  |  |  |  |  | * @param crc32 pointer to the current hash value | 
| 207 |  |  |  |  |  |  | * @param result calculated hash in binary form | 
| 208 |  |  |  |  |  |  | */ | 
| 209 | 3 |  |  |  |  |  | static void rhash_crc32_final(uint32_t* crc32, unsigned char* result) | 
| 210 |  |  |  |  |  |  | { | 
| 211 |  |  |  |  |  |  | #if defined(CPU_IA32) || defined(CPU_X64) | 
| 212 |  |  |  |  |  |  | /* intel CPUs support assigment with non 32-bit aligned pointers */ | 
| 213 | 3 |  |  |  |  |  | *(unsigned*)result = be2me_32(*crc32); | 
| 214 |  |  |  |  |  |  | #else | 
| 215 |  |  |  |  |  |  | /* correct saving BigEndian integer on all archs */ | 
| 216 |  |  |  |  |  |  | result[0] = (unsigned char)(*crc32 >> 24), result[1] = (unsigned char)(*crc32 >> 16); | 
| 217 |  |  |  |  |  |  | result[2] = (unsigned char)(*crc32 >> 8), result[3] = (unsigned char)(*crc32); | 
| 218 |  |  |  |  |  |  | #endif | 
| 219 | 3 |  |  |  |  |  | } | 
| 220 |  |  |  |  |  |  |  | 
| 221 |  |  |  |  |  |  | /** | 
| 222 |  |  |  |  |  |  | * Initialize crc32c hash. | 
| 223 |  |  |  |  |  |  | * | 
| 224 |  |  |  |  |  |  | * @param crc32c pointer to the hash to initialize | 
| 225 |  |  |  |  |  |  | */ | 
| 226 | 2 |  |  |  |  |  | static void rhash_crc32c_init(uint32_t* crc32c) | 
| 227 |  |  |  |  |  |  | { | 
| 228 | 2 |  |  |  |  |  | *crc32c = 0; /* note: context size is sizeof(uint32_t) */ | 
| 229 | 2 |  |  |  |  |  | } | 
| 230 |  |  |  |  |  |  |  | 
| 231 |  |  |  |  |  |  | /** | 
| 232 |  |  |  |  |  |  | * Calculate message CRC32C hash. | 
| 233 |  |  |  |  |  |  | * Can be called repeatedly with chunks of the message to be hashed. | 
| 234 |  |  |  |  |  |  | * | 
| 235 |  |  |  |  |  |  | * @param crc32c pointer to the hash | 
| 236 |  |  |  |  |  |  | * @param msg message chunk | 
| 237 |  |  |  |  |  |  | * @param size length of the message chunk | 
| 238 |  |  |  |  |  |  | */ | 
| 239 | 2 |  |  |  |  |  | static void rhash_crc32c_update(uint32_t* crc32c, const unsigned char* msg, size_t size) | 
| 240 |  |  |  |  |  |  | { | 
| 241 | 2 |  |  |  |  |  | *crc32c = rhash_get_crc32c(*crc32c, msg, size); | 
| 242 | 2 |  |  |  |  |  | } | 
| 243 |  |  |  |  |  |  |  | 
| 244 |  |  |  |  |  |  | /** | 
| 245 |  |  |  |  |  |  | * Store calculated hash into the given array. | 
| 246 |  |  |  |  |  |  | * | 
| 247 |  |  |  |  |  |  | * @param crc32c pointer to the current hash value | 
| 248 |  |  |  |  |  |  | * @param result calculated hash in binary form | 
| 249 |  |  |  |  |  |  | */ | 
| 250 | 2 |  |  |  |  |  | static void rhash_crc32c_final(uint32_t* crc32c, unsigned char* result) | 
| 251 |  |  |  |  |  |  | { | 
| 252 |  |  |  |  |  |  | #if defined(CPU_IA32) || defined(CPU_X64) | 
| 253 |  |  |  |  |  |  | /* intel CPUs support assigment with non 32-bit aligned pointers */ | 
| 254 | 2 |  |  |  |  |  | *(unsigned*)result = be2me_32(*crc32c); | 
| 255 |  |  |  |  |  |  | #else | 
| 256 |  |  |  |  |  |  | /* correct saving BigEndian integer on all archs */ | 
| 257 |  |  |  |  |  |  | result[0] = (unsigned char)(*crc32c >> 24), result[1] = (unsigned char)(*crc32c >> 16); | 
| 258 |  |  |  |  |  |  | result[2] = (unsigned char)(*crc32c >> 8), result[3] = (unsigned char)(*crc32c); | 
| 259 |  |  |  |  |  |  | #endif | 
| 260 | 2 |  |  |  |  |  | } |