Path: blob/master/Utilities/cmlibrhash/librhash/algorithms.c
3150 views
/* algorithms.c - the algorithms supported by the rhash library1*2* Copyright (c) 2011, Aleksey Kravchenko <[email protected]>3*4* Permission to use, copy, modify, and/or distribute this software for any5* purpose with or without fee is hereby granted.6*7* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH8* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY9* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,10* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM11* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE12* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR13* PERFORMANCE OF THIS SOFTWARE.14*/1516#include "algorithms.h"17#include "byte_order.h"18#include "rhash.h"1920/* header files of all supported hash functions */21#if 022#include "aich.h"23#include "blake2b.h"24#include "blake2s.h"25#include "crc32.h"26#include "ed2k.h"27#include "edonr.h"28#include "gost12.h"29#include "gost94.h"30#include "has160.h"31#include "md4.h"32#endif33#include "md5.h"34#if 035#include "ripemd-160.h"36#include "snefru.h"37#endif38#include "sha1.h"39#include "sha256.h"40#include "sha512.h"41#include "sha3.h"42#if 043#include "tiger.h"44#include "tth.h"45#include "whirlpool.h"46#endif4748#ifdef USE_OPENSSL49# include "plug_openssl.h"50#endif /* USE_OPENSSL */51#include <assert.h>5253#ifdef USE_OPENSSL54/* note: BTIH and AICH depends on the used SHA1 algorithm */55# define NEED_OPENSSL_INIT (RHASH_MD4 | RHASH_MD5 | \56RHASH_SHA1 | RHASH_SHA224 | RHASH_SHA256 | RHASH_SHA384 | RHASH_SHA512 | \57RHASH_BTIH | RHASH_AICH | RHASH_RIPEMD160 | RHASH_WHIRLPOOL)58#else59# define NEED_OPENSSL_INIT 060#endif /* USE_OPENSSL */6162#ifdef GENERATE_GOST94_LOOKUP_TABLE63# define NEED_GOST94_INIT (RHASH_GOST94 | RHASH_GOST94_CRYPTOPRO)64#else65# define NEED_GOST94_INIT 066#endif /* GENERATE_GOST94_LOOKUP_TABLE */6768#define RHASH_NEED_INIT_ALG (NEED_GOST94_INIT | NEED_OPENSSL_INIT)69unsigned rhash_uninitialized_algorithms = RHASH_NEED_INIT_ALG;7071rhash_hash_info* rhash_info_table = rhash_hash_info_default;72int rhash_info_size = RHASH_HASH_COUNT;7374#if 075static void rhash_crc32_init(uint32_t* crc32);76static void rhash_crc32_update(uint32_t* crc32, const unsigned char* msg, size_t size);77static void rhash_crc32_final(uint32_t* crc32, unsigned char* result);78static void rhash_crc32c_init(uint32_t* crc32);79static void rhash_crc32c_update(uint32_t* crc32, const unsigned char* msg, size_t size);80static void rhash_crc32c_final(uint32_t* crc32, unsigned char* result);81#endif8283#if 084rhash_info info_crc32 = { RHASH_CRC32, F_BE32, 4, "CRC32", "crc32" };85rhash_info info_crc32c = { RHASH_CRC32C, F_BE32, 4, "CRC32C", "crc32c" };86rhash_info info_md4 = { RHASH_MD4, F_LE32, 16, "MD4", "md4" };87#endif88rhash_info info_md5 = { RHASH_MD5, F_LE32, 16, "MD5", "md5" };89rhash_info info_sha1 = { RHASH_SHA1, F_BE32, 20, "SHA1", "sha1" };90#if 091rhash_info info_tiger = { RHASH_TIGER, F_LE64, 24, "TIGER", "tiger" };92rhash_info info_tth = { RHASH_TTH, F_BS32 | F_SPCEXP, 24, "TTH", "tree:tiger" };93rhash_info info_btih = { RHASH_BTIH, F_SPCEXP, 20, "BTIH", "btih" };94rhash_info info_ed2k = { RHASH_ED2K, F_LE32, 16, "ED2K", "ed2k" };95rhash_info info_aich = { RHASH_AICH, F_BS32 | F_SPCEXP, 20, "AICH", "aich" };96rhash_info info_whirlpool = { RHASH_WHIRLPOOL, F_BE64, 64, "WHIRLPOOL", "whirlpool" };97rhash_info info_rmd160 = { RHASH_RIPEMD160, F_LE32, 20, "RIPEMD-160", "ripemd160" };98rhash_info info_gost12_256 = { RHASH_GOST12_256, F_LE64, 32, "GOST12-256", "gost12-256" };99rhash_info info_gost12_512 = { RHASH_GOST12_512, F_LE64, 64, "GOST12-512", "gost12-512" };100rhash_info info_gost94 = { RHASH_GOST94, F_LE32, 32, "GOST94", "gost94" };101rhash_info info_gost94pro = { RHASH_GOST94_CRYPTOPRO, F_LE32, 32, "GOST94-CRYPTOPRO", "gost94-cryptopro" };102rhash_info info_has160 = { RHASH_HAS160, F_LE32, 20, "HAS-160", "has160" };103rhash_info info_snf128 = { RHASH_SNEFRU128, F_BE32, 16, "SNEFRU-128", "snefru128" };104rhash_info info_snf256 = { RHASH_SNEFRU256, F_BE32, 32, "SNEFRU-256", "snefru256" };105#endif106rhash_info info_sha224 = { RHASH_SHA224, F_BE32, 28, "SHA-224", "sha224" };107rhash_info info_sha256 = { RHASH_SHA256, F_BE32, 32, "SHA-256", "sha256" };108rhash_info info_sha384 = { RHASH_SHA384, F_BE64, 48, "SHA-384", "sha384" };109rhash_info info_sha512 = { RHASH_SHA512, F_BE64, 64, "SHA-512", "sha512" };110#if 0111rhash_info info_edr256 = { RHASH_EDONR256, F_LE32, 32, "EDON-R256", "edon-r256" };112rhash_info info_edr512 = { RHASH_EDONR512, F_LE64, 64, "EDON-R512", "edon-r512" };113rhash_info info_blake2s = { RHASH_BLAKE2S, F_LE32, 32, "BLAKE2S", "blake2s" };114rhash_info info_blake2b = { RHASH_BLAKE2B, F_LE64, 64, "BLAKE2B", "blake2b" };115#endif116rhash_info info_sha3_224 = { RHASH_SHA3_224, F_LE64, 28, "SHA3-224", "sha3-224" };117rhash_info info_sha3_256 = { RHASH_SHA3_256, F_LE64, 32, "SHA3-256", "sha3-256" };118rhash_info info_sha3_384 = { RHASH_SHA3_384, F_LE64, 48, "SHA3-384", "sha3-384" };119rhash_info info_sha3_512 = { RHASH_SHA3_512, F_LE64, 64, "SHA3-512", "sha3-512" };120121/* some helper macros */122#define dgshft(name) ((uintptr_t)((char*)&((name##_ctx*)0)->hash))123#define dgshft2(name, field) ((uintptr_t)((char*)&((name##_ctx*)0)->field))124#define ini(name) ((pinit_t)(name##_init))125#define upd(name) ((pupdate_t)(name##_update))126#define fin(name) ((pfinal_t)(name##_final))127#define iuf(name) ini(name), upd(name), fin(name)128#define iuf2(name1, name2) ini(name1), upd(name2), fin(name2)129130/* information about all supported hash functions */131rhash_hash_info rhash_hash_info_default[RHASH_HASH_COUNT] =132{133#if 0134{ &info_crc32, sizeof(uint32_t), 0, iuf(rhash_crc32), 0 }, /* 32 bit */135{ &info_md4, sizeof(md4_ctx), dgshft(md4), iuf(rhash_md4), 0 }, /* 128 bit */136#endif137{ &info_md5, sizeof(md5_ctx), dgshft(md5), iuf(rhash_md5), 0 }, /* 128 bit */138{ &info_sha1, sizeof(sha1_ctx), dgshft(sha1), iuf(rhash_sha1), 0 }, /* 160 bit */139#if 0140{ &info_tiger, sizeof(tiger_ctx), dgshft(tiger), iuf(rhash_tiger), 0 }, /* 192 bit */141{ &info_tth, sizeof(tth_ctx), dgshft2(tth, tiger.hash), iuf(rhash_tth), 0 }, /* 192 bit */142{ &info_ed2k, sizeof(ed2k_ctx), dgshft2(ed2k, md4_context_inner.hash), iuf(rhash_ed2k), 0 }, /* 128 bit */143{ &info_aich, sizeof(aich_ctx), dgshft2(aich, sha1_context.hash), iuf(rhash_aich), (pcleanup_t)rhash_aich_cleanup }, /* 160 bit */144{ &info_whirlpool, sizeof(whirlpool_ctx), dgshft(whirlpool), iuf(rhash_whirlpool), 0 }, /* 512 bit */145{ &info_rmd160, sizeof(ripemd160_ctx), dgshft(ripemd160), iuf(rhash_ripemd160), 0 }, /* 160 bit */146{ &info_gost94, sizeof(gost94_ctx), dgshft(gost94), iuf(rhash_gost94), 0 }, /* 256 bit */147{ &info_gost94pro, sizeof(gost94_ctx), dgshft(gost94), iuf2(rhash_gost94_cryptopro, rhash_gost94), 0 }, /* 256 bit */148{ &info_has160, sizeof(has160_ctx), dgshft(has160), iuf(rhash_has160), 0 }, /* 160 bit */149{ &info_gost12_256, sizeof(gost12_ctx), dgshft2(gost12, h) + 32, iuf2(rhash_gost12_256, rhash_gost12), 0 }, /* 256 bit */150{ &info_gost12_512, sizeof(gost12_ctx), dgshft2(gost12, h), iuf2(rhash_gost12_512, rhash_gost12), 0 }, /* 512 bit */151#endif152{ &info_sha224, sizeof(sha256_ctx), dgshft(sha256), iuf2(rhash_sha224, rhash_sha256), 0 }, /* 224 bit */153{ &info_sha256, sizeof(sha256_ctx), dgshft(sha256), iuf(rhash_sha256), 0 }, /* 256 bit */154{ &info_sha384, sizeof(sha512_ctx), dgshft(sha512), iuf2(rhash_sha384, rhash_sha512), 0 }, /* 384 bit */155{ &info_sha512, sizeof(sha512_ctx), dgshft(sha512), iuf(rhash_sha512), 0 }, /* 512 bit */156#if 0157{ &info_edr256, sizeof(edonr_ctx), dgshft2(edonr, u.data256.hash) + 32, iuf(rhash_edonr256), 0 }, /* 256 bit */158{ &info_edr512, sizeof(edonr_ctx), dgshft2(edonr, u.data512.hash) + 64, iuf(rhash_edonr512), 0 }, /* 512 bit */159#endif160{ &info_sha3_224, sizeof(sha3_ctx), dgshft(sha3), iuf2(rhash_sha3_224, rhash_sha3), 0 }, /* 224 bit */161{ &info_sha3_256, sizeof(sha3_ctx), dgshft(sha3), iuf2(rhash_sha3_256, rhash_sha3), 0 }, /* 256 bit */162{ &info_sha3_384, sizeof(sha3_ctx), dgshft(sha3), iuf2(rhash_sha3_384, rhash_sha3), 0 }, /* 384 bit */163{ &info_sha3_512, sizeof(sha3_ctx), dgshft(sha3), iuf2(rhash_sha3_512, rhash_sha3), 0 }, /* 512 bit */164#if 0165{ &info_crc32c, sizeof(uint32_t), 0, iuf(rhash_crc32c), 0 }, /* 32 bit */166{ &info_snf128, sizeof(snefru_ctx), dgshft(snefru), iuf2(rhash_snefru128, rhash_snefru), 0 }, /* 128 bit */167{ &info_snf256, sizeof(snefru_ctx), dgshft(snefru), iuf2(rhash_snefru256, rhash_snefru), 0 }, /* 256 bit */168{ &info_blake2s, sizeof(blake2s_ctx), dgshft(blake2s), iuf(rhash_blake2s), 0 }, /* 256 bit */169{ &info_blake2b, sizeof(blake2b_ctx), dgshft(blake2b), iuf(rhash_blake2b), 0 }, /* 512 bit */170#endif171};172173/**174* Initialize requested algorithms.175*176* @param mask ids of hash sums to initialize177*/178void rhash_init_algorithms(unsigned mask)179{180(void)mask; /* unused now */181182/* verify that RHASH_HASH_COUNT is the index of the major bit of RHASH_ALL_HASHES */183assert(1 == (RHASH_ALL_HASHES >> (RHASH_HASH_COUNT - 1)));184185#ifdef GENERATE_GOST94_LOOKUP_TABLE186rhash_gost94_init_table();187#endif188rhash_uninitialized_algorithms = 0;189}190191/**192* Returns information about a hash function by its hash_id.193*194* @param hash_id the id of hash algorithm195* @return pointer to the rhash_info structure containing the information196*/197const rhash_info* rhash_info_by_id(unsigned hash_id)198{199hash_id &= RHASH_ALL_HASHES;200/* check that one and only one bit is set */201if (!hash_id || (hash_id & (hash_id - 1)) != 0) return NULL;202return rhash_info_table[rhash_ctz(hash_id)].info;203}204205#if 0206/* CRC32 helper functions */207208/**209* Initialize crc32 hash.210*211* @param crc32 pointer to the hash to initialize212*/213static void rhash_crc32_init(uint32_t* crc32)214{215*crc32 = 0; /* note: context size is sizeof(uint32_t) */216}217218/**219* Calculate message CRC32 hash.220* Can be called repeatedly with chunks of the message to be hashed.221*222* @param crc32 pointer to the hash223* @param msg message chunk224* @param size length of the message chunk225*/226static void rhash_crc32_update(uint32_t* crc32, const unsigned char* msg, size_t size)227{228*crc32 = rhash_get_crc32(*crc32, msg, size);229}230231/**232* Store calculated hash into the given array.233*234* @param crc32 pointer to the current hash value235* @param result calculated hash in binary form236*/237static void rhash_crc32_final(uint32_t* crc32, unsigned char* result)238{239#if defined(CPU_IA32) || defined(CPU_X64)240/* intel CPUs support assigment with non 32-bit aligned pointers */241*(unsigned*)result = be2me_32(*crc32);242#else243/* correct saving BigEndian integer on all archs */244result[0] = (unsigned char)(*crc32 >> 24), result[1] = (unsigned char)(*crc32 >> 16);245result[2] = (unsigned char)(*crc32 >> 8), result[3] = (unsigned char)(*crc32);246#endif247}248249/**250* Initialize crc32c hash.251*252* @param crc32c pointer to the hash to initialize253*/254static void rhash_crc32c_init(uint32_t* crc32c)255{256*crc32c = 0; /* note: context size is sizeof(uint32_t) */257}258259/**260* Calculate message CRC32C hash.261* Can be called repeatedly with chunks of the message to be hashed.262*263* @param crc32c pointer to the hash264* @param msg message chunk265* @param size length of the message chunk266*/267static void rhash_crc32c_update(uint32_t* crc32c, const unsigned char* msg, size_t size)268{269*crc32c = rhash_get_crc32c(*crc32c, msg, size);270}271272/**273* Store calculated hash into the given array.274*275* @param crc32c pointer to the current hash value276* @param result calculated hash in binary form277*/278static void rhash_crc32c_final(uint32_t* crc32c, unsigned char* result)279{280#if defined(CPU_IA32) || defined(CPU_X64)281/* intel CPUs support assigment with non 32-bit aligned pointers */282*(unsigned*)result = be2me_32(*crc32c);283#else284/* correct saving BigEndian integer on all archs */285result[0] = (unsigned char)(*crc32c >> 24), result[1] = (unsigned char)(*crc32c >> 16);286result[2] = (unsigned char)(*crc32c >> 8), result[3] = (unsigned char)(*crc32c);287#endif288}289#endif290291#if !defined(NO_IMPORT_EXPORT)292/**293* Export a hash function context to a memory region,294* or calculate the size required for context export.295*296* @param hash_id identifier of the hash function297* @param ctx the algorithm context containing current hashing state298* @param out pointer to the memory region or NULL299* @param size size of memory region300* @return the size of the exported data on success, 0 on fail.301*/302size_t rhash_export_alg(unsigned hash_id, const void* ctx, void* out, size_t size)303{304switch (hash_id)305{306case RHASH_TTH:307return rhash_tth_export((const tth_ctx*)ctx, out, size);308case RHASH_AICH:309return rhash_aich_export((const aich_ctx*)ctx, out, size);310}311return 0;312}313314/**315* Import a hash function context from a memory region.316*317* @param hash_id identifier of the hash function318* @param ctx pointer to the algorithm context319* @param in pointer to the data to import320* @param size size of data to import321* @return the size of the imported data on success, 0 on fail.322*/323size_t rhash_import_alg(unsigned hash_id, void* ctx, const void* in, size_t size)324{325switch (hash_id)326{327case RHASH_TTH:328return rhash_tth_import((tth_ctx*)ctx, in, size);329case RHASH_AICH:330return rhash_aich_import((aich_ctx*)ctx, in, size);331}332return 0;333}334#endif /* !defined(NO_IMPORT_EXPORT) */335336#ifdef USE_OPENSSL337void rhash_load_sha1_methods(rhash_hashing_methods* methods, int methods_type)338{339int use_openssl;340switch (methods_type) {341case METHODS_OPENSSL:342use_openssl = 1;343break;344case METHODS_SELECTED:345assert(rhash_info_table[3].info->hash_id == RHASH_SHA1);346use_openssl = ARE_OPENSSL_METHODS(rhash_info_table[3]);347break;348default:349use_openssl = 0;350break;351}352if (use_openssl) {353methods->init = rhash_ossl_sha1_init();354methods->update = rhash_ossl_sha1_update();355methods->final = rhash_ossl_sha1_final();356} else {357methods->init = (pinit_t)&rhash_sha1_init;358methods->update = (pupdate_t)&rhash_sha1_update;359methods->final = (pfinal_t)&rhash_sha1_final;360}361}362#endif363364365