mirror of
https://github.com/reactos/CMake.git
synced 2024-11-25 04:29:52 +00:00
Merge branch 'upstream-librhash' into import-librhash
* upstream-librhash: librhash 2016-11-01 (d839a1a8)
This commit is contained in:
commit
5cb1b345d9
1
Utilities/cmlibrhash/.gitattributes
vendored
Normal file
1
Utilities/cmlibrhash/.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
* -whitespace
|
15
Utilities/cmlibrhash/COPYING
Normal file
15
Utilities/cmlibrhash/COPYING
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
RHash License
|
||||
|
||||
Copyright (c) 2005-2014 Aleksey Kravchenko <rhash.admin@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so.
|
||||
|
||||
The Software is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Use this program at your own risk!
|
61
Utilities/cmlibrhash/README
Normal file
61
Utilities/cmlibrhash/README
Normal file
@ -0,0 +1,61 @@
|
||||
=== RHash program ===
|
||||
|
||||
RHash is a console utility for calculation and verification of magnet links
|
||||
and a wide range of hash sums like CRC32, MD4, MD5, SHA1, SHA256, SHA512,
|
||||
SHA3, AICH, ED2K, Tiger, DC++ TTH, BitTorrent BTIH, GOST R 34.11-94,
|
||||
RIPEMD-160, HAS-160, EDON-R, Whirlpool and Snefru.
|
||||
|
||||
Hash sums are used to ensure and verify integrity of large volumes of data
|
||||
for a long-term storing or transferring.
|
||||
|
||||
Features:
|
||||
* Output in a predefined (SFV, BSD-like) or a user-defined format.
|
||||
* Can calculate Magnet links.
|
||||
* Updating hash files (adding hash sums of files missing in the hash file).
|
||||
* Calculates several hash sums in one pass
|
||||
* Ability to process directories recursively.
|
||||
* Portability: the program works the same on Linux, *BSD or Windows.
|
||||
|
||||
|
||||
=== The LibRHash library ===
|
||||
|
||||
LibRHash is a professional, portable, thread-safe C library for computing
|
||||
a wide variety of hash sums, such as CRC32, MD4, MD5, SHA1, SHA256, SHA512,
|
||||
SHA3, AICH, ED2K, Tiger, DC++ TTH, BitTorrent BTIH, GOST R 34.11-94,
|
||||
RIPEMD-160, HAS-160, EDON-R, Whirlpool and Snefru.
|
||||
Hash sums are used to ensure and verify integrity of large volumes of data
|
||||
for a long-term storing or transferring.
|
||||
|
||||
Features:
|
||||
* Small and easy to learn interface.
|
||||
* Hi-level and Low-level API.
|
||||
* Allows calculating of several hash functions simultaneously.
|
||||
* Portability: the library works on Linux, *BSD and Windows.
|
||||
|
||||
|
||||
=== Links ===
|
||||
|
||||
* Project Home Page: http://rhash.sourceforge.net/
|
||||
* Official Releases: http://sf.net/projects/rhash/files/rhash/
|
||||
|
||||
* RHash hash functions descriptions http://rhash.anz.ru/hashes.php
|
||||
* The table of the hash functions supported by RHash
|
||||
http://sf.net/apps/mediawiki/rhash/index.php?title=Hash_sums
|
||||
* ECRYPT: The Hash Function Zoo
|
||||
http://ehash.iaik.tugraz.at/wiki/The_Hash_Function_Zoo
|
||||
|
||||
|
||||
=== Getting latest source code ===
|
||||
|
||||
The latest source code can be obtained from Git repository by command:
|
||||
|
||||
git clone git://github.com/rhash/RHash.git
|
||||
|
||||
|
||||
=== Notes on RHash License ===
|
||||
|
||||
The RHash program and LibRHash library are distributed under RHash License,
|
||||
see the COPYING file for details. In particular, the program, the library
|
||||
and source code can be used free of charge under the MIT, BSD, GPL,
|
||||
commercial or freeware license without additional restrictions. In the case
|
||||
the OSI-approved license is required the MIT license should be used.
|
200
Utilities/cmlibrhash/librhash/algorithms.c
Normal file
200
Utilities/cmlibrhash/librhash/algorithms.c
Normal file
@ -0,0 +1,200 @@
|
||||
/* algorithms.c - the algorithms supported by the rhash library
|
||||
*
|
||||
* Copyright: 2011-2012 Aleksey Kravchenko <rhash.admin@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "byte_order.h"
|
||||
#include "rhash.h"
|
||||
#include "algorithms.h"
|
||||
|
||||
/* header files of all supported hash sums */
|
||||
#include "aich.h"
|
||||
#include "crc32.h"
|
||||
#include "ed2k.h"
|
||||
#include "edonr.h"
|
||||
#include "gost.h"
|
||||
#include "has160.h"
|
||||
#include "md4.h"
|
||||
#include "md5.h"
|
||||
#include "ripemd-160.h"
|
||||
#include "snefru.h"
|
||||
#include "sha1.h"
|
||||
#include "sha256.h"
|
||||
#include "sha512.h"
|
||||
#include "sha3.h"
|
||||
#include "tiger.h"
|
||||
#include "torrent.h"
|
||||
#include "tth.h"
|
||||
#include "whirlpool.h"
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
/* note: BTIH and AICH depends on the used SHA1 algorithm */
|
||||
# define NEED_OPENSSL_INIT (RHASH_MD4 | RHASH_MD5 | \
|
||||
RHASH_SHA1 | RHASH_SHA224 | RHASH_SHA256 | RHASH_SHA384 | RHASH_SHA512 | \
|
||||
RHASH_BTIH | RHASH_AICH | RHASH_RIPEMD160 | RHASH_WHIRLPOOL)
|
||||
#else
|
||||
# define NEED_OPENSSL_INIT 0
|
||||
#endif /* USE_OPENSSL */
|
||||
#ifdef GENERATE_GOST_LOOKUP_TABLE
|
||||
# define NEED_GOST_INIT (RHASH_GOST | RHASH_GOST_CRYPTOPRO)
|
||||
#else
|
||||
# define NEED_GOST_INIT 0
|
||||
#endif /* GENERATE_GOST_LOOKUP_TABLE */
|
||||
#ifdef GENERATE_CRC32_TABLE
|
||||
# define NEED_CRC32_INIT RHASH_CRC32
|
||||
#else
|
||||
# define NEED_CRC32_INIT 0
|
||||
#endif /* GENERATE_CRC32_TABLE */
|
||||
|
||||
#define RHASH_NEED_INIT_ALG (NEED_CRC32_INIT | NEED_GOST_INIT | NEED_OPENSSL_INIT)
|
||||
unsigned rhash_uninitialized_algorithms = RHASH_NEED_INIT_ALG;
|
||||
|
||||
rhash_hash_info* rhash_info_table = rhash_hash_info_default;
|
||||
int rhash_info_size = RHASH_HASH_COUNT;
|
||||
|
||||
static void rhash_crc32_init(uint32_t* crc32);
|
||||
static void rhash_crc32_update(uint32_t* crc32, const unsigned char* msg, size_t size);
|
||||
static void rhash_crc32_final(uint32_t* crc32, unsigned char* result);
|
||||
|
||||
rhash_info info_crc32 = { RHASH_CRC32, F_BE32, 4, "CRC32", "crc32" };
|
||||
rhash_info info_md4 = { RHASH_MD4, F_LE32, 16, "MD4", "md4" };
|
||||
rhash_info info_md5 = { RHASH_MD5, F_LE32, 16, "MD5", "md5" };
|
||||
rhash_info info_sha1 = { RHASH_SHA1, F_BE32, 20, "SHA1", "sha1" };
|
||||
rhash_info info_tiger = { RHASH_TIGER, F_LE64, 24, "TIGER", "tiger" };
|
||||
rhash_info info_tth = { RHASH_TTH, F_BS32, 24, "TTH", "tree:tiger" };
|
||||
rhash_info info_btih = { RHASH_BTIH, 0, 20, "BTIH", "btih" };
|
||||
rhash_info info_ed2k = { RHASH_ED2K, F_LE32, 16, "ED2K", "ed2k" };
|
||||
rhash_info info_aich = { RHASH_AICH, F_BS32, 20, "AICH", "aich" };
|
||||
rhash_info info_whirlpool = { RHASH_WHIRLPOOL, F_BE64, 64, "WHIRLPOOL", "whirlpool" };
|
||||
rhash_info info_rmd160 = { RHASH_RIPEMD160, F_LE32, 20, "RIPEMD-160", "ripemd160" };
|
||||
rhash_info info_gost = { RHASH_GOST, F_LE32, 32, "GOST", "gost" };
|
||||
rhash_info info_gostpro = { RHASH_GOST_CRYPTOPRO, F_LE32, 32, "GOST-CRYPTOPRO", "gost-cryptopro" };
|
||||
rhash_info info_has160 = { RHASH_HAS160, F_LE32, 20, "HAS-160", "has160" };
|
||||
rhash_info info_snf128 = { RHASH_SNEFRU128, F_BE32, 16, "SNEFRU-128", "snefru128" };
|
||||
rhash_info info_snf256 = { RHASH_SNEFRU256, F_BE32, 32, "SNEFRU-256", "snefru256" };
|
||||
rhash_info info_sha224 = { RHASH_SHA224, F_BE32, 28, "SHA-224", "sha224" };
|
||||
rhash_info info_sha256 = { RHASH_SHA256, F_BE32, 32, "SHA-256", "sha256" };
|
||||
rhash_info info_sha384 = { RHASH_SHA384, F_BE64, 48, "SHA-384", "sha384" };
|
||||
rhash_info info_sha512 = { RHASH_SHA512, F_BE64, 64, "SHA-512", "sha512" };
|
||||
rhash_info info_edr256 = { RHASH_EDONR256, F_LE32, 32, "EDON-R256", "edon-r256" };
|
||||
rhash_info info_edr512 = { RHASH_EDONR512, F_LE64, 64, "EDON-R512", "edon-r512" };
|
||||
rhash_info info_sha3_224 = { RHASH_SHA3_224, F_LE64, 28, "SHA3-224", "sha3-224" };
|
||||
rhash_info info_sha3_256 = { RHASH_SHA3_256, F_LE64, 32, "SHA3-256", "sha3-256" };
|
||||
rhash_info info_sha3_384 = { RHASH_SHA3_384, F_LE64, 48, "SHA3-384", "sha3-384" };
|
||||
rhash_info info_sha3_512 = { RHASH_SHA3_512, F_LE64, 64, "SHA3-512", "sha3-512" };
|
||||
|
||||
/* some helper macros */
|
||||
#define dgshft(name) (((char*)&((name##_ctx*)0)->hash) - (char*)0)
|
||||
#define dgshft2(name, field) (((char*)&((name##_ctx*)0)->field) - (char*)0)
|
||||
#define ini(name) ((pinit_t)(name##_init))
|
||||
#define upd(name) ((pupdate_t)(name##_update))
|
||||
#define fin(name) ((pfinal_t)(name##_final))
|
||||
#define iuf(name) ini(name), upd(name), fin(name)
|
||||
#define diuf(name) dgshft(name), ini(name), upd(name), fin(name)
|
||||
|
||||
/* information about all hashes */
|
||||
rhash_hash_info rhash_hash_info_default[RHASH_HASH_COUNT] =
|
||||
{
|
||||
{ &info_crc32, sizeof(uint32_t), 0, iuf(rhash_crc32), 0 }, /* 32 bit */
|
||||
{ &info_md4, sizeof(md4_ctx), dgshft(md4), iuf(rhash_md4), 0 }, /* 128 bit */
|
||||
{ &info_md5, sizeof(md5_ctx), dgshft(md5), iuf(rhash_md5), 0 }, /* 128 bit */
|
||||
{ &info_sha1, sizeof(sha1_ctx), dgshft(sha1), iuf(rhash_sha1), 0 }, /* 160 bit */
|
||||
{ &info_tiger, sizeof(tiger_ctx), dgshft(tiger), iuf(rhash_tiger), 0 }, /* 192 bit */
|
||||
{ &info_tth, sizeof(tth_ctx), dgshft2(tth, tiger.hash), iuf(rhash_tth), 0 }, /* 192 bit */
|
||||
{ &info_btih, sizeof(torrent_ctx), dgshft2(torrent, btih), iuf(bt), (pcleanup_t)bt_cleanup }, /* 160 bit */
|
||||
{ &info_ed2k, sizeof(ed2k_ctx), dgshft2(ed2k, md4_context_inner.hash), iuf(rhash_ed2k), 0 }, /* 128 bit */
|
||||
{ &info_aich, sizeof(aich_ctx), dgshft2(aich, sha1_context.hash), iuf(rhash_aich), (pcleanup_t)rhash_aich_cleanup }, /* 160 bit */
|
||||
{ &info_whirlpool, sizeof(whirlpool_ctx), dgshft(whirlpool), iuf(rhash_whirlpool), 0 }, /* 512 bit */
|
||||
{ &info_rmd160, sizeof(ripemd160_ctx), dgshft(ripemd160), iuf(rhash_ripemd160), 0 }, /* 160 bit */
|
||||
{ &info_gost, sizeof(gost_ctx), dgshft(gost), iuf(rhash_gost), 0 }, /* 256 bit */
|
||||
{ &info_gostpro, sizeof(gost_ctx), dgshft(gost), ini(rhash_gost_cryptopro), upd(rhash_gost), fin(rhash_gost), 0 }, /* 256 bit */
|
||||
{ &info_has160, sizeof(has160_ctx), dgshft(has160), iuf(rhash_has160), 0 }, /* 160 bit */
|
||||
{ &info_snf128, sizeof(snefru_ctx), dgshft(snefru), ini(rhash_snefru128), upd(rhash_snefru), fin(rhash_snefru), 0 }, /* 128 bit */
|
||||
{ &info_snf256, sizeof(snefru_ctx), dgshft(snefru), ini(rhash_snefru256), upd(rhash_snefru), fin(rhash_snefru), 0 }, /* 256 bit */
|
||||
{ &info_sha224, sizeof(sha256_ctx), dgshft(sha256), ini(rhash_sha224), upd(rhash_sha256), fin(rhash_sha256), 0 }, /* 224 bit */
|
||||
{ &info_sha256, sizeof(sha256_ctx), dgshft(sha256), iuf(rhash_sha256), 0 }, /* 256 bit */
|
||||
{ &info_sha384, sizeof(sha512_ctx), dgshft(sha512), ini(rhash_sha384), upd(rhash_sha512), fin(rhash_sha512), 0 }, /* 384 bit */
|
||||
{ &info_sha512, sizeof(sha512_ctx), dgshft(sha512), iuf(rhash_sha512), 0 }, /* 512 bit */
|
||||
{ &info_edr256, sizeof(edonr_ctx), dgshft2(edonr, u.data256.hash) + 32, iuf(rhash_edonr256), 0 }, /* 256 bit */
|
||||
{ &info_edr512, sizeof(edonr_ctx), dgshft2(edonr, u.data512.hash) + 64, iuf(rhash_edonr512), 0 }, /* 512 bit */
|
||||
{ &info_sha3_224, sizeof(sha3_ctx), dgshft(sha3), ini(rhash_sha3_224), upd(rhash_sha3), fin(rhash_sha3), 0 }, /* 224 bit */
|
||||
{ &info_sha3_256, sizeof(sha3_ctx), dgshft(sha3), ini(rhash_sha3_256), upd(rhash_sha3), fin(rhash_sha3), 0 }, /* 256 bit */
|
||||
{ &info_sha3_384, sizeof(sha3_ctx), dgshft(sha3), ini(rhash_sha3_384), upd(rhash_sha3), fin(rhash_sha3), 0 }, /* 384 bit */
|
||||
{ &info_sha3_512, sizeof(sha3_ctx), dgshft(sha3), ini(rhash_sha3_512), upd(rhash_sha3), fin(rhash_sha3), 0 }, /* 512 bit */
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize requested algorithms.
|
||||
*/
|
||||
void rhash_init_algorithms(unsigned mask)
|
||||
{
|
||||
(void)mask; /* unused now */
|
||||
|
||||
/* verify that RHASH_HASH_COUNT is the index of the major bit of RHASH_ALL_HASHES */
|
||||
assert(1 == (RHASH_ALL_HASHES >> (RHASH_HASH_COUNT - 1)));
|
||||
|
||||
#ifdef GENERATE_CRC32_TABLE
|
||||
rhash_crc32_init_table();
|
||||
#endif
|
||||
#ifdef GENERATE_GOST_LOOKUP_TABLE
|
||||
rhash_gost_init_table();
|
||||
#endif
|
||||
rhash_uninitialized_algorithms = 0;
|
||||
}
|
||||
|
||||
/* CRC32 helper functions */
|
||||
|
||||
/**
|
||||
* Initialize crc32 hash.
|
||||
*
|
||||
* @param crc32 pointer to the hash to initialize
|
||||
*/
|
||||
static void rhash_crc32_init(uint32_t* crc32)
|
||||
{
|
||||
*crc32 = 0; /* note: context size is sizeof(uint32_t) */
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate message CRC32 hash.
|
||||
* Can be called repeatedly with chunks of the message to be hashed.
|
||||
*
|
||||
* @param crc32 pointer to the hash
|
||||
* @param msg message chunk
|
||||
* @param size length of the message chunk
|
||||
*/
|
||||
static void rhash_crc32_update(uint32_t* crc32, const unsigned char* msg, size_t size)
|
||||
{
|
||||
*crc32 = rhash_get_crc32(*crc32, msg, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store calculated hash into the given array.
|
||||
*
|
||||
* @param crc32 pointer to the current hash value
|
||||
* @param result calculated hash in binary form
|
||||
*/
|
||||
static void rhash_crc32_final(uint32_t* crc32, unsigned char* result)
|
||||
{
|
||||
#if defined(CPU_IA32) || defined(CPU_X64)
|
||||
/* intel CPUs support assigment with non 32-bit aligned pointers */
|
||||
*(unsigned*)result = be2me_32(*crc32);
|
||||
#else
|
||||
/* correct saving BigEndian integer on all archs */
|
||||
result[0] = (unsigned char)(*crc32 >> 24), result[1] = (unsigned char)(*crc32 >> 16);
|
||||
result[2] = (unsigned char)(*crc32 >> 8), result[3] = (unsigned char)(*crc32);
|
||||
#endif
|
||||
}
|
120
Utilities/cmlibrhash/librhash/algorithms.h
Normal file
120
Utilities/cmlibrhash/librhash/algorithms.h
Normal file
@ -0,0 +1,120 @@
|
||||
/* algorithms.h - rhash library algorithms */
|
||||
#ifndef RHASH_ALGORITHMS_H
|
||||
#define RHASH_ALGORITHMS_H
|
||||
|
||||
#include <stddef.h> /* for ptrdiff_t */
|
||||
#include "rhash.h"
|
||||
#include "byte_order.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef RHASH_API
|
||||
/* modifier for RHash library functions */
|
||||
# define RHASH_API
|
||||
#endif
|
||||
|
||||
typedef void (*pinit_t)(void*);
|
||||
typedef void (*pupdate_t)(void *ctx, const void* msg, size_t size);
|
||||
typedef void (*pfinal_t)(void*, unsigned char*);
|
||||
typedef void (*pcleanup_t)(void*);
|
||||
|
||||
/**
|
||||
* Information about a hash function
|
||||
*/
|
||||
typedef struct rhash_hash_info
|
||||
{
|
||||
rhash_info *info;
|
||||
size_t context_size;
|
||||
ptrdiff_t digest_diff;
|
||||
pinit_t init;
|
||||
pupdate_t update;
|
||||
pfinal_t final;
|
||||
pcleanup_t cleanup;
|
||||
} rhash_hash_info;
|
||||
|
||||
/**
|
||||
* Information on a hash function and its context
|
||||
*/
|
||||
typedef struct rhash_vector_item
|
||||
{
|
||||
struct rhash_hash_info* hash_info;
|
||||
void *context;
|
||||
} rhash_vector_item;
|
||||
|
||||
/**
|
||||
* The rhash context containing contexts for several hash functions
|
||||
*/
|
||||
typedef struct rhash_context_ext
|
||||
{
|
||||
struct rhash_context rc;
|
||||
unsigned hash_vector_size; /* number of contained hash sums */
|
||||
unsigned flags;
|
||||
unsigned state;
|
||||
void *callback, *callback_data;
|
||||
void *bt_ctx;
|
||||
rhash_vector_item vector[1]; /* contexts of contained hash sums */
|
||||
} rhash_context_ext;
|
||||
|
||||
extern rhash_hash_info rhash_hash_info_default[RHASH_HASH_COUNT];
|
||||
extern rhash_hash_info* rhash_info_table;
|
||||
extern int rhash_info_size;
|
||||
extern unsigned rhash_uninitialized_algorithms;
|
||||
|
||||
extern rhash_info info_crc32;
|
||||
extern rhash_info info_md4;
|
||||
extern rhash_info info_md5;
|
||||
extern rhash_info info_sha1;
|
||||
extern rhash_info info_tiger;
|
||||
extern rhash_info info_tth ;
|
||||
extern rhash_info info_btih;
|
||||
extern rhash_info info_ed2k;
|
||||
extern rhash_info info_aich;
|
||||
extern rhash_info info_whirlpool;
|
||||
extern rhash_info info_rmd160;
|
||||
extern rhash_info info_gost;
|
||||
extern rhash_info info_gostpro;
|
||||
extern rhash_info info_has160;
|
||||
extern rhash_info info_snf128;
|
||||
extern rhash_info info_snf256;
|
||||
extern rhash_info info_sha224;
|
||||
extern rhash_info info_sha256;
|
||||
extern rhash_info info_sha384;
|
||||
extern rhash_info info_sha512;
|
||||
extern rhash_info info_sha3_224;
|
||||
extern rhash_info info_sha3_256;
|
||||
extern rhash_info info_sha3_384;
|
||||
extern rhash_info info_sha3_512;
|
||||
extern rhash_info info_edr256;
|
||||
extern rhash_info info_edr512;
|
||||
|
||||
/* rhash_info flags */
|
||||
#define F_BS32 1 /* default output in base32 */
|
||||
#define F_SWAP32 2 /* Big endian flag */
|
||||
#define F_SWAP64 4
|
||||
|
||||
/* define endianness flags */
|
||||
#ifndef CPU_BIG_ENDIAN
|
||||
#define F_LE32 0
|
||||
#define F_LE64 0
|
||||
#define F_BE32 F_SWAP32
|
||||
#define F_BE64 F_SWAP64
|
||||
#else
|
||||
#define F_LE32 F_SWAP32
|
||||
#define F_LE64 F_SWAP64
|
||||
#define F_BE32 0
|
||||
#define F_BE64 0
|
||||
#endif
|
||||
|
||||
void rhash_init_algorithms(unsigned mask);
|
||||
|
||||
#if defined(OPENSSL_RUNTIME) && !defined(USE_OPENSSL)
|
||||
# define USE_OPENSSL
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* RHASH_ALGORITHMS_H */
|
150
Utilities/cmlibrhash/librhash/byte_order.c
Normal file
150
Utilities/cmlibrhash/librhash/byte_order.c
Normal file
@ -0,0 +1,150 @@
|
||||
/* byte_order.c - byte order related platform dependent routines,
|
||||
*
|
||||
* Copyright: 2008-2012 Aleksey Kravchenko <rhash.admin@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
|
||||
*/
|
||||
#include "byte_order.h"
|
||||
|
||||
#if !(__GNUC__ >= 4 || (__GNUC__ ==3 && __GNUC_MINOR__ >= 4)) /* if !GCC or GCC < 4.3 */
|
||||
|
||||
# if _MSC_VER >= 1300 && (_M_IX86 || _M_AMD64 || _M_IA64) /* if MSVC++ >= 2002 on x86/x64 */
|
||||
# include <intrin.h>
|
||||
# pragma intrinsic(_BitScanForward)
|
||||
|
||||
/**
|
||||
* Returns index of the trailing bit of x.
|
||||
*
|
||||
* @param x the number to process
|
||||
* @return zero-based index of the trailing bit
|
||||
*/
|
||||
unsigned rhash_ctz(unsigned x)
|
||||
{
|
||||
unsigned long index;
|
||||
unsigned char isNonzero = _BitScanForward(&index, x); /* MSVC intrinsic */
|
||||
return (isNonzero ? (unsigned)index : 0);
|
||||
}
|
||||
# else /* _MSC_VER >= 1300... */
|
||||
|
||||
/**
|
||||
* Returns index of the trailing bit of a 32-bit number.
|
||||
* This is a plain C equivalent for GCC __builtin_ctz() bit scan.
|
||||
*
|
||||
* @param x the number to process
|
||||
* @return zero-based index of the trailing bit
|
||||
*/
|
||||
unsigned rhash_ctz(unsigned x)
|
||||
{
|
||||
/* array for conversion to bit position */
|
||||
static unsigned char bit_pos[32] = {
|
||||
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
|
||||
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
|
||||
};
|
||||
|
||||
/* The De Bruijn bit-scan was devised in 1997, according to Donald Knuth
|
||||
* by Martin Lauter. The constant 0x077CB531UL is a De Bruijn sequence,
|
||||
* which produces a unique pattern of bits into the high 5 bits for each
|
||||
* possible bit position that it is multiplied against.
|
||||
* See http://graphics.stanford.edu/~seander/bithacks.html
|
||||
* and http://chessprogramming.wikispaces.com/BitScan */
|
||||
return (unsigned)bit_pos[((uint32_t)((x & -x) * 0x077CB531U)) >> 27];
|
||||
}
|
||||
# endif /* _MSC_VER >= 1300... */
|
||||
#endif /* !(GCC >= 4.3) */
|
||||
|
||||
/**
|
||||
* Copy a memory block with simultaneous exchanging byte order.
|
||||
* The byte order is changed from little-endian 32-bit integers
|
||||
* to big-endian (or vice-versa).
|
||||
*
|
||||
* @param to the pointer where to copy memory block
|
||||
* @param index the index to start writing from
|
||||
* @param from the source block to copy
|
||||
* @param length length of the memory block
|
||||
*/
|
||||
void rhash_swap_copy_str_to_u32(void* to, int index, const void* from, size_t length)
|
||||
{
|
||||
/* if all pointers and length are 32-bits aligned */
|
||||
if ( 0 == (( (int)((char*)to - (char*)0) | ((char*)from - (char*)0) | index | length ) & 3) ) {
|
||||
/* copy memory as 32-bit words */
|
||||
const uint32_t* src = (const uint32_t*)from;
|
||||
const uint32_t* end = (const uint32_t*)((const char*)src + length);
|
||||
uint32_t* dst = (uint32_t*)((char*)to + index);
|
||||
while (src < end) *(dst++) = bswap_32( *(src++) );
|
||||
} else {
|
||||
const char* src = (const char*)from;
|
||||
for (length += index; (size_t)index < length; index++) ((char*)to)[index ^ 3] = *(src++);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a memory block with changed byte order.
|
||||
* The byte order is changed from little-endian 64-bit integers
|
||||
* to big-endian (or vice-versa).
|
||||
*
|
||||
* @param to the pointer where to copy memory block
|
||||
* @param index the index to start writing from
|
||||
* @param from the source block to copy
|
||||
* @param length length of the memory block
|
||||
*/
|
||||
void rhash_swap_copy_str_to_u64(void* to, int index, const void* from, size_t length)
|
||||
{
|
||||
/* if all pointers and length are 64-bits aligned */
|
||||
if ( 0 == (( (int)((char*)to - (char*)0) | ((char*)from - (char*)0) | index | length ) & 7) ) {
|
||||
/* copy aligned memory block as 64-bit integers */
|
||||
const uint64_t* src = (const uint64_t*)from;
|
||||
const uint64_t* end = (const uint64_t*)((const char*)src + length);
|
||||
uint64_t* dst = (uint64_t*)((char*)to + index);
|
||||
while (src < end) *(dst++) = bswap_64( *(src++) );
|
||||
} else {
|
||||
const char* src = (const char*)from;
|
||||
for (length += index; (size_t)index < length; index++) ((char*)to)[index ^ 7] = *(src++);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy data from a sequence of 64-bit words to a binary string of given length,
|
||||
* while changing byte order.
|
||||
*
|
||||
* @param to the binary string to receive data
|
||||
* @param from the source sequence of 64-bit words
|
||||
* @param length the size in bytes of the data being copied
|
||||
*/
|
||||
void rhash_swap_copy_u64_to_str(void* to, const void* from, size_t length)
|
||||
{
|
||||
/* if all pointers and length are 64-bits aligned */
|
||||
if ( 0 == (( (int)((char*)to - (char*)0) | ((char*)from - (char*)0) | length ) & 7) ) {
|
||||
/* copy aligned memory block as 64-bit integers */
|
||||
const uint64_t* src = (const uint64_t*)from;
|
||||
const uint64_t* end = (const uint64_t*)((const char*)src + length);
|
||||
uint64_t* dst = (uint64_t*)to;
|
||||
while (src < end) *(dst++) = bswap_64( *(src++) );
|
||||
} else {
|
||||
size_t index;
|
||||
char* dst = (char*)to;
|
||||
for (index = 0; index < length; index++) *(dst++) = ((char*)from)[index ^ 7];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exchange byte order in the given array of 32-bit integers.
|
||||
*
|
||||
* @param arr the array to process
|
||||
* @param length array length
|
||||
*/
|
||||
void rhash_u32_mem_swap(unsigned *arr, int length)
|
||||
{
|
||||
unsigned* end = arr + length;
|
||||
for (; arr < end; arr++) {
|
||||
*arr = bswap_32(*arr);
|
||||
}
|
||||
}
|
171
Utilities/cmlibrhash/librhash/byte_order.h
Normal file
171
Utilities/cmlibrhash/librhash/byte_order.h
Normal file
@ -0,0 +1,171 @@
|
||||
/* byte_order.h */
|
||||
#ifndef BYTE_ORDER_H
|
||||
#define BYTE_ORDER_H
|
||||
#include "ustd.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef IN_RHASH
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef __GLIBC__
|
||||
# include <endian.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* if x86 compatible cpu */
|
||||
#if defined(i386) || defined(__i386__) || defined(__i486__) || \
|
||||
defined(__i586__) || defined(__i686__) || defined(__pentium__) || \
|
||||
defined(__pentiumpro__) || defined(__pentium4__) || \
|
||||
defined(__nocona__) || defined(prescott) || defined(__core2__) || \
|
||||
defined(__k6__) || defined(__k8__) || defined(__athlon__) || \
|
||||
defined(__amd64) || defined(__amd64__) || \
|
||||
defined(__x86_64) || defined(__x86_64__) || defined(_M_IX86) || \
|
||||
defined(_M_AMD64) || defined(_M_IA64) || defined(_M_X64)
|
||||
/* detect if x86-64 instruction set is supported */
|
||||
# if defined(_LP64) || defined(__LP64__) || defined(__x86_64) || \
|
||||
defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
|
||||
# define CPU_X64
|
||||
# else
|
||||
# define CPU_IA32
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* detect CPU endianness */
|
||||
#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
|
||||
__BYTE_ORDER == __LITTLE_ENDIAN) || \
|
||||
defined(CPU_IA32) || defined(CPU_X64) || \
|
||||
defined(__ia64) || defined(__ia64__) || defined(__alpha__) || defined(_M_ALPHA) || \
|
||||
defined(vax) || defined(MIPSEL) || defined(_ARM_) || defined(__arm__)
|
||||
# define CPU_LITTLE_ENDIAN
|
||||
# define IS_BIG_ENDIAN 0
|
||||
# define IS_LITTLE_ENDIAN 1
|
||||
#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
|
||||
__BYTE_ORDER == __BIG_ENDIAN) || \
|
||||
defined(__sparc) || defined(__sparc__) || defined(sparc) || \
|
||||
defined(_ARCH_PPC) || defined(_ARCH_PPC64) || defined(_POWER) || \
|
||||
defined(__POWERPC__) || defined(POWERPC) || defined(__powerpc) || \
|
||||
defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__) || \
|
||||
defined(__hpux) || defined(_MIPSEB) || defined(mc68000) || \
|
||||
defined(__s390__) || defined(__s390x__) || defined(sel)
|
||||
# define CPU_BIG_ENDIAN
|
||||
# define IS_BIG_ENDIAN 1
|
||||
# define IS_LITTLE_ENDIAN 0
|
||||
#else
|
||||
# error "Can't detect CPU architechture"
|
||||
#endif
|
||||
|
||||
#define IS_ALIGNED_32(p) (0 == (3 & ((const char*)(p) - (const char*)0)))
|
||||
#define IS_ALIGNED_64(p) (0 == (7 & ((const char*)(p) - (const char*)0)))
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define ALIGN_ATTR(n) __declspec(align(n))
|
||||
#elif defined(__GNUC__)
|
||||
#define ALIGN_ATTR(n) __attribute__((aligned (n)))
|
||||
#else
|
||||
#define ALIGN_ATTR(n) /* nothing */
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
#define I64(x) x##ui64
|
||||
#else
|
||||
#define I64(x) x##LL
|
||||
#endif
|
||||
|
||||
/* convert a hash flag to index */
|
||||
#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) /* GCC < 3.4 */
|
||||
# define rhash_ctz(x) __builtin_ctz(x)
|
||||
#else
|
||||
unsigned rhash_ctz(unsigned); /* define as function */
|
||||
#endif
|
||||
|
||||
void rhash_swap_copy_str_to_u32(void* to, int index, const void* from, size_t length);
|
||||
void rhash_swap_copy_str_to_u64(void* to, int index, const void* from, size_t length);
|
||||
void rhash_swap_copy_u64_to_str(void* to, const void* from, size_t length);
|
||||
void rhash_u32_mem_swap(unsigned *p, int length_in_u32);
|
||||
|
||||
/* define bswap_32 */
|
||||
#if defined(__GNUC__) && defined(CPU_IA32) && !defined(__i386__)
|
||||
/* for intel x86 CPU */
|
||||
static inline uint32_t bswap_32(uint32_t x) {
|
||||
__asm("bswap\t%0" : "=r" (x) : "0" (x));
|
||||
return x;
|
||||
}
|
||||
#elif defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3)
|
||||
/* for GCC >= 4.3 */
|
||||
# define bswap_32(x) __builtin_bswap32(x)
|
||||
#elif (_MSC_VER > 1300) && (defined(CPU_IA32) || defined(CPU_X64)) /* MS VC */
|
||||
# define bswap_32(x) _byteswap_ulong((unsigned long)x)
|
||||
#elif !defined(__STRICT_ANSI__)
|
||||
/* general bswap_32 definition */
|
||||
static inline uint32_t bswap_32(uint32_t x) {
|
||||
x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0x00FF00FF);
|
||||
return (x >> 16) | (x << 16);
|
||||
}
|
||||
#else
|
||||
#define bswap_32(x) ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
|
||||
(((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
|
||||
#endif /* bswap_32 */
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3)
|
||||
# define bswap_64(x) __builtin_bswap64(x)
|
||||
#elif (_MSC_VER > 1300) && (defined(CPU_IA32) || defined(CPU_X64)) /* MS VC */
|
||||
# define bswap_64(x) _byteswap_uint64((__int64)x)
|
||||
#elif !defined(__STRICT_ANSI__)
|
||||
static inline uint64_t bswap_64(uint64_t x) {
|
||||
union {
|
||||
uint64_t ll;
|
||||
uint32_t l[2];
|
||||
} w, r;
|
||||
w.ll = x;
|
||||
r.l[0] = bswap_32(w.l[1]);
|
||||
r.l[1] = bswap_32(w.l[0]);
|
||||
return r.ll;
|
||||
}
|
||||
#else
|
||||
#error "bswap_64 unsupported"
|
||||
#endif
|
||||
|
||||
#ifdef CPU_BIG_ENDIAN
|
||||
# define be2me_32(x) (x)
|
||||
# define be2me_64(x) (x)
|
||||
# define le2me_32(x) bswap_32(x)
|
||||
# define le2me_64(x) bswap_64(x)
|
||||
|
||||
# define be32_copy(to, index, from, length) memcpy((to) + (index), (from), (length))
|
||||
# define le32_copy(to, index, from, length) rhash_swap_copy_str_to_u32((to), (index), (from), (length))
|
||||
# define be64_copy(to, index, from, length) memcpy((to) + (index), (from), (length))
|
||||
# define le64_copy(to, index, from, length) rhash_swap_copy_str_to_u64((to), (index), (from), (length))
|
||||
# define me64_to_be_str(to, from, length) memcpy((to), (from), (length))
|
||||
# define me64_to_le_str(to, from, length) rhash_swap_copy_u64_to_str((to), (from), (length))
|
||||
|
||||
#else /* CPU_BIG_ENDIAN */
|
||||
# define be2me_32(x) bswap_32(x)
|
||||
# define be2me_64(x) bswap_64(x)
|
||||
# define le2me_32(x) (x)
|
||||
# define le2me_64(x) (x)
|
||||
|
||||
# define be32_copy(to, index, from, length) rhash_swap_copy_str_to_u32((to), (index), (from), (length))
|
||||
# define le32_copy(to, index, from, length) memcpy((to) + (index), (from), (length))
|
||||
# define be64_copy(to, index, from, length) rhash_swap_copy_str_to_u64((to), (index), (from), (length))
|
||||
# define le64_copy(to, index, from, length) memcpy((to) + (index), (from), (length))
|
||||
# define me64_to_be_str(to, from, length) rhash_swap_copy_u64_to_str((to), (from), (length))
|
||||
# define me64_to_le_str(to, from, length) memcpy((to), (from), (length))
|
||||
#endif /* CPU_BIG_ENDIAN */
|
||||
|
||||
/* ROTL/ROTR macros rotate a 32/64-bit word left/right by n bits */
|
||||
#define ROTL32(dword, n) ((dword) << (n) ^ ((dword) >> (32 - (n))))
|
||||
#define ROTR32(dword, n) ((dword) >> (n) ^ ((dword) << (32 - (n))))
|
||||
#define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n))))
|
||||
#define ROTR64(qword, n) ((qword) >> (n) ^ ((qword) << (64 - (n))))
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* BYTE_ORDER_H */
|
188
Utilities/cmlibrhash/librhash/hex.c
Normal file
188
Utilities/cmlibrhash/librhash/hex.c
Normal file
@ -0,0 +1,188 @@
|
||||
/* hex.c - conversion for hexadecimal and base32 strings.
|
||||
*
|
||||
* Copyright: 2008-2012 Aleksey Kravchenko <rhash.admin@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "hex.h"
|
||||
|
||||
/**
|
||||
* Convert a byte to a hexadecimal number. The result, consisting of two
|
||||
* hexadecimal digits is stored into a buffer.
|
||||
*
|
||||
* @param dest the buffer to receive two symbols of hex representation
|
||||
* @param byte the byte to decode
|
||||
* @param upper_case flag to print string in uppercase
|
||||
* @return pointer to the chararcter just after the written number (dest + 2)
|
||||
*/
|
||||
char* rhash_print_hex_byte(char *dest, const unsigned char byte, int upper_case)
|
||||
{
|
||||
const char add = (upper_case ? 'A' - 10 : 'a' - 10);
|
||||
unsigned char c = (byte >> 4) & 15;
|
||||
*dest++ = (c > 9 ? c + add : c + '0');
|
||||
c = byte & 15;
|
||||
*dest++ = (c > 9 ? c + add : c + '0');
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store hexadecimal representation of a binary string to given buffer.
|
||||
*
|
||||
* @param dest the buffer to receive hexadecimal representation
|
||||
* @param src binary string
|
||||
* @param len string length
|
||||
* @param upper_case flag to print string in uppercase
|
||||
*/
|
||||
void rhash_byte_to_hex(char *dest, const unsigned char *src, unsigned len, int upper_case)
|
||||
{
|
||||
while (len-- > 0) {
|
||||
dest = rhash_print_hex_byte(dest, *src++, upper_case);
|
||||
}
|
||||
*dest = '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a binary string to base32.
|
||||
*
|
||||
* @param dest the buffer to store result
|
||||
* @param src binary string
|
||||
* @param len string length
|
||||
* @param upper_case flag to print string in uppercase
|
||||
*/
|
||||
void rhash_byte_to_base32(char* dest, const unsigned char* src, unsigned len, int upper_case)
|
||||
{
|
||||
const char a = (upper_case ? 'A' : 'a');
|
||||
unsigned shift = 0;
|
||||
unsigned char word;
|
||||
const unsigned char* e = src + len;
|
||||
while (src < e) {
|
||||
if (shift > 3) {
|
||||
word = (*src & (0xFF >> shift));
|
||||
shift = (shift + 5) % 8;
|
||||
word <<= shift;
|
||||
if (src + 1 < e)
|
||||
word |= *(src + 1) >> (8 - shift);
|
||||
++src;
|
||||
} else {
|
||||
shift = (shift + 5) % 8;
|
||||
word = ( *src >> ( (8 - shift) & 7 ) ) & 0x1F;
|
||||
if (shift == 0) src++;
|
||||
}
|
||||
*dest++ = ( word < 26 ? word + a : word + '2' - 26 );
|
||||
}
|
||||
*dest = '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a binary string to base64.
|
||||
* Encoded output length is always a multiple of 4 bytes.
|
||||
*
|
||||
* @param dest the buffer to store result
|
||||
* @param src binary string
|
||||
* @param len string length
|
||||
*/
|
||||
void rhash_byte_to_base64(char* dest, const unsigned char* src, unsigned len)
|
||||
{
|
||||
static const char* tail = "0123456789+/";
|
||||
unsigned shift = 0;
|
||||
unsigned char word;
|
||||
const unsigned char* e = src + len;
|
||||
while (src < e) {
|
||||
if (shift > 2) {
|
||||
word = (*src & (0xFF >> shift));
|
||||
shift = (shift + 6) % 8;
|
||||
word <<= shift;
|
||||
if (src + 1 < e)
|
||||
word |= *(src + 1) >> (8 - shift);
|
||||
++src;
|
||||
} else {
|
||||
shift = (shift + 6) % 8;
|
||||
word = ( *src >> ( (8 - shift) & 7 ) ) & 0x3F;
|
||||
if (shift == 0) src++;
|
||||
}
|
||||
*dest++ = ( word < 52 ? (word < 26 ? word + 'A' : word - 26 + 'a') : tail[word - 52]);
|
||||
}
|
||||
if (shift > 0) {
|
||||
*dest++ = '=';
|
||||
if (shift == 4) *dest++ = '=';
|
||||
}
|
||||
*dest = '\0';
|
||||
}
|
||||
|
||||
/* unsafe characters are "<>{}[]%#/|\^~`@:;?=&+ */
|
||||
#define IS_GOOD_URL_CHAR(c) (isalnum((unsigned char)c) || strchr("$-_.!'(),", c))
|
||||
|
||||
/**
|
||||
* URL-encode a string.
|
||||
*
|
||||
* @param dst buffer to receive result or NULL to calculate
|
||||
* the lengths of encoded string
|
||||
* @param filename the file name
|
||||
* @return the length of the result string
|
||||
*/
|
||||
int rhash_urlencode(char *dst, const char *name)
|
||||
{
|
||||
const char *start;
|
||||
if (!dst) {
|
||||
int len;
|
||||
for (len = 0; *name; name++) len += (IS_GOOD_URL_CHAR(*name) ? 1 : 3);
|
||||
return len;
|
||||
}
|
||||
/* encode URL as specified by RFC 1738 */
|
||||
for (start = dst; *name; name++) {
|
||||
if ( IS_GOOD_URL_CHAR(*name) ) {
|
||||
*dst++ = *name;
|
||||
} else {
|
||||
*dst++ = '%';
|
||||
dst = rhash_print_hex_byte(dst, *name, 'A');
|
||||
}
|
||||
}
|
||||
*dst = 0;
|
||||
return (int)(dst - start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print 64-bit number with trailing '\0' to a string buffer.
|
||||
* if dst is NULL, then just return the length of the number.
|
||||
*
|
||||
* @param dst output buffer
|
||||
* @param number the number to print
|
||||
* @return length of the printed number (without trailing '\0')
|
||||
*/
|
||||
int rhash_sprintI64(char *dst, uint64_t number)
|
||||
{
|
||||
/* The biggest number has 20 digits: 2^64 = 18 446 744 073 709 551 616 */
|
||||
char buf[24], *p;
|
||||
size_t length;
|
||||
|
||||
if (dst == NULL) {
|
||||
/* just calculate the length of the number */
|
||||
if (number == 0) return 1;
|
||||
for (length = 0; number != 0; number /= 10) length++;
|
||||
return (int)length;
|
||||
}
|
||||
|
||||
p = buf + 23;
|
||||
*p = '\0'; /* last symbol should be '\0' */
|
||||
if (number == 0) {
|
||||
*(--p) = '0';
|
||||
} else {
|
||||
for (; p >= buf && number != 0; number /= 10) {
|
||||
*(--p) = '0' + (char)(number % 10);
|
||||
}
|
||||
}
|
||||
length = buf + 23 - p;
|
||||
memcpy(dst, p, length + 1);
|
||||
return (int)length;
|
||||
}
|
25
Utilities/cmlibrhash/librhash/hex.h
Normal file
25
Utilities/cmlibrhash/librhash/hex.h
Normal file
@ -0,0 +1,25 @@
|
||||
/* hex.h - conversion for hexadecimal and base32 strings. */
|
||||
#ifndef HEX_H
|
||||
#define HEX_H
|
||||
|
||||
#include "ustd.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void rhash_byte_to_hex(char *dest, const unsigned char *src, unsigned len, int upper_case);
|
||||
void rhash_byte_to_base32(char* dest, const unsigned char* src, unsigned len, int upper_case);
|
||||
void rhash_byte_to_base64(char* dest, const unsigned char* src, unsigned len);
|
||||
char* rhash_print_hex_byte(char *dest, const unsigned char byte, int upper_case);
|
||||
int rhash_urlencode(char *dst, const char *name);
|
||||
int rhash_sprintI64(char *dst, uint64_t number);
|
||||
|
||||
#define BASE32_LENGTH(bytes) (((bytes) * 8 + 4) / 5)
|
||||
#define BASE64_LENGTH(bytes) ((((bytes) + 2) / 3) * 4)
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* HEX_H */
|
236
Utilities/cmlibrhash/librhash/md5.c
Normal file
236
Utilities/cmlibrhash/librhash/md5.c
Normal file
@ -0,0 +1,236 @@
|
||||
/* md5.c - an implementation of the MD5 algorithm, based on RFC 1321.
|
||||
*
|
||||
* Copyright: 2007-2012 Aleksey Kravchenko <rhash.admin@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "byte_order.h"
|
||||
#include "md5.h"
|
||||
|
||||
/**
|
||||
* Initialize context before calculaing hash.
|
||||
*
|
||||
* @param ctx context to initialize
|
||||
*/
|
||||
void rhash_md5_init(md5_ctx *ctx)
|
||||
{
|
||||
ctx->length = 0;
|
||||
|
||||
/* initialize state */
|
||||
ctx->hash[0] = 0x67452301;
|
||||
ctx->hash[1] = 0xefcdab89;
|
||||
ctx->hash[2] = 0x98badcfe;
|
||||
ctx->hash[3] = 0x10325476;
|
||||
}
|
||||
|
||||
/* First, define four auxiliary functions that each take as input
|
||||
* three 32-bit words and returns a 32-bit word.*/
|
||||
|
||||
/* F(x,y,z) = ((y XOR z) AND x) XOR z - is faster then original version */
|
||||
#define MD5_F(x, y, z) ((((y) ^ (z)) & (x)) ^ (z))
|
||||
#define MD5_G(x, y, z) (((x) & (z)) | ((y) & (~z)))
|
||||
#define MD5_H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define MD5_I(x, y, z) ((y) ^ ((x) | (~z)))
|
||||
|
||||
/* transformations for rounds 1, 2, 3, and 4. */
|
||||
#define MD5_ROUND1(a, b, c, d, x, s, ac) { \
|
||||
(a) += MD5_F((b), (c), (d)) + (x) + (ac); \
|
||||
(a) = ROTL32((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define MD5_ROUND2(a, b, c, d, x, s, ac) { \
|
||||
(a) += MD5_G((b), (c), (d)) + (x) + (ac); \
|
||||
(a) = ROTL32((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define MD5_ROUND3(a, b, c, d, x, s, ac) { \
|
||||
(a) += MD5_H((b), (c), (d)) + (x) + (ac); \
|
||||
(a) = ROTL32((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define MD5_ROUND4(a, b, c, d, x, s, ac) { \
|
||||
(a) += MD5_I((b), (c), (d)) + (x) + (ac); \
|
||||
(a) = ROTL32((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
|
||||
/**
|
||||
* The core transformation. Process a 512-bit block.
|
||||
* The function has been taken from RFC 1321 with little changes.
|
||||
*
|
||||
* @param state algorithm state
|
||||
* @param x the message block to process
|
||||
*/
|
||||
static void rhash_md5_process_block(unsigned state[4], const unsigned* x)
|
||||
{
|
||||
register unsigned a, b, c, d;
|
||||
a = state[0];
|
||||
b = state[1];
|
||||
c = state[2];
|
||||
d = state[3];
|
||||
|
||||
MD5_ROUND1(a, b, c, d, x[ 0], 7, 0xd76aa478);
|
||||
MD5_ROUND1(d, a, b, c, x[ 1], 12, 0xe8c7b756);
|
||||
MD5_ROUND1(c, d, a, b, x[ 2], 17, 0x242070db);
|
||||
MD5_ROUND1(b, c, d, a, x[ 3], 22, 0xc1bdceee);
|
||||
MD5_ROUND1(a, b, c, d, x[ 4], 7, 0xf57c0faf);
|
||||
MD5_ROUND1(d, a, b, c, x[ 5], 12, 0x4787c62a);
|
||||
MD5_ROUND1(c, d, a, b, x[ 6], 17, 0xa8304613);
|
||||
MD5_ROUND1(b, c, d, a, x[ 7], 22, 0xfd469501);
|
||||
MD5_ROUND1(a, b, c, d, x[ 8], 7, 0x698098d8);
|
||||
MD5_ROUND1(d, a, b, c, x[ 9], 12, 0x8b44f7af);
|
||||
MD5_ROUND1(c, d, a, b, x[10], 17, 0xffff5bb1);
|
||||
MD5_ROUND1(b, c, d, a, x[11], 22, 0x895cd7be);
|
||||
MD5_ROUND1(a, b, c, d, x[12], 7, 0x6b901122);
|
||||
MD5_ROUND1(d, a, b, c, x[13], 12, 0xfd987193);
|
||||
MD5_ROUND1(c, d, a, b, x[14], 17, 0xa679438e);
|
||||
MD5_ROUND1(b, c, d, a, x[15], 22, 0x49b40821);
|
||||
|
||||
MD5_ROUND2(a, b, c, d, x[ 1], 5, 0xf61e2562);
|
||||
MD5_ROUND2(d, a, b, c, x[ 6], 9, 0xc040b340);
|
||||
MD5_ROUND2(c, d, a, b, x[11], 14, 0x265e5a51);
|
||||
MD5_ROUND2(b, c, d, a, x[ 0], 20, 0xe9b6c7aa);
|
||||
MD5_ROUND2(a, b, c, d, x[ 5], 5, 0xd62f105d);
|
||||
MD5_ROUND2(d, a, b, c, x[10], 9, 0x2441453);
|
||||
MD5_ROUND2(c, d, a, b, x[15], 14, 0xd8a1e681);
|
||||
MD5_ROUND2(b, c, d, a, x[ 4], 20, 0xe7d3fbc8);
|
||||
MD5_ROUND2(a, b, c, d, x[ 9], 5, 0x21e1cde6);
|
||||
MD5_ROUND2(d, a, b, c, x[14], 9, 0xc33707d6);
|
||||
MD5_ROUND2(c, d, a, b, x[ 3], 14, 0xf4d50d87);
|
||||
MD5_ROUND2(b, c, d, a, x[ 8], 20, 0x455a14ed);
|
||||
MD5_ROUND2(a, b, c, d, x[13], 5, 0xa9e3e905);
|
||||
MD5_ROUND2(d, a, b, c, x[ 2], 9, 0xfcefa3f8);
|
||||
MD5_ROUND2(c, d, a, b, x[ 7], 14, 0x676f02d9);
|
||||
MD5_ROUND2(b, c, d, a, x[12], 20, 0x8d2a4c8a);
|
||||
|
||||
MD5_ROUND3(a, b, c, d, x[ 5], 4, 0xfffa3942);
|
||||
MD5_ROUND3(d, a, b, c, x[ 8], 11, 0x8771f681);
|
||||
MD5_ROUND3(c, d, a, b, x[11], 16, 0x6d9d6122);
|
||||
MD5_ROUND3(b, c, d, a, x[14], 23, 0xfde5380c);
|
||||
MD5_ROUND3(a, b, c, d, x[ 1], 4, 0xa4beea44);
|
||||
MD5_ROUND3(d, a, b, c, x[ 4], 11, 0x4bdecfa9);
|
||||
MD5_ROUND3(c, d, a, b, x[ 7], 16, 0xf6bb4b60);
|
||||
MD5_ROUND3(b, c, d, a, x[10], 23, 0xbebfbc70);
|
||||
MD5_ROUND3(a, b, c, d, x[13], 4, 0x289b7ec6);
|
||||
MD5_ROUND3(d, a, b, c, x[ 0], 11, 0xeaa127fa);
|
||||
MD5_ROUND3(c, d, a, b, x[ 3], 16, 0xd4ef3085);
|
||||
MD5_ROUND3(b, c, d, a, x[ 6], 23, 0x4881d05);
|
||||
MD5_ROUND3(a, b, c, d, x[ 9], 4, 0xd9d4d039);
|
||||
MD5_ROUND3(d, a, b, c, x[12], 11, 0xe6db99e5);
|
||||
MD5_ROUND3(c, d, a, b, x[15], 16, 0x1fa27cf8);
|
||||
MD5_ROUND3(b, c, d, a, x[ 2], 23, 0xc4ac5665);
|
||||
|
||||
MD5_ROUND4(a, b, c, d, x[ 0], 6, 0xf4292244);
|
||||
MD5_ROUND4(d, a, b, c, x[ 7], 10, 0x432aff97);
|
||||
MD5_ROUND4(c, d, a, b, x[14], 15, 0xab9423a7);
|
||||
MD5_ROUND4(b, c, d, a, x[ 5], 21, 0xfc93a039);
|
||||
MD5_ROUND4(a, b, c, d, x[12], 6, 0x655b59c3);
|
||||
MD5_ROUND4(d, a, b, c, x[ 3], 10, 0x8f0ccc92);
|
||||
MD5_ROUND4(c, d, a, b, x[10], 15, 0xffeff47d);
|
||||
MD5_ROUND4(b, c, d, a, x[ 1], 21, 0x85845dd1);
|
||||
MD5_ROUND4(a, b, c, d, x[ 8], 6, 0x6fa87e4f);
|
||||
MD5_ROUND4(d, a, b, c, x[15], 10, 0xfe2ce6e0);
|
||||
MD5_ROUND4(c, d, a, b, x[ 6], 15, 0xa3014314);
|
||||
MD5_ROUND4(b, c, d, a, x[13], 21, 0x4e0811a1);
|
||||
MD5_ROUND4(a, b, c, d, x[ 4], 6, 0xf7537e82);
|
||||
MD5_ROUND4(d, a, b, c, x[11], 10, 0xbd3af235);
|
||||
MD5_ROUND4(c, d, a, b, x[ 2], 15, 0x2ad7d2bb);
|
||||
MD5_ROUND4(b, c, d, a, x[ 9], 21, 0xeb86d391);
|
||||
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate message hash.
|
||||
* Can be called repeatedly with chunks of the message to be hashed.
|
||||
*
|
||||
* @param ctx the algorithm context containing current hashing state
|
||||
* @param msg message chunk
|
||||
* @param size length of the message chunk
|
||||
*/
|
||||
void rhash_md5_update(md5_ctx *ctx, const unsigned char* msg, size_t size)
|
||||
{
|
||||
unsigned index = (unsigned)ctx->length & 63;
|
||||
ctx->length += size;
|
||||
|
||||
/* fill partial block */
|
||||
if (index) {
|
||||
unsigned left = md5_block_size - index;
|
||||
le32_copy((char*)ctx->message, index, msg, (size < left ? size : left));
|
||||
if (size < left) return;
|
||||
|
||||
/* process partial block */
|
||||
rhash_md5_process_block(ctx->hash, ctx->message);
|
||||
msg += left;
|
||||
size -= left;
|
||||
}
|
||||
while (size >= md5_block_size) {
|
||||
unsigned* aligned_message_block;
|
||||
if (IS_LITTLE_ENDIAN && IS_ALIGNED_32(msg)) {
|
||||
/* the most common case is processing a 32-bit aligned message
|
||||
on a little-endian CPU without copying it */
|
||||
aligned_message_block = (unsigned*)msg;
|
||||
} else {
|
||||
le32_copy(ctx->message, 0, msg, md5_block_size);
|
||||
aligned_message_block = ctx->message;
|
||||
}
|
||||
|
||||
rhash_md5_process_block(ctx->hash, aligned_message_block);
|
||||
msg += md5_block_size;
|
||||
size -= md5_block_size;
|
||||
}
|
||||
if (size) {
|
||||
/* save leftovers */
|
||||
le32_copy(ctx->message, 0, msg, size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store calculated hash into the given array.
|
||||
*
|
||||
* @param ctx the algorithm context containing current hashing state
|
||||
* @param result calculated hash in binary form
|
||||
*/
|
||||
void rhash_md5_final(md5_ctx *ctx, unsigned char* result)
|
||||
{
|
||||
unsigned index = ((unsigned)ctx->length & 63) >> 2;
|
||||
unsigned shift = ((unsigned)ctx->length & 3) * 8;
|
||||
|
||||
/* pad message and run for last block */
|
||||
|
||||
/* append the byte 0x80 to the message */
|
||||
ctx->message[index] &= ~(0xFFFFFFFF << shift);
|
||||
ctx->message[index++] ^= 0x80 << shift;
|
||||
|
||||
/* if no room left in the message to store 64-bit message length */
|
||||
if (index > 14) {
|
||||
/* then fill the rest with zeros and process it */
|
||||
while (index < 16) {
|
||||
ctx->message[index++] = 0;
|
||||
}
|
||||
rhash_md5_process_block(ctx->hash, ctx->message);
|
||||
index = 0;
|
||||
}
|
||||
while (index < 14) {
|
||||
ctx->message[index++] = 0;
|
||||
}
|
||||
ctx->message[14] = (unsigned)(ctx->length << 3);
|
||||
ctx->message[15] = (unsigned)(ctx->length >> 29);
|
||||
rhash_md5_process_block(ctx->hash, ctx->message);
|
||||
|
||||
if (result) le32_copy(result, 0, &ctx->hash, 16);
|
||||
}
|
31
Utilities/cmlibrhash/librhash/md5.h
Normal file
31
Utilities/cmlibrhash/librhash/md5.h
Normal file
@ -0,0 +1,31 @@
|
||||
/* md5.h */
|
||||
#ifndef MD5_HIDER
|
||||
#define MD5_HIDER
|
||||
#include "ustd.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define md5_block_size 64
|
||||
#define md5_hash_size 16
|
||||
|
||||
/* algorithm context */
|
||||
typedef struct md5_ctx
|
||||
{
|
||||
unsigned message[md5_block_size / 4]; /* 512-bit buffer for leftovers */
|
||||
uint64_t length; /* number of processed bytes */
|
||||
unsigned hash[4]; /* 128-bit algorithm internal hashing state */
|
||||
} md5_ctx;
|
||||
|
||||
/* hash functions */
|
||||
|
||||
void rhash_md5_init(md5_ctx *ctx);
|
||||
void rhash_md5_update(md5_ctx *ctx, const unsigned char* msg, size_t size);
|
||||
void rhash_md5_final(md5_ctx *ctx, unsigned char result[16]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* MD5_HIDER */
|
919
Utilities/cmlibrhash/librhash/rhash.c
Normal file
919
Utilities/cmlibrhash/librhash/rhash.c
Normal file
@ -0,0 +1,919 @@
|
||||
/* rhash.c - implementation of LibRHash library calls
|
||||
*
|
||||
* Copyright: 2008-2012 Aleksey Kravchenko <rhash.admin@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
|
||||
*/
|
||||
|
||||
/* macros for large file support, must be defined before any include file */
|
||||
#define _LARGEFILE64_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <string.h> /* memset() */
|
||||
#include <stdlib.h> /* free() */
|
||||
#include <stddef.h> /* ptrdiff_t */
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* modifier for Windows DLL */
|
||||
#if defined(_WIN32) && defined(RHASH_EXPORTS)
|
||||
# define RHASH_API __declspec(dllexport)
|
||||
#endif
|
||||
|
||||
#include "byte_order.h"
|
||||
#include "algorithms.h"
|
||||
#include "torrent.h"
|
||||
#include "plug_openssl.h"
|
||||
#include "util.h"
|
||||
#include "hex.h"
|
||||
#include "rhash.h" /* RHash library interface */
|
||||
|
||||
#define STATE_ACTIVE 0xb01dbabe
|
||||
#define STATE_STOPED 0xdeadbeef
|
||||
#define STATE_DELETED 0xdecea5ed
|
||||
#define RCTX_AUTO_FINAL 0x1
|
||||
#define RCTX_FINALIZED 0x2
|
||||
#define RCTX_FINALIZED_MASK (RCTX_AUTO_FINAL | RCTX_FINALIZED)
|
||||
#define RHPR_FORMAT (RHPR_RAW | RHPR_HEX | RHPR_BASE32 | RHPR_BASE64)
|
||||
#define RHPR_MODIFIER (RHPR_UPPERCASE | RHPR_REVERSE)
|
||||
|
||||
/**
|
||||
* Initialize static data of rhash algorithms
|
||||
*/
|
||||
void rhash_library_init(void)
|
||||
{
|
||||
rhash_init_algorithms(RHASH_ALL_HASHES);
|
||||
#ifdef USE_OPENSSL
|
||||
rhash_plug_openssl();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of supported hash algorithms.
|
||||
*
|
||||
* @return the number of supported hash functions
|
||||
*/
|
||||
int RHASH_API rhash_count(void)
|
||||
{
|
||||
return rhash_info_size;
|
||||
}
|
||||
|
||||
/* Lo-level rhash library functions */
|
||||
|
||||
/**
|
||||
* Allocate and initialize RHash context for calculating hash(es).
|
||||
* After initializing rhash_update()/rhash_final() functions should be used.
|
||||
* Then the context must be freed by calling rhash_free().
|
||||
*
|
||||
* @param hash_id union of bit flags, containing ids of hashes to calculate.
|
||||
* @return initialized rhash context, NULL on error and errno is set
|
||||
*/
|
||||
RHASH_API rhash rhash_init(unsigned hash_id)
|
||||
{
|
||||
unsigned tail_bit_index; /* index of hash_id trailing bit */
|
||||
unsigned num = 0; /* number of hashes to compute */
|
||||
rhash_context_ext *rctx = NULL; /* allocated rhash context */
|
||||
size_t hash_size_sum = 0; /* size of hash contexts to store in rctx */
|
||||
|
||||
unsigned i, bit_index, id;
|
||||
struct rhash_hash_info* info;
|
||||
size_t aligned_size;
|
||||
char* phash_ctx;
|
||||
|
||||
hash_id &= RHASH_ALL_HASHES;
|
||||
if (hash_id == 0) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tail_bit_index = rhash_ctz(hash_id); /* get trailing bit index */
|
||||
assert(tail_bit_index < RHASH_HASH_COUNT);
|
||||
|
||||
id = 1 << tail_bit_index;
|
||||
|
||||
if (hash_id == id) {
|
||||
/* handle the most common case of only one hash */
|
||||
num = 1;
|
||||
info = &rhash_info_table[tail_bit_index];
|
||||
hash_size_sum = info->context_size;
|
||||
} else {
|
||||
/* another case: hash_id contains several hashes */
|
||||
for (bit_index = tail_bit_index; id <= hash_id; bit_index++, id = id << 1) {
|
||||
assert(id != 0);
|
||||
assert(bit_index < RHASH_HASH_COUNT);
|
||||
info = &rhash_info_table[bit_index];
|
||||
if (hash_id & id) {
|
||||
/* align sizes by 8 bytes */
|
||||
aligned_size = (info->context_size + 7) & ~7;
|
||||
hash_size_sum += aligned_size;
|
||||
num++;
|
||||
}
|
||||
}
|
||||
assert(num > 1);
|
||||
}
|
||||
|
||||
/* align the size of the rhash context common part */
|
||||
aligned_size = (offsetof(rhash_context_ext, vector[num]) + 7) & ~7;
|
||||
assert(aligned_size >= sizeof(rhash_context_ext));
|
||||
|
||||
/* allocate rhash context with enough memory to store contexts of all used hashes */
|
||||
rctx = (rhash_context_ext*)malloc(aligned_size + hash_size_sum);
|
||||
if (rctx == NULL) return NULL;
|
||||
|
||||
/* initialize common fields of the rhash context */
|
||||
memset(rctx, 0, sizeof(rhash_context_ext));
|
||||
rctx->rc.hash_id = hash_id;
|
||||
rctx->flags = RCTX_AUTO_FINAL; /* turn on auto-final by default */
|
||||
rctx->state = STATE_ACTIVE;
|
||||
rctx->hash_vector_size = num;
|
||||
|
||||
/* aligned hash contexts follows rctx->vector[num] in the same memory block */
|
||||
phash_ctx = (char*)rctx + aligned_size;
|
||||
assert(phash_ctx >= (char*)&rctx->vector[num]);
|
||||
|
||||
/* initialize context for every hash in a loop */
|
||||
for (bit_index = tail_bit_index, id = 1 << tail_bit_index, i = 0;
|
||||
id <= hash_id; bit_index++, id = id << 1)
|
||||
{
|
||||
/* check if a hash function with given id shall be included into rctx */
|
||||
if ((hash_id & id) != 0) {
|
||||
info = &rhash_info_table[bit_index];
|
||||
assert(info->context_size > 0);
|
||||
assert(((phash_ctx - (char*)0) & 7) == 0); /* hash context is aligned */
|
||||
assert(info->init != NULL);
|
||||
|
||||
rctx->vector[i].hash_info = info;
|
||||
rctx->vector[i].context = phash_ctx;
|
||||
|
||||
/* BTIH initialization is complex, save pointer for later */
|
||||
if ((id & RHASH_BTIH) != 0) rctx->bt_ctx = phash_ctx;
|
||||
phash_ctx += (info->context_size + 7) & ~7;
|
||||
|
||||
/* initialize the i-th hash context */
|
||||
info->init(rctx->vector[i].context);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return &rctx->rc; /* return allocated and initialized rhash context */
|
||||
}
|
||||
|
||||
/**
|
||||
* Free RHash context memory.
|
||||
*
|
||||
* @param ctx the context to free.
|
||||
*/
|
||||
void rhash_free(rhash ctx)
|
||||
{
|
||||
rhash_context_ext* const ectx = (rhash_context_ext*)ctx;
|
||||
unsigned i;
|
||||
|
||||
if (ctx == 0) return;
|
||||
assert(ectx->hash_vector_size <= RHASH_HASH_COUNT);
|
||||
ectx->state = STATE_DELETED; /* mark memory block as being removed */
|
||||
|
||||
/* clean the hash functions, which require additional clean up */
|
||||
for (i = 0; i < ectx->hash_vector_size; i++) {
|
||||
struct rhash_hash_info* info = ectx->vector[i].hash_info;
|
||||
if (info->cleanup != 0) {
|
||||
info->cleanup(ectx->vector[i].context);
|
||||
}
|
||||
}
|
||||
|
||||
free(ectx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-initialize RHash context to reuse it.
|
||||
* Useful to speed up processing of many small messages.
|
||||
*
|
||||
* @param ctx context to reinitialize
|
||||
*/
|
||||
RHASH_API void rhash_reset(rhash ctx)
|
||||
{
|
||||
rhash_context_ext* const ectx = (rhash_context_ext*)ctx;
|
||||
unsigned i;
|
||||
|
||||
assert(ectx->hash_vector_size > 0);
|
||||
assert(ectx->hash_vector_size <= RHASH_HASH_COUNT);
|
||||
ectx->state = STATE_ACTIVE; /* re-activate the structure */
|
||||
|
||||
/* re-initialize every hash in a loop */
|
||||
for (i = 0; i < ectx->hash_vector_size; i++) {
|
||||
struct rhash_hash_info* info = ectx->vector[i].hash_info;
|
||||
if (info->cleanup != 0) {
|
||||
info->cleanup(ectx->vector[i].context);
|
||||
}
|
||||
|
||||
assert(info->init != NULL);
|
||||
info->init(ectx->vector[i].context);
|
||||
}
|
||||
ectx->flags &= ~RCTX_FINALIZED; /* clear finalized state */
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate hashes of message.
|
||||
* Can be called repeatedly with chunks of the message to be hashed.
|
||||
*
|
||||
* @param ctx the rhash context
|
||||
* @param message message chunk
|
||||
* @param length length of the message chunk
|
||||
* @return 0 on success; On fail return -1 and set errno
|
||||
*/
|
||||
RHASH_API int rhash_update(rhash ctx, const void* message, size_t length)
|
||||
{
|
||||
rhash_context_ext* const ectx = (rhash_context_ext*)ctx;
|
||||
unsigned i;
|
||||
|
||||
assert(ectx->hash_vector_size <= RHASH_HASH_COUNT);
|
||||
if (ectx->state != STATE_ACTIVE) return 0; /* do nothing if canceled */
|
||||
|
||||
ctx->msg_size += length;
|
||||
|
||||
/* call update method for every algorithm */
|
||||
for (i = 0; i < ectx->hash_vector_size; i++) {
|
||||
struct rhash_hash_info* info = ectx->vector[i].hash_info;
|
||||
assert(info->update != 0);
|
||||
info->update(ectx->vector[i].context, message, length);
|
||||
}
|
||||
return 0; /* no error processing at the moment */
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalize hash calculation and optionally store the first hash.
|
||||
*
|
||||
* @param ctx the rhash context
|
||||
* @param first_result optional buffer to store a calculated hash with the lowest available id
|
||||
* @return 0 on success; On fail return -1 and set errno
|
||||
*/
|
||||
RHASH_API int rhash_final(rhash ctx, unsigned char* first_result)
|
||||
{
|
||||
unsigned i = 0;
|
||||
unsigned char buffer[130];
|
||||
unsigned char* out = (first_result ? first_result : buffer);
|
||||
rhash_context_ext* const ectx = (rhash_context_ext*)ctx;
|
||||
assert(ectx->hash_vector_size <= RHASH_HASH_COUNT);
|
||||
|
||||
/* skip final call if already finalized and auto-final is on */
|
||||
if ((ectx->flags & RCTX_FINALIZED_MASK) ==
|
||||
(RCTX_AUTO_FINAL | RCTX_FINALIZED)) return 0;
|
||||
|
||||
/* call final method for every algorithm */
|
||||
for (i = 0; i < ectx->hash_vector_size; i++) {
|
||||
struct rhash_hash_info* info = ectx->vector[i].hash_info;
|
||||
assert(info->final != 0);
|
||||
assert(info->info->digest_size < sizeof(buffer));
|
||||
info->final(ectx->vector[i].context, out);
|
||||
out = buffer;
|
||||
}
|
||||
ectx->flags |= RCTX_FINALIZED;
|
||||
return 0; /* no error processing at the moment */
|
||||
}
|
||||
|
||||
/**
|
||||
* Store digest for given hash_id.
|
||||
* If hash_id is zero, function stores digest for a hash with the lowest id found in the context.
|
||||
* For nonzero hash_id the context must contain it, otherwise function silently does nothing.
|
||||
*
|
||||
* @param ctx rhash context
|
||||
* @param hash_id id of hash to retrieve or zero for hash with the lowest available id
|
||||
* @param result buffer to put the hash into
|
||||
*/
|
||||
static void rhash_put_digest(rhash ctx, unsigned hash_id, unsigned char* result)
|
||||
{
|
||||
rhash_context_ext* const ectx = (rhash_context_ext*)ctx;
|
||||
unsigned i;
|
||||
rhash_vector_item *item;
|
||||
struct rhash_hash_info* info;
|
||||
unsigned char* digest;
|
||||
|
||||
assert(ectx);
|
||||
assert(ectx->hash_vector_size > 0 && ectx->hash_vector_size <= RHASH_HASH_COUNT);
|
||||
|
||||
/* finalize context if not yet finalized and auto-final is on */
|
||||
if ((ectx->flags & RCTX_FINALIZED_MASK) == RCTX_AUTO_FINAL) {
|
||||
rhash_final(ctx, NULL);
|
||||
}
|
||||
|
||||
if (hash_id == 0) {
|
||||
item = &ectx->vector[0]; /* get the first hash */
|
||||
info = item->hash_info;
|
||||
} else {
|
||||
for (i = 0;; i++) {
|
||||
if (i >= ectx->hash_vector_size) {
|
||||
return; /* hash_id not found, do nothing */
|
||||
}
|
||||
item = &ectx->vector[i];
|
||||
info = item->hash_info;
|
||||
if (info->info->hash_id == hash_id) break;
|
||||
}
|
||||
}
|
||||
digest = ((unsigned char*)item->context + info->digest_diff);
|
||||
if (info->info->flags & F_SWAP32) {
|
||||
assert((info->info->digest_size & 3) == 0);
|
||||
/* NB: the next call is correct only for multiple of 4 byte size */
|
||||
rhash_swap_copy_str_to_u32(result, 0, digest, info->info->digest_size);
|
||||
} else if (info->info->flags & F_SWAP64) {
|
||||
rhash_swap_copy_u64_to_str(result, digest, info->info->digest_size);
|
||||
} else {
|
||||
memcpy(result, digest, info->info->digest_size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the callback function to be called from the
|
||||
* rhash_file() and rhash_file_update() functions
|
||||
* on processing every file block. The file block
|
||||
* size is set internally by rhash and now is 8 KiB.
|
||||
*
|
||||
* @param ctx rhash context
|
||||
* @param callback pointer to the callback function
|
||||
* @param callback_data pointer to data passed to the callback
|
||||
*/
|
||||
RHASH_API void rhash_set_callback(rhash ctx, rhash_callback_t callback, void* callback_data)
|
||||
{
|
||||
((rhash_context_ext*)ctx)->callback = callback;
|
||||
((rhash_context_ext*)ctx)->callback_data = callback_data;
|
||||
}
|
||||
|
||||
|
||||
/* hi-level message hashing interface */
|
||||
|
||||
/**
|
||||
* Compute a hash of the given message.
|
||||
*
|
||||
* @param hash_id id of hash sum to compute
|
||||
* @param message the message to process
|
||||
* @param length message length
|
||||
* @param result buffer to receive binary hash string
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
RHASH_API int rhash_msg(unsigned hash_id, const void* message, size_t length, unsigned char* result)
|
||||
{
|
||||
rhash ctx;
|
||||
hash_id &= RHASH_ALL_HASHES;
|
||||
ctx = rhash_init(hash_id);
|
||||
if (ctx == NULL) return -1;
|
||||
rhash_update(ctx, message, length);
|
||||
rhash_final(ctx, result);
|
||||
rhash_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash a file or stream. Multiple hashes can be computed.
|
||||
* First, inintialize ctx parameter with rhash_init() before calling
|
||||
* rhash_file_update(). Then use rhash_final() and rhash_print()
|
||||
* to retrive hash values. Finaly call rhash_free() on ctx
|
||||
* to free allocated memory or call rhash_reset() to reuse ctx.
|
||||
*
|
||||
* @param ctx rhash context
|
||||
* @param fd descriptor of the file to hash
|
||||
* @return 0 on success, -1 on error and errno is set
|
||||
*/
|
||||
RHASH_API int rhash_file_update(rhash ctx, FILE* fd)
|
||||
{
|
||||
rhash_context_ext* const ectx = (rhash_context_ext*)ctx;
|
||||
const size_t block_size = 8192;
|
||||
unsigned char *buffer, *pmem;
|
||||
size_t length = 0, align8;
|
||||
int res = 0;
|
||||
if (ectx->state != STATE_ACTIVE) return 0; /* do nothing if canceled */
|
||||
|
||||
if (ctx == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pmem = (unsigned char*)malloc(block_size + 8);
|
||||
if (!pmem) return -1; /* errno is set to ENOMEM according to UNIX 98 */
|
||||
|
||||
align8 = ((unsigned char*)0 - pmem) & 7;
|
||||
buffer = pmem + align8;
|
||||
|
||||
while (!feof(fd)) {
|
||||
/* stop if canceled */
|
||||
if (ectx->state != STATE_ACTIVE) break;
|
||||
|
||||
length = fread(buffer, 1, block_size, fd);
|
||||
|
||||
if (ferror(fd)) {
|
||||
res = -1; /* note: errno contains error code */
|
||||
break;
|
||||
} else if (length) {
|
||||
rhash_update(ctx, buffer, length);
|
||||
|
||||
if (ectx->callback) {
|
||||
((rhash_callback_t)ectx->callback)(ectx->callback_data, ectx->rc.msg_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute a single hash for given file.
|
||||
*
|
||||
* @param hash_id id of hash sum to compute
|
||||
* @param filepath path to the file to hash
|
||||
* @param result buffer to receive hash value with the lowest requested id
|
||||
* @return 0 on success, -1 on error and errno is set
|
||||
*/
|
||||
RHASH_API int rhash_file(unsigned hash_id, const char* filepath, unsigned char* result)
|
||||
{
|
||||
FILE* fd;
|
||||
rhash ctx;
|
||||
int res;
|
||||
|
||||
hash_id &= RHASH_ALL_HASHES;
|
||||
if (hash_id == 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((fd = fopen(filepath, "rb")) == NULL) return -1;
|
||||
|
||||
if ((ctx = rhash_init(hash_id)) == NULL) return -1;
|
||||
|
||||
res = rhash_file_update(ctx, fd); /* hash the file */
|
||||
fclose(fd);
|
||||
|
||||
rhash_final(ctx, result);
|
||||
rhash_free(ctx);
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef _WIN32 /* windows only function */
|
||||
#include <share.h>
|
||||
|
||||
/**
|
||||
* Compute a single hash for given file.
|
||||
*
|
||||
* @param hash_id id of hash sum to compute
|
||||
* @param filepath path to the file to hash
|
||||
* @param result buffer to receive hash value with the lowest requested id
|
||||
* @return 0 on success, -1 on error, -1 on error and errno is set
|
||||
*/
|
||||
RHASH_API int rhash_wfile(unsigned hash_id, const wchar_t* filepath, unsigned char* result)
|
||||
{
|
||||
FILE* fd;
|
||||
rhash ctx;
|
||||
int res;
|
||||
|
||||
hash_id &= RHASH_ALL_HASHES;
|
||||
if (hash_id == 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((fd = _wfsopen(filepath, L"rb", _SH_DENYWR)) == NULL) return -1;
|
||||
|
||||
if ((ctx = rhash_init(hash_id)) == NULL) return -1;
|
||||
|
||||
res = rhash_file_update(ctx, fd); /* hash the file */
|
||||
fclose(fd);
|
||||
|
||||
rhash_final(ctx, result);
|
||||
rhash_free(ctx);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* RHash information functions */
|
||||
|
||||
/**
|
||||
* Returns information about a hash function by its hash_id.
|
||||
*
|
||||
* @param hash_id the id of hash algorithm
|
||||
* @return pointer to the rhash_info structure containing the information
|
||||
*/
|
||||
const rhash_info* rhash_info_by_id(unsigned hash_id)
|
||||
{
|
||||
hash_id &= RHASH_ALL_HASHES;
|
||||
/* check that only one bit is set */
|
||||
if (hash_id != (hash_id & -(int)hash_id)) return NULL;
|
||||
/* note: alternative condition is (hash_id == 0 || (hash_id & (hash_id - 1)) != 0) */
|
||||
return rhash_info_table[rhash_ctz(hash_id)].info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect default digest output format for given hash algorithm.
|
||||
*
|
||||
* @param hash_id the id of hash algorithm
|
||||
* @return 1 for base32 format, 0 for hexadecimal
|
||||
*/
|
||||
RHASH_API int rhash_is_base32(unsigned hash_id)
|
||||
{
|
||||
/* fast method is just to test a bit-mask */
|
||||
return ((hash_id & (RHASH_TTH | RHASH_AICH)) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns size of binary digest for given hash algorithm.
|
||||
*
|
||||
* @param hash_id the id of hash algorithm
|
||||
* @return digest size in bytes
|
||||
*/
|
||||
RHASH_API int rhash_get_digest_size(unsigned hash_id)
|
||||
{
|
||||
hash_id &= RHASH_ALL_HASHES;
|
||||
if (hash_id == 0 || (hash_id & (hash_id - 1)) != 0) return -1;
|
||||
return (int)rhash_info_table[rhash_ctz(hash_id)].info->digest_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns length of digest hash string in default output format.
|
||||
*
|
||||
* @param hash_id the id of hash algorithm
|
||||
* @return the length of hash string
|
||||
*/
|
||||
RHASH_API int rhash_get_hash_length(unsigned hash_id)
|
||||
{
|
||||
const rhash_info* info = rhash_info_by_id(hash_id);
|
||||
return (int)(info ? (info->flags & F_BS32 ?
|
||||
BASE32_LENGTH(info->digest_size) : info->digest_size * 2) : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a name of given hash algorithm.
|
||||
*
|
||||
* @param hash_id the id of hash algorithm
|
||||
* @return algorithm name
|
||||
*/
|
||||
RHASH_API const char* rhash_get_name(unsigned hash_id)
|
||||
{
|
||||
const rhash_info* info = rhash_info_by_id(hash_id);
|
||||
return (info ? info->name : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a name part of magnet urn of the given hash algorithm.
|
||||
* Such magnet_name is used to generate a magnet link of the form
|
||||
* urn:<magnet_name>=<hash_value>.
|
||||
*
|
||||
* @param hash_id the id of hash algorithm
|
||||
* @return name
|
||||
*/
|
||||
RHASH_API const char* rhash_get_magnet_name(unsigned hash_id)
|
||||
{
|
||||
const rhash_info* info = rhash_info_by_id(hash_id);
|
||||
return (info ? info->magnet_name : 0);
|
||||
}
|
||||
|
||||
static size_t rhash_get_magnet_url_size(const char* filepath,
|
||||
rhash context, unsigned hash_mask, int flags)
|
||||
{
|
||||
size_t size = 0; /* count terminating '\0' */
|
||||
unsigned bit, hash = context->hash_id & hash_mask;
|
||||
|
||||
/* RHPR_NO_MAGNET, RHPR_FILESIZE */
|
||||
if ((flags & RHPR_NO_MAGNET) == 0) {
|
||||
size += 8;
|
||||
}
|
||||
|
||||
if ((flags & RHPR_FILESIZE) != 0) {
|
||||
uint64_t num = context->msg_size;
|
||||
|
||||
size += 4;
|
||||
if (num == 0) size++;
|
||||
else {
|
||||
for (; num; num /= 10, size++);
|
||||
}
|
||||
}
|
||||
|
||||
if (filepath) {
|
||||
size += 4 + rhash_urlencode(NULL, filepath);
|
||||
}
|
||||
|
||||
/* loop through hash values */
|
||||
for (bit = hash & -(int)hash; bit <= hash; bit <<= 1) {
|
||||
const char* name;
|
||||
if ((bit & hash) == 0) continue;
|
||||
if ((name = rhash_get_magnet_name(bit)) == 0) continue;
|
||||
|
||||
size += (7 + 2) + strlen(name);
|
||||
size += rhash_print(NULL, context, bit,
|
||||
(bit & (RHASH_SHA1 | RHASH_BTIH) ? RHPR_BASE32 : 0));
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print magnet link with given filepath and calculated hash sums into the
|
||||
* output buffer. The hash_mask can limit which hash values will be printed.
|
||||
* The function returns the size of the required buffer.
|
||||
* If output is NULL the .
|
||||
*
|
||||
* @param output a string buffer to receive the magnet link or NULL
|
||||
* @param filepath the file path to be printed or NULL
|
||||
* @param context algorithms state
|
||||
* @param hash_mask bit mask of the hash sums to add to the link
|
||||
* @param flags can be combination of bits RHPR_UPPERCASE, RHPR_NO_MAGNET,
|
||||
* RHPR_FILESIZE
|
||||
* @return number of written characters, including terminating '\0' on success, 0 on fail
|
||||
*/
|
||||
RHASH_API size_t rhash_print_magnet(char* output, const char* filepath,
|
||||
rhash context, unsigned hash_mask, int flags)
|
||||
{
|
||||
int i;
|
||||
const char* begin = output;
|
||||
|
||||
if (output == NULL) return rhash_get_magnet_url_size(
|
||||
filepath, context, hash_mask, flags);
|
||||
|
||||
/* RHPR_NO_MAGNET, RHPR_FILESIZE */
|
||||
if ((flags & RHPR_NO_MAGNET) == 0) {
|
||||
strcpy(output, "magnet:?");
|
||||
output += 8;
|
||||
}
|
||||
|
||||
if ((flags & RHPR_FILESIZE) != 0) {
|
||||
strcpy(output, "xl=");
|
||||
output += 3;
|
||||
output += rhash_sprintI64(output, context->msg_size);
|
||||
*(output++) = '&';
|
||||
}
|
||||
|
||||
if (filepath) {
|
||||
strcpy(output, "dn=");
|
||||
output += 3;
|
||||
output += rhash_urlencode(output, filepath);
|
||||
*(output++) = '&';
|
||||
}
|
||||
flags &= RHPR_UPPERCASE;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
unsigned bit;
|
||||
unsigned hash = context->hash_id & hash_mask;
|
||||
hash = (i == 0 ? hash & (RHASH_ED2K | RHASH_AICH)
|
||||
: hash & ~(RHASH_ED2K | RHASH_AICH));
|
||||
if (!hash) continue;
|
||||
|
||||
/* loop through hash values */
|
||||
for (bit = hash & -(int)hash; bit <= hash; bit <<= 1) {
|
||||
const char* name;
|
||||
if ((bit & hash) == 0) continue;
|
||||
if (!(name = rhash_get_magnet_name(bit))) continue;
|
||||
|
||||
strcpy(output, "xt=urn:");
|
||||
output += 7;
|
||||
strcpy(output, name);
|
||||
output += strlen(name);
|
||||
*(output++) = ':';
|
||||
output += rhash_print(output, context, bit,
|
||||
(bit & (RHASH_SHA1 | RHASH_BTIH) ? flags | RHPR_BASE32 : flags));
|
||||
*(output++) = '&';
|
||||
}
|
||||
}
|
||||
output[-1] = '\0'; /* terminate the line */
|
||||
|
||||
return (output - begin);
|
||||
}
|
||||
|
||||
/* hash sum output */
|
||||
|
||||
/**
|
||||
* Print a text presentation of a given hash sum to the specified buffer,
|
||||
*
|
||||
* @param output a buffer to print the hash to
|
||||
* @param bytes a hash sum to print
|
||||
* @param size a size of hash sum in bytes
|
||||
* @param flags a bit-mask controlling how to format the hash sum,
|
||||
* can be a mix of the flags: RHPR_RAW, RHPR_HEX, RHPR_BASE32,
|
||||
* RHPR_BASE64, RHPR_UPPERCASE, RHPR_REVERSE
|
||||
* @return the number of written characters
|
||||
*/
|
||||
size_t rhash_print_bytes(char* output, const unsigned char* bytes,
|
||||
size_t size, int flags)
|
||||
{
|
||||
size_t str_len;
|
||||
int upper_case = (flags & RHPR_UPPERCASE);
|
||||
int format = (flags & ~RHPR_MODIFIER);
|
||||
|
||||
switch (format) {
|
||||
case RHPR_HEX:
|
||||
str_len = size * 2;
|
||||
rhash_byte_to_hex(output, bytes, (unsigned)size, upper_case);
|
||||
break;
|
||||
case RHPR_BASE32:
|
||||
str_len = BASE32_LENGTH(size);
|
||||
rhash_byte_to_base32(output, bytes, (unsigned)size, upper_case);
|
||||
break;
|
||||
case RHPR_BASE64:
|
||||
str_len = BASE64_LENGTH(size);
|
||||
rhash_byte_to_base64(output, bytes, (unsigned)size);
|
||||
break;
|
||||
default:
|
||||
str_len = size;
|
||||
memcpy(output, bytes, size);
|
||||
break;
|
||||
}
|
||||
return str_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print text presentation of a hash sum with given hash_id to the specified
|
||||
* output buffer. If the hash_id is zero, then print the hash sum with
|
||||
* the lowest id stored in the hash context.
|
||||
* The function call fails if the context doesn't include a hash with the
|
||||
* given hash_id.
|
||||
*
|
||||
* @param output a buffer to print the hash to
|
||||
* @param context algorithms state
|
||||
* @param hash_id id of the hash sum to print or 0 to print the first hash
|
||||
* saved in the context.
|
||||
* @param flags a bitmask controlling how to print the hash. Can contain flags
|
||||
* RHPR_UPPERCASE, RHPR_HEX, RHPR_BASE32, RHPR_BASE64, etc.
|
||||
* @return the number of written characters on success or 0 on fail
|
||||
*/
|
||||
size_t RHASH_API rhash_print(char* output, rhash context, unsigned hash_id, int flags)
|
||||
{
|
||||
const rhash_info* info;
|
||||
unsigned char digest[80];
|
||||
size_t digest_size;
|
||||
|
||||
info = (hash_id != 0 ? rhash_info_by_id(hash_id) :
|
||||
((rhash_context_ext*)context)->vector[0].hash_info->info);
|
||||
|
||||
if (info == NULL) return 0;
|
||||
digest_size = info->digest_size;
|
||||
assert(digest_size <= 64);
|
||||
|
||||
flags &= (RHPR_FORMAT | RHPR_MODIFIER);
|
||||
if ((flags & RHPR_FORMAT) == 0) {
|
||||
/* use default format if not specified by flags */
|
||||
flags |= (info->flags & RHASH_INFO_BASE32 ? RHPR_BASE32 : RHPR_HEX);
|
||||
}
|
||||
|
||||
if (output == NULL) {
|
||||
switch (flags & RHPR_FORMAT) {
|
||||
case RHPR_HEX:
|
||||
return (digest_size * 2);
|
||||
case RHPR_BASE32:
|
||||
return BASE32_LENGTH(digest_size);
|
||||
case RHPR_BASE64:
|
||||
return BASE64_LENGTH(digest_size);
|
||||
default:
|
||||
return digest_size;
|
||||
}
|
||||
}
|
||||
|
||||
/* note: use info->hash_id, cause hash_id can be 0 */
|
||||
rhash_put_digest(context, info->hash_id, digest);
|
||||
|
||||
if ((flags & ~RHPR_UPPERCASE) == (RHPR_REVERSE | RHPR_HEX)) {
|
||||
/* reverse the digest */
|
||||
unsigned char *p = digest, *r = digest + digest_size - 1;
|
||||
char tmp;
|
||||
for (; p < r; p++, r--) {
|
||||
tmp = *p;
|
||||
*p = *r;
|
||||
*r = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return rhash_print_bytes(output, digest, digest_size, flags);
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && defined(RHASH_EXPORTS)
|
||||
#include <windows.h>
|
||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID reserved);
|
||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID reserved)
|
||||
{
|
||||
(void)hModule;
|
||||
(void)reserved;
|
||||
switch (reason) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
rhash_library_init();
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
/*rhash_library_free();*/
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Process a BitTorrent-related rhash message.
|
||||
*
|
||||
* @param msg_id message identifier
|
||||
* @param bt BitTorrent context
|
||||
* @param ldata data depending on message
|
||||
* @param rdata data depending on message
|
||||
* @return message-specific data
|
||||
*/
|
||||
static rhash_uptr_t process_bt_msg(unsigned msg_id, torrent_ctx* bt, rhash_uptr_t ldata, rhash_uptr_t rdata)
|
||||
{
|
||||
if (bt == NULL) return RHASH_ERROR;
|
||||
|
||||
switch (msg_id) {
|
||||
case RMSG_BT_ADD_FILE:
|
||||
bt_add_file(bt, (const char*)ldata, *(unsigned long long*)rdata);
|
||||
break;
|
||||
case RMSG_BT_SET_OPTIONS:
|
||||
bt_set_options(bt, (unsigned)ldata);
|
||||
break;
|
||||
case RMSG_BT_SET_ANNOUNCE:
|
||||
bt_add_announce(bt, (const char*)ldata);
|
||||
break;
|
||||
case RMSG_BT_SET_PIECE_LENGTH:
|
||||
bt_set_piece_length(bt, (size_t)ldata);
|
||||
break;
|
||||
case RMSG_BT_SET_BATCH_SIZE:
|
||||
bt_set_piece_length(bt,
|
||||
bt_default_piece_length(*(unsigned long long*)ldata));
|
||||
break;
|
||||
case RMSG_BT_SET_PROGRAM_NAME:
|
||||
bt_set_program_name(bt, (const char*)ldata);
|
||||
break;
|
||||
case RMSG_BT_GET_TEXT:
|
||||
return (rhash_uptr_t)bt_get_text(bt, (char**)ldata);
|
||||
default:
|
||||
return RHASH_ERROR; /* unknown message */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PVOID2UPTR(p) ((rhash_uptr_t)((char*)p - 0))
|
||||
|
||||
/**
|
||||
* Process a rhash message.
|
||||
*
|
||||
* @param msg_id message identifier
|
||||
* @param dst message destination (can be NULL for generic messages)
|
||||
* @param ldata data depending on message
|
||||
* @param rdata data depending on message
|
||||
* @return message-specific data
|
||||
*/
|
||||
RHASH_API rhash_uptr_t rhash_transmit(unsigned msg_id, void* dst, rhash_uptr_t ldata, rhash_uptr_t rdata)
|
||||
{
|
||||
/* for messages working with rhash context */
|
||||
rhash_context_ext* const ctx = (rhash_context_ext*)dst;
|
||||
|
||||
switch (msg_id) {
|
||||
case RMSG_GET_CONTEXT:
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < ctx->hash_vector_size; i++) {
|
||||
struct rhash_hash_info* info = ctx->vector[i].hash_info;
|
||||
if (info->info->hash_id == (unsigned)ldata)
|
||||
return PVOID2UPTR(ctx->vector[i].context);
|
||||
}
|
||||
return (rhash_uptr_t)0;
|
||||
}
|
||||
|
||||
case RMSG_CANCEL:
|
||||
/* mark rhash context as canceled, in a multithreaded program */
|
||||
atomic_compare_and_swap(&ctx->state, STATE_ACTIVE, STATE_STOPED);
|
||||
return 0;
|
||||
|
||||
case RMSG_IS_CANCELED:
|
||||
return (ctx->state == STATE_STOPED);
|
||||
|
||||
case RMSG_GET_FINALIZED:
|
||||
return ((ctx->flags & RCTX_FINALIZED) != 0);
|
||||
case RMSG_SET_AUTOFINAL:
|
||||
ctx->flags &= ~RCTX_AUTO_FINAL;
|
||||
if (ldata) ctx->flags |= RCTX_AUTO_FINAL;
|
||||
break;
|
||||
|
||||
/* OpenSSL related messages */
|
||||
#ifdef USE_OPENSSL
|
||||
case RMSG_SET_OPENSSL_MASK:
|
||||
rhash_openssl_hash_mask = (unsigned)ldata;
|
||||
break;
|
||||
case RMSG_GET_OPENSSL_MASK:
|
||||
return rhash_openssl_hash_mask;
|
||||
#endif
|
||||
|
||||
/* BitTorrent related messages */
|
||||
case RMSG_BT_ADD_FILE:
|
||||
case RMSG_BT_SET_OPTIONS:
|
||||
case RMSG_BT_SET_ANNOUNCE:
|
||||
case RMSG_BT_SET_PIECE_LENGTH:
|
||||
case RMSG_BT_SET_PROGRAM_NAME:
|
||||
case RMSG_BT_GET_TEXT:
|
||||
case RMSG_BT_SET_BATCH_SIZE:
|
||||
return process_bt_msg(msg_id, (torrent_ctx*)(((rhash_context_ext*)dst)->bt_ctx), ldata, rdata);
|
||||
|
||||
default:
|
||||
return RHASH_ERROR; /* unknown message */
|
||||
}
|
||||
return 0;
|
||||
}
|
273
Utilities/cmlibrhash/librhash/rhash.h
Normal file
273
Utilities/cmlibrhash/librhash/rhash.h
Normal file
@ -0,0 +1,273 @@
|
||||
/** @file rhash.h LibRHash interface */
|
||||
#ifndef RHASH_H
|
||||
#define RHASH_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef RHASH_API
|
||||
/* modifier for LibRHash functions */
|
||||
# define RHASH_API
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Identifiers of supported hash functions.
|
||||
* The rhash_init() function allows mixing several ids using
|
||||
* binary OR, to calculate several hash functions for one message.
|
||||
*/
|
||||
enum rhash_ids
|
||||
{
|
||||
RHASH_CRC32 = 0x01,
|
||||
RHASH_MD4 = 0x02,
|
||||
RHASH_MD5 = 0x04,
|
||||
RHASH_SHA1 = 0x08,
|
||||
RHASH_TIGER = 0x10,
|
||||
RHASH_TTH = 0x20,
|
||||
RHASH_BTIH = 0x40,
|
||||
RHASH_ED2K = 0x80,
|
||||
RHASH_AICH = 0x100,
|
||||
RHASH_WHIRLPOOL = 0x200,
|
||||
RHASH_RIPEMD160 = 0x400,
|
||||
RHASH_GOST = 0x800,
|
||||
RHASH_GOST_CRYPTOPRO = 0x1000,
|
||||
RHASH_HAS160 = 0x2000,
|
||||
RHASH_SNEFRU128 = 0x4000,
|
||||
RHASH_SNEFRU256 = 0x8000,
|
||||
RHASH_SHA224 = 0x10000,
|
||||
RHASH_SHA256 = 0x20000,
|
||||
RHASH_SHA384 = 0x40000,
|
||||
RHASH_SHA512 = 0x80000,
|
||||
RHASH_EDONR256 = 0x0100000,
|
||||
RHASH_EDONR512 = 0x0200000,
|
||||
RHASH_SHA3_224 = 0x0400000,
|
||||
RHASH_SHA3_256 = 0x0800000,
|
||||
RHASH_SHA3_384 = 0x1000000,
|
||||
RHASH_SHA3_512 = 0x2000000,
|
||||
|
||||
/** The bit-mask containing all supported hashe functions */
|
||||
RHASH_ALL_HASHES = RHASH_CRC32 | RHASH_MD4 | RHASH_MD5 | RHASH_ED2K | RHASH_SHA1 |
|
||||
RHASH_TIGER | RHASH_TTH | RHASH_GOST | RHASH_GOST_CRYPTOPRO |
|
||||
RHASH_BTIH | RHASH_AICH | RHASH_WHIRLPOOL | RHASH_RIPEMD160 |
|
||||
RHASH_HAS160 | RHASH_SNEFRU128 | RHASH_SNEFRU256 |
|
||||
RHASH_SHA224 | RHASH_SHA256 | RHASH_SHA384 | RHASH_SHA512 |
|
||||
RHASH_SHA3_224 | RHASH_SHA3_256 | RHASH_SHA3_384 | RHASH_SHA3_512 |
|
||||
RHASH_EDONR256 | RHASH_EDONR512,
|
||||
|
||||
/** The number of supported hash functions */
|
||||
RHASH_HASH_COUNT = 26
|
||||
};
|
||||
|
||||
/**
|
||||
* The rhash context structure contains contexts for several hash functions
|
||||
*/
|
||||
typedef struct rhash_context
|
||||
{
|
||||
/** The size of the hashed message */
|
||||
unsigned long long msg_size;
|
||||
|
||||
/**
|
||||
* The bit-mask containing identifiers of the hashes being calculated
|
||||
*/
|
||||
unsigned hash_id;
|
||||
} rhash_context;
|
||||
|
||||
#ifndef LIBRHASH_RHASH_CTX_DEFINED
|
||||
#define LIBRHASH_RHASH_CTX_DEFINED
|
||||
/**
|
||||
* Hashing context.
|
||||
*/
|
||||
typedef struct rhash_context* rhash;
|
||||
#endif /* LIBRHASH_RHASH_CTX_DEFINED */
|
||||
|
||||
/** type of a callback to be called periodically while hashing a file */
|
||||
typedef void (*rhash_callback_t)(void* data, unsigned long long offset);
|
||||
|
||||
RHASH_API void rhash_library_init(void); /* initialize static data */
|
||||
|
||||
/* hi-level hashing functions */
|
||||
RHASH_API int rhash_msg(unsigned hash_id, const void* message, size_t length, unsigned char* result);
|
||||
RHASH_API int rhash_file(unsigned hash_id, const char* filepath, unsigned char* result);
|
||||
RHASH_API int rhash_file_update(rhash ctx, FILE* fd);
|
||||
|
||||
#ifdef _WIN32 /* windows only function */
|
||||
RHASH_API int rhash_wfile(unsigned hash_id, const wchar_t* filepath, unsigned char* result);
|
||||
#endif
|
||||
|
||||
/* lo-level interface */
|
||||
RHASH_API rhash rhash_init(unsigned hash_id);
|
||||
/*RHASH_API rhash rhash_init_by_ids(unsigned hash_ids[], unsigned count);*/
|
||||
RHASH_API int rhash_update(rhash ctx, const void* message, size_t length);
|
||||
RHASH_API int rhash_final(rhash ctx, unsigned char* first_result);
|
||||
RHASH_API void rhash_reset(rhash ctx); /* reinitialize the context */
|
||||
RHASH_API void rhash_free(rhash ctx);
|
||||
|
||||
/* additional lo-level functions */
|
||||
RHASH_API void rhash_set_callback(rhash ctx, rhash_callback_t callback, void* callback_data);
|
||||
|
||||
/** bit-flag: default hash output format is base32 */
|
||||
#define RHASH_INFO_BASE32 1
|
||||
|
||||
/**
|
||||
* Information about a hash function.
|
||||
*/
|
||||
typedef struct rhash_info
|
||||
{
|
||||
/** hash function indentifier */
|
||||
unsigned hash_id;
|
||||
/** flags bit-mask, including RHASH_INFO_BASE32 bit */
|
||||
unsigned flags;
|
||||
/** size of binary message digest in bytes */
|
||||
size_t digest_size;
|
||||
const char* name;
|
||||
const char* magnet_name;
|
||||
} rhash_info;
|
||||
|
||||
/* information functions */
|
||||
RHASH_API int rhash_count(void); /* number of supported hashes */
|
||||
RHASH_API int rhash_get_digest_size(unsigned hash_id); /* size of binary message digest */
|
||||
RHASH_API int rhash_get_hash_length(unsigned hash_id); /* length of formated hash string */
|
||||
RHASH_API int rhash_is_base32(unsigned hash_id); /* default digest output format */
|
||||
RHASH_API const char* rhash_get_name(unsigned hash_id); /* get hash function name */
|
||||
RHASH_API const char* rhash_get_magnet_name(unsigned hash_id); /* get name part of magnet urn */
|
||||
|
||||
/* note, that rhash_info_by_id() is not exported to a shared library or DLL */
|
||||
const rhash_info* rhash_info_by_id(unsigned hash_id); /* get hash sum info by hash id */
|
||||
|
||||
/**
|
||||
* Flags for printing a hash sum
|
||||
*/
|
||||
enum rhash_print_sum_flags
|
||||
{
|
||||
/** print in a default format */
|
||||
RHPR_DEFAULT = 0x0,
|
||||
/** output as binary message digest */
|
||||
RHPR_RAW = 0x1,
|
||||
/** print as a hexadecimal string */
|
||||
RHPR_HEX = 0x2,
|
||||
/** print as a base32-encoded string */
|
||||
RHPR_BASE32 = 0x3,
|
||||
/** print as a base64-encoded string */
|
||||
RHPR_BASE64 = 0x4,
|
||||
|
||||
/**
|
||||
* Print as an uppercase string. Can be used
|
||||
* for base32 or hexadecimal format only.
|
||||
*/
|
||||
RHPR_UPPERCASE = 0x8,
|
||||
|
||||
/**
|
||||
* Reverse hash bytes. Can be used for GOST hash.
|
||||
*/
|
||||
RHPR_REVERSE = 0x10,
|
||||
|
||||
/** don't print 'magnet:?' prefix in rhash_print_magnet */
|
||||
RHPR_NO_MAGNET = 0x20,
|
||||
/** print file size in rhash_print_magnet */
|
||||
RHPR_FILESIZE = 0x40,
|
||||
};
|
||||
|
||||
/* output hash into the given buffer */
|
||||
RHASH_API size_t rhash_print_bytes(char* output,
|
||||
const unsigned char* bytes, size_t size, int flags);
|
||||
|
||||
RHASH_API size_t rhash_print(char* output, rhash ctx, unsigned hash_id,
|
||||
int flags);
|
||||
|
||||
/* output magnet URL into the given buffer */
|
||||
RHASH_API size_t rhash_print_magnet(char* output, const char* filepath,
|
||||
rhash context, unsigned hash_mask, int flags);
|
||||
|
||||
/* macros for message API */
|
||||
|
||||
/** The type of an unsigned integer large enough to hold a pointer */
|
||||
#if defined(UINTPTR_MAX)
|
||||
typedef uintptr_t rhash_uptr_t;
|
||||
#elif defined(_LP64) || defined(__LP64__) || defined(__x86_64) || \
|
||||
defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
|
||||
typedef unsigned long long rhash_uptr_t;
|
||||
#else
|
||||
typedef unsigned long rhash_uptr_t;
|
||||
#endif
|
||||
|
||||
/** The value returned by rhash_transmit on error */
|
||||
#define RHASH_ERROR ((rhash_uptr_t)-1)
|
||||
/** Convert a pointer to rhash_uptr_t */
|
||||
#define RHASH_STR2UPTR(str) ((rhash_uptr_t)(char*)(str))
|
||||
/** Convert a rhash_uptr_t to a void* pointer */
|
||||
#define RHASH_UPTR2PVOID(u) ((void*)((char*)0 + (u)))
|
||||
|
||||
/* rhash API to set/get data via messages */
|
||||
RHASH_API rhash_uptr_t rhash_transmit(
|
||||
unsigned msg_id, void* dst, rhash_uptr_t ldata, rhash_uptr_t rdata);
|
||||
|
||||
/* rhash message constants */
|
||||
|
||||
#define RMSG_GET_CONTEXT 1
|
||||
#define RMSG_CANCEL 2
|
||||
#define RMSG_IS_CANCELED 3
|
||||
#define RMSG_GET_FINALIZED 4
|
||||
#define RMSG_SET_AUTOFINAL 5
|
||||
#define RMSG_SET_OPENSSL_MASK 10
|
||||
#define RMSG_GET_OPENSSL_MASK 11
|
||||
|
||||
#define RMSG_BT_ADD_FILE 32
|
||||
#define RMSG_BT_SET_OPTIONS 33
|
||||
#define RMSG_BT_SET_ANNOUNCE 34
|
||||
#define RMSG_BT_SET_PIECE_LENGTH 35
|
||||
#define RMSG_BT_SET_PROGRAM_NAME 36
|
||||
#define RMSG_BT_GET_TEXT 37
|
||||
#define RMSG_BT_SET_BATCH_SIZE 38
|
||||
|
||||
/* possible BitTorrent options for the RMSG_BT_SET_OPTIONS message */
|
||||
#define RHASH_BT_OPT_PRIVATE 1
|
||||
#define RHASH_BT_OPT_INFOHASH_ONLY 2
|
||||
|
||||
/* helper macros */
|
||||
|
||||
/** Get a pointer to context of the specified hash function */
|
||||
#define rhash_get_context_ptr(ctx, hash_id) RHASH_UPTR2PVOID(rhash_transmit(RMSG_GET_CONTEXT, ctx, hash_id, 0))
|
||||
/** Cancel hash calculation of a file */
|
||||
#define rhash_cancel(ctx) rhash_transmit(RMSG_CANCEL, ctx, 0, 0)
|
||||
/** Return non-zero if hash calculation was canceled, zero otherwise */
|
||||
#define rhash_is_canceled(ctx) rhash_transmit(RMSG_IS_CANCELED, ctx, 0, 0)
|
||||
/** Return non-zero if rhash_final was called for rhash_context */
|
||||
#define rhash_get_finalized(ctx) rhash_transmit(RMSG_GET_FINALIZED, ctx, 0, 0)
|
||||
|
||||
/**
|
||||
* Turn on/off the auto-final flag for the given rhash_context. By default
|
||||
* auto-final is on, which means rhash_final is called automatically, if
|
||||
* needed when a hash value is retrived by rhash_print call.
|
||||
*/
|
||||
#define rhash_set_autofinal(ctx, on) rhash_transmit(RMSG_SET_AUTOFINAL, ctx, on, 0)
|
||||
|
||||
/**
|
||||
* Set the bit-mask of hash algorithms to be calculated by OpenSSL library.
|
||||
* The call rhash_set_openssl_mask(0) made before rhash_library_init(),
|
||||
* turns off loading of the OpenSSL dynamic library.
|
||||
* This call works if the LibRHash was compiled with OpenSSL support.
|
||||
*/
|
||||
#define rhash_set_openssl_mask(mask) rhash_transmit(RMSG_SET_OPENSSL_MASK, NULL, mask, 0)
|
||||
|
||||
/**
|
||||
* Return current bit-mask of hash algorithms selected to be calculated
|
||||
* by OpenSSL library.
|
||||
*/
|
||||
#define rhash_get_openssl_mask() rhash_transmit(RMSG_GET_OPENSSL_MASK, NULL, 0, 0)
|
||||
|
||||
/** The bit mask of hash algorithms implemented by OpenSSL */
|
||||
#if defined(USE_OPENSSL) || defined(OPENSSL_RUNTIME)
|
||||
# define RHASH_OPENSSL_SUPPORTED_HASHES (RHASH_MD4 | RHASH_MD5 | \
|
||||
RHASH_SHA1 | RHASH_SHA224 | RHASH_SHA256 | RHASH_SHA384 | \
|
||||
RHASH_SHA512 | RHASH_RIPEMD160 | RHASH_WHIRLPOOL)
|
||||
#else
|
||||
# define RHASH_OPENSSL_SUPPORTED_HASHES 0
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* RHASH_H */
|
196
Utilities/cmlibrhash/librhash/sha1.c
Normal file
196
Utilities/cmlibrhash/librhash/sha1.c
Normal file
@ -0,0 +1,196 @@
|
||||
/* sha1.c - an implementation of Secure Hash Algorithm 1 (SHA1)
|
||||
* based on RFC 3174.
|
||||
*
|
||||
* Copyright: 2008-2012 Aleksey Kravchenko <rhash.admin@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "byte_order.h"
|
||||
#include "sha1.h"
|
||||
|
||||
/**
|
||||
* Initialize context before calculaing hash.
|
||||
*
|
||||
* @param ctx context to initialize
|
||||
*/
|
||||
void rhash_sha1_init(sha1_ctx *ctx)
|
||||
{
|
||||
ctx->length = 0;
|
||||
|
||||
/* initialize algorithm state */
|
||||
ctx->hash[0] = 0x67452301;
|
||||
ctx->hash[1] = 0xefcdab89;
|
||||
ctx->hash[2] = 0x98badcfe;
|
||||
ctx->hash[3] = 0x10325476;
|
||||
ctx->hash[4] = 0xc3d2e1f0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The core transformation. Process a 512-bit block.
|
||||
* The function has been taken from RFC 3174 with little changes.
|
||||
*
|
||||
* @param hash algorithm state
|
||||
* @param block the message block to process
|
||||
*/
|
||||
static void rhash_sha1_process_block(unsigned* hash, const unsigned* block)
|
||||
{
|
||||
int t; /* Loop counter */
|
||||
uint32_t temp; /* Temporary word value */
|
||||
uint32_t W[80]; /* Word sequence */
|
||||
uint32_t A, B, C, D, E; /* Word buffers */
|
||||
|
||||
/* initialize the first 16 words in the array W */
|
||||
for (t = 0; t < 16; t++) {
|
||||
/* note: it is much faster to apply be2me here, then using be32_copy */
|
||||
W[t] = be2me_32(block[t]);
|
||||
}
|
||||
|
||||
/* initialize the rest */
|
||||
for (t = 16; t < 80; t++) {
|
||||
W[t] = ROTL32(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1);
|
||||
}
|
||||
|
||||
A = hash[0];
|
||||
B = hash[1];
|
||||
C = hash[2];
|
||||
D = hash[3];
|
||||
E = hash[4];
|
||||
|
||||
for (t = 0; t < 20; t++) {
|
||||
/* the following is faster than ((B & C) | ((~B) & D)) */
|
||||
temp = ROTL32(A, 5) + (((C ^ D) & B) ^ D)
|
||||
+ E + W[t] + 0x5A827999;
|
||||
E = D;
|
||||
D = C;
|
||||
C = ROTL32(B, 30);
|
||||
B = A;
|
||||
A = temp;
|
||||
}
|
||||
|
||||
for (t = 20; t < 40; t++) {
|
||||
temp = ROTL32(A, 5) + (B ^ C ^ D) + E + W[t] + 0x6ED9EBA1;
|
||||
E = D;
|
||||
D = C;
|
||||
C = ROTL32(B, 30);
|
||||
B = A;
|
||||
A = temp;
|
||||
}
|
||||
|
||||
for (t = 40; t < 60; t++) {
|
||||
temp = ROTL32(A, 5) + ((B & C) | (B & D) | (C & D))
|
||||
+ E + W[t] + 0x8F1BBCDC;
|
||||
E = D;
|
||||
D = C;
|
||||
C = ROTL32(B, 30);
|
||||
B = A;
|
||||
A = temp;
|
||||
}
|
||||
|
||||
for (t = 60; t < 80; t++) {
|
||||
temp = ROTL32(A, 5) + (B ^ C ^ D) + E + W[t] + 0xCA62C1D6;
|
||||
E = D;
|
||||
D = C;
|
||||
C = ROTL32(B, 30);
|
||||
B = A;
|
||||
A = temp;
|
||||
}
|
||||
|
||||
hash[0] += A;
|
||||
hash[1] += B;
|
||||
hash[2] += C;
|
||||
hash[3] += D;
|
||||
hash[4] += E;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate message hash.
|
||||
* Can be called repeatedly with chunks of the message to be hashed.
|
||||
*
|
||||
* @param ctx the algorithm context containing current hashing state
|
||||
* @param msg message chunk
|
||||
* @param size length of the message chunk
|
||||
*/
|
||||
void rhash_sha1_update(sha1_ctx *ctx, const unsigned char* msg, size_t size)
|
||||
{
|
||||
unsigned index = (unsigned)ctx->length & 63;
|
||||
ctx->length += size;
|
||||
|
||||
/* fill partial block */
|
||||
if (index) {
|
||||
unsigned left = sha1_block_size - index;
|
||||
memcpy(ctx->message + index, msg, (size < left ? size : left));
|
||||
if (size < left) return;
|
||||
|
||||
/* process partial block */
|
||||
rhash_sha1_process_block(ctx->hash, (unsigned*)ctx->message);
|
||||
msg += left;
|
||||
size -= left;
|
||||
}
|
||||
while (size >= sha1_block_size) {
|
||||
unsigned* aligned_message_block;
|
||||
if (IS_ALIGNED_32(msg)) {
|
||||
/* the most common case is processing of an already aligned message
|
||||
without copying it */
|
||||
aligned_message_block = (unsigned*)msg;
|
||||
} else {
|
||||
memcpy(ctx->message, msg, sha1_block_size);
|
||||
aligned_message_block = (unsigned*)ctx->message;
|
||||
}
|
||||
|
||||
rhash_sha1_process_block(ctx->hash, aligned_message_block);
|
||||
msg += sha1_block_size;
|
||||
size -= sha1_block_size;
|
||||
}
|
||||
if (size) {
|
||||
/* save leftovers */
|
||||
memcpy(ctx->message, msg, size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store calculated hash into the given array.
|
||||
*
|
||||
* @param ctx the algorithm context containing current hashing state
|
||||
* @param result calculated hash in binary form
|
||||
*/
|
||||
void rhash_sha1_final(sha1_ctx *ctx, unsigned char* result)
|
||||
{
|
||||
unsigned index = (unsigned)ctx->length & 63;
|
||||
unsigned* msg32 = (unsigned*)ctx->message;
|
||||
|
||||
/* pad message and run for last block */
|
||||
ctx->message[index++] = 0x80;
|
||||
while ((index & 3) != 0) {
|
||||
ctx->message[index++] = 0;
|
||||
}
|
||||
index >>= 2;
|
||||
|
||||
/* if no room left in the message to store 64-bit message length */
|
||||
if (index > 14) {
|
||||
/* then fill the rest with zeros and process it */
|
||||
while (index < 16) {
|
||||
msg32[index++] = 0;
|
||||
}
|
||||
rhash_sha1_process_block(ctx->hash, msg32);
|
||||
index = 0;
|
||||
}
|
||||
while (index < 14) {
|
||||
msg32[index++] = 0;
|
||||
}
|
||||
msg32[14] = be2me_32( (unsigned)(ctx->length >> 29) );
|
||||
msg32[15] = be2me_32( (unsigned)(ctx->length << 3) );
|
||||
rhash_sha1_process_block(ctx->hash, msg32);
|
||||
|
||||
if (result) be32_copy(result, 0, &ctx->hash, sha1_hash_size);
|
||||
}
|
31
Utilities/cmlibrhash/librhash/sha1.h
Normal file
31
Utilities/cmlibrhash/librhash/sha1.h
Normal file
@ -0,0 +1,31 @@
|
||||
/* sha1.h */
|
||||
#ifndef SHA1_H
|
||||
#define SHA1_H
|
||||
#include "ustd.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define sha1_block_size 64
|
||||
#define sha1_hash_size 20
|
||||
|
||||
/* algorithm context */
|
||||
typedef struct sha1_ctx
|
||||
{
|
||||
unsigned char message[sha1_block_size]; /* 512-bit buffer for leftovers */
|
||||
uint64_t length; /* number of processed bytes */
|
||||
unsigned hash[5]; /* 160-bit algorithm internal hashing state */
|
||||
} sha1_ctx;
|
||||
|
||||
/* hash functions */
|
||||
|
||||
void rhash_sha1_init(sha1_ctx *ctx);
|
||||
void rhash_sha1_update(sha1_ctx *ctx, const unsigned char* msg, size_t size);
|
||||
void rhash_sha1_final(sha1_ctx *ctx, unsigned char* result);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* SHA1_H */
|
241
Utilities/cmlibrhash/librhash/sha256.c
Normal file
241
Utilities/cmlibrhash/librhash/sha256.c
Normal file
@ -0,0 +1,241 @@
|
||||
/* sha256.c - an implementation of SHA-256/224 hash functions
|
||||
* based on FIPS 180-3 (Federal Information Processing Standart).
|
||||
*
|
||||
* Copyright: 2010-2012 Aleksey Kravchenko <rhash.admin@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "byte_order.h"
|
||||
#include "sha256.h"
|
||||
|
||||
/* SHA-224 and SHA-256 constants for 64 rounds. These words represent
|
||||
* the first 32 bits of the fractional parts of the cube
|
||||
* roots of the first 64 prime numbers. */
|
||||
static const unsigned rhash_k256[64] = {
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
|
||||
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
|
||||
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
|
||||
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
|
||||
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
|
||||
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||
};
|
||||
|
||||
/* The SHA256/224 functions defined by FIPS 180-3, 4.1.2 */
|
||||
/* Optimized version of Ch(x,y,z)=((x & y) | (~x & z)) */
|
||||
#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
|
||||
/* Optimized version of Maj(x,y,z)=((x & y) ^ (x & z) ^ (y & z)) */
|
||||
#define Maj(x,y,z) (((x) & (y)) ^ ((z) & ((x) ^ (y))))
|
||||
|
||||
#define Sigma0(x) (ROTR32((x), 2) ^ ROTR32((x), 13) ^ ROTR32((x), 22))
|
||||
#define Sigma1(x) (ROTR32((x), 6) ^ ROTR32((x), 11) ^ ROTR32((x), 25))
|
||||
#define sigma0(x) (ROTR32((x), 7) ^ ROTR32((x), 18) ^ ((x) >> 3))
|
||||
#define sigma1(x) (ROTR32((x),17) ^ ROTR32((x), 19) ^ ((x) >> 10))
|
||||
|
||||
/* Recalculate element n-th of circular buffer W using formula
|
||||
* W[n] = sigma1(W[n - 2]) + W[n - 7] + sigma0(W[n - 15]) + W[n - 16]; */
|
||||
#define RECALCULATE_W(W,n) (W[n] += \
|
||||
(sigma1(W[(n - 2) & 15]) + W[(n - 7) & 15] + sigma0(W[(n - 15) & 15])))
|
||||
|
||||
#define ROUND(a,b,c,d,e,f,g,h,k,data) { \
|
||||
unsigned T1 = h + Sigma1(e) + Ch(e,f,g) + k + (data); \
|
||||
d += T1, h = T1 + Sigma0(a) + Maj(a,b,c); }
|
||||
#define ROUND_1_16(a,b,c,d,e,f,g,h,n) \
|
||||
ROUND(a,b,c,d,e,f,g,h, rhash_k256[n], W[n] = be2me_32(block[n]))
|
||||
#define ROUND_17_64(a,b,c,d,e,f,g,h,n) \
|
||||
ROUND(a,b,c,d,e,f,g,h, k[n], RECALCULATE_W(W, n))
|
||||
|
||||
/**
|
||||
* Initialize context before calculaing hash.
|
||||
*
|
||||
* @param ctx context to initialize
|
||||
*/
|
||||
void rhash_sha256_init(sha256_ctx *ctx)
|
||||
{
|
||||
/* Initial values. These words were obtained by taking the first 32
|
||||
* bits of the fractional parts of the square roots of the first
|
||||
* eight prime numbers. */
|
||||
static const unsigned SHA256_H0[8] = {
|
||||
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
||||
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
|
||||
};
|
||||
|
||||
ctx->length = 0;
|
||||
ctx->digest_length = sha256_hash_size;
|
||||
|
||||
/* initialize algorithm state */
|
||||
memcpy(ctx->hash, SHA256_H0, sizeof(ctx->hash));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize context before calculaing hash.
|
||||
*
|
||||
* @param ctx context to initialize
|
||||
*/
|
||||
void rhash_sha224_init(struct sha256_ctx *ctx)
|
||||
{
|
||||
/* Initial values from FIPS 180-3. These words were obtained by taking
|
||||
* bits from 33th to 64th of the fractional parts of the square
|
||||
* roots of ninth through sixteenth prime numbers. */
|
||||
static const unsigned SHA224_H0[8] = {
|
||||
0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
|
||||
0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4
|
||||
};
|
||||
|
||||
ctx->length = 0;
|
||||
ctx->digest_length = sha224_hash_size;
|
||||
|
||||
memcpy(ctx->hash, SHA224_H0, sizeof(ctx->hash));
|
||||
}
|
||||
|
||||
/**
|
||||
* The core transformation. Process a 512-bit block.
|
||||
*
|
||||
* @param hash algorithm state
|
||||
* @param block the message block to process
|
||||
*/
|
||||
static void rhash_sha256_process_block(unsigned hash[8], unsigned block[16])
|
||||
{
|
||||
unsigned A, B, C, D, E, F, G, H;
|
||||
unsigned W[16];
|
||||
const unsigned *k;
|
||||
int i;
|
||||
|
||||
A = hash[0], B = hash[1], C = hash[2], D = hash[3];
|
||||
E = hash[4], F = hash[5], G = hash[6], H = hash[7];
|
||||
|
||||
/* Compute SHA using alternate Method: FIPS 180-3 6.1.3 */
|
||||
ROUND_1_16(A, B, C, D, E, F, G, H, 0);
|
||||
ROUND_1_16(H, A, B, C, D, E, F, G, 1);
|
||||
ROUND_1_16(G, H, A, B, C, D, E, F, 2);
|
||||
ROUND_1_16(F, G, H, A, B, C, D, E, 3);
|
||||
ROUND_1_16(E, F, G, H, A, B, C, D, 4);
|
||||
ROUND_1_16(D, E, F, G, H, A, B, C, 5);
|
||||
ROUND_1_16(C, D, E, F, G, H, A, B, 6);
|
||||
ROUND_1_16(B, C, D, E, F, G, H, A, 7);
|
||||
ROUND_1_16(A, B, C, D, E, F, G, H, 8);
|
||||
ROUND_1_16(H, A, B, C, D, E, F, G, 9);
|
||||
ROUND_1_16(G, H, A, B, C, D, E, F, 10);
|
||||
ROUND_1_16(F, G, H, A, B, C, D, E, 11);
|
||||
ROUND_1_16(E, F, G, H, A, B, C, D, 12);
|
||||
ROUND_1_16(D, E, F, G, H, A, B, C, 13);
|
||||
ROUND_1_16(C, D, E, F, G, H, A, B, 14);
|
||||
ROUND_1_16(B, C, D, E, F, G, H, A, 15);
|
||||
|
||||
for (i = 16, k = &rhash_k256[16]; i < 64; i += 16, k += 16) {
|
||||
ROUND_17_64(A, B, C, D, E, F, G, H, 0);
|
||||
ROUND_17_64(H, A, B, C, D, E, F, G, 1);
|
||||
ROUND_17_64(G, H, A, B, C, D, E, F, 2);
|
||||
ROUND_17_64(F, G, H, A, B, C, D, E, 3);
|
||||
ROUND_17_64(E, F, G, H, A, B, C, D, 4);
|
||||
ROUND_17_64(D, E, F, G, H, A, B, C, 5);
|
||||
ROUND_17_64(C, D, E, F, G, H, A, B, 6);
|
||||
ROUND_17_64(B, C, D, E, F, G, H, A, 7);
|
||||
ROUND_17_64(A, B, C, D, E, F, G, H, 8);
|
||||
ROUND_17_64(H, A, B, C, D, E, F, G, 9);
|
||||
ROUND_17_64(G, H, A, B, C, D, E, F, 10);
|
||||
ROUND_17_64(F, G, H, A, B, C, D, E, 11);
|
||||
ROUND_17_64(E, F, G, H, A, B, C, D, 12);
|
||||
ROUND_17_64(D, E, F, G, H, A, B, C, 13);
|
||||
ROUND_17_64(C, D, E, F, G, H, A, B, 14);
|
||||
ROUND_17_64(B, C, D, E, F, G, H, A, 15);
|
||||
}
|
||||
|
||||
hash[0] += A, hash[1] += B, hash[2] += C, hash[3] += D;
|
||||
hash[4] += E, hash[5] += F, hash[6] += G, hash[7] += H;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate message hash.
|
||||
* Can be called repeatedly with chunks of the message to be hashed.
|
||||
*
|
||||
* @param ctx the algorithm context containing current hashing state
|
||||
* @param msg message chunk
|
||||
* @param size length of the message chunk
|
||||
*/
|
||||
void rhash_sha256_update(sha256_ctx *ctx, const unsigned char *msg, size_t size)
|
||||
{
|
||||
size_t index = (size_t)ctx->length & 63;
|
||||
ctx->length += size;
|
||||
|
||||
/* fill partial block */
|
||||
if (index) {
|
||||
size_t left = sha256_block_size - index;
|
||||
memcpy((char*)ctx->message + index, msg, (size < left ? size : left));
|
||||
if (size < left) return;
|
||||
|
||||
/* process partial block */
|
||||
rhash_sha256_process_block(ctx->hash, (unsigned*)ctx->message);
|
||||
msg += left;
|
||||
size -= left;
|
||||
}
|
||||
while (size >= sha256_block_size) {
|
||||
unsigned* aligned_message_block;
|
||||
if (IS_ALIGNED_32(msg)) {
|
||||
/* the most common case is processing of an already aligned message
|
||||
without copying it */
|
||||
aligned_message_block = (unsigned*)msg;
|
||||
} else {
|
||||
memcpy(ctx->message, msg, sha256_block_size);
|
||||
aligned_message_block = (unsigned*)ctx->message;
|
||||
}
|
||||
|
||||
rhash_sha256_process_block(ctx->hash, aligned_message_block);
|
||||
msg += sha256_block_size;
|
||||
size -= sha256_block_size;
|
||||
}
|
||||
if (size) {
|
||||
memcpy(ctx->message, msg, size); /* save leftovers */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store calculated hash into the given array.
|
||||
*
|
||||
* @param ctx the algorithm context containing current hashing state
|
||||
* @param result calculated hash in binary form
|
||||
*/
|
||||
void rhash_sha256_final(sha256_ctx *ctx, unsigned char* result)
|
||||
{
|
||||
size_t index = ((unsigned)ctx->length & 63) >> 2;
|
||||
unsigned shift = ((unsigned)ctx->length & 3) * 8;
|
||||
|
||||
/* pad message and run for last block */
|
||||
|
||||
/* append the byte 0x80 to the message */
|
||||
ctx->message[index] &= le2me_32(~(0xFFFFFFFF << shift));
|
||||
ctx->message[index++] ^= le2me_32(0x80 << shift);
|
||||
|
||||
/* if no room left in the message to store 64-bit message length */
|
||||
if (index > 14) {
|
||||
/* then fill the rest with zeros and process it */
|
||||
while (index < 16) {
|
||||
ctx->message[index++] = 0;
|
||||
}
|
||||
rhash_sha256_process_block(ctx->hash, ctx->message);
|
||||
index = 0;
|
||||
}
|
||||
while (index < 14) {
|
||||
ctx->message[index++] = 0;
|
||||
}
|
||||
ctx->message[14] = be2me_32( (unsigned)(ctx->length >> 29) );
|
||||
ctx->message[15] = be2me_32( (unsigned)(ctx->length << 3) );
|
||||
rhash_sha256_process_block(ctx->hash, ctx->message);
|
||||
|
||||
if (result) be32_copy(result, 0, ctx->hash, ctx->digest_length);
|
||||
}
|
32
Utilities/cmlibrhash/librhash/sha256.h
Normal file
32
Utilities/cmlibrhash/librhash/sha256.h
Normal file
@ -0,0 +1,32 @@
|
||||
/* sha.h sha256 and sha224 hash functions */
|
||||
#ifndef SHA256_H
|
||||
#define SHA256_H
|
||||
#include "ustd.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define sha256_block_size 64
|
||||
#define sha256_hash_size 32
|
||||
#define sha224_hash_size 28
|
||||
|
||||
/* algorithm context */
|
||||
typedef struct sha256_ctx
|
||||
{
|
||||
unsigned message[16]; /* 512-bit buffer for leftovers */
|
||||
uint64_t length; /* number of processed bytes */
|
||||
unsigned hash[8]; /* 256-bit algorithm internal hashing state */
|
||||
unsigned digest_length; /* length of the algorithm digest in bytes */
|
||||
} sha256_ctx;
|
||||
|
||||
void rhash_sha224_init(sha256_ctx *ctx);
|
||||
void rhash_sha256_init(sha256_ctx *ctx);
|
||||
void rhash_sha256_update(sha256_ctx *ctx, const unsigned char* data, size_t length);
|
||||
void rhash_sha256_final(sha256_ctx *ctx, unsigned char result[32]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* SHA256_H */
|
255
Utilities/cmlibrhash/librhash/sha512.c
Normal file
255
Utilities/cmlibrhash/librhash/sha512.c
Normal file
@ -0,0 +1,255 @@
|
||||
/* sha512.c - an implementation of SHA-384/512 hash functions
|
||||
* based on FIPS 180-3 (Federal Information Processing Standart).
|
||||
*
|
||||
* Copyright: 2010-2012 Aleksey Kravchenko <rhash.admin@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "byte_order.h"
|
||||
#include "sha512.h"
|
||||
|
||||
/* SHA-384 and SHA-512 constants for 80 rounds. These qwords represent
|
||||
* the first 64 bits of the fractional parts of the cube
|
||||
* roots of the first 80 prime numbers. */
|
||||
static const uint64_t rhash_k512[80] = {
|
||||
I64(0x428a2f98d728ae22), I64(0x7137449123ef65cd), I64(0xb5c0fbcfec4d3b2f),
|
||||
I64(0xe9b5dba58189dbbc), I64(0x3956c25bf348b538), I64(0x59f111f1b605d019),
|
||||
I64(0x923f82a4af194f9b), I64(0xab1c5ed5da6d8118), I64(0xd807aa98a3030242),
|
||||
I64(0x12835b0145706fbe), I64(0x243185be4ee4b28c), I64(0x550c7dc3d5ffb4e2),
|
||||
I64(0x72be5d74f27b896f), I64(0x80deb1fe3b1696b1), I64(0x9bdc06a725c71235),
|
||||
I64(0xc19bf174cf692694), I64(0xe49b69c19ef14ad2), I64(0xefbe4786384f25e3),
|
||||
I64(0x0fc19dc68b8cd5b5), I64(0x240ca1cc77ac9c65), I64(0x2de92c6f592b0275),
|
||||
I64(0x4a7484aa6ea6e483), I64(0x5cb0a9dcbd41fbd4), I64(0x76f988da831153b5),
|
||||
I64(0x983e5152ee66dfab), I64(0xa831c66d2db43210), I64(0xb00327c898fb213f),
|
||||
I64(0xbf597fc7beef0ee4), I64(0xc6e00bf33da88fc2), I64(0xd5a79147930aa725),
|
||||
I64(0x06ca6351e003826f), I64(0x142929670a0e6e70), I64(0x27b70a8546d22ffc),
|
||||
I64(0x2e1b21385c26c926), I64(0x4d2c6dfc5ac42aed), I64(0x53380d139d95b3df),
|
||||
I64(0x650a73548baf63de), I64(0x766a0abb3c77b2a8), I64(0x81c2c92e47edaee6),
|
||||
I64(0x92722c851482353b), I64(0xa2bfe8a14cf10364), I64(0xa81a664bbc423001),
|
||||
I64(0xc24b8b70d0f89791), I64(0xc76c51a30654be30), I64(0xd192e819d6ef5218),
|
||||
I64(0xd69906245565a910), I64(0xf40e35855771202a), I64(0x106aa07032bbd1b8),
|
||||
I64(0x19a4c116b8d2d0c8), I64(0x1e376c085141ab53), I64(0x2748774cdf8eeb99),
|
||||
I64(0x34b0bcb5e19b48a8), I64(0x391c0cb3c5c95a63), I64(0x4ed8aa4ae3418acb),
|
||||
I64(0x5b9cca4f7763e373), I64(0x682e6ff3d6b2b8a3), I64(0x748f82ee5defb2fc),
|
||||
I64(0x78a5636f43172f60), I64(0x84c87814a1f0ab72), I64(0x8cc702081a6439ec),
|
||||
I64(0x90befffa23631e28), I64(0xa4506cebde82bde9), I64(0xbef9a3f7b2c67915),
|
||||
I64(0xc67178f2e372532b), I64(0xca273eceea26619c), I64(0xd186b8c721c0c207),
|
||||
I64(0xeada7dd6cde0eb1e), I64(0xf57d4f7fee6ed178), I64(0x06f067aa72176fba),
|
||||
I64(0x0a637dc5a2c898a6), I64(0x113f9804bef90dae), I64(0x1b710b35131c471b),
|
||||
I64(0x28db77f523047d84), I64(0x32caab7b40c72493), I64(0x3c9ebe0a15c9bebc),
|
||||
I64(0x431d67c49c100d4c), I64(0x4cc5d4becb3e42b6), I64(0x597f299cfc657e2a),
|
||||
I64(0x5fcb6fab3ad6faec), I64(0x6c44198c4a475817)
|
||||
};
|
||||
|
||||
/* The SHA512/384 functions defined by FIPS 180-3, 4.1.3 */
|
||||
/* Optimized version of Ch(x,y,z)=((x & y) | (~x & z)) */
|
||||
#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
|
||||
/* Optimized version of Maj(x,y,z)=((x & y) ^ (x & z) ^ (y & z)) */
|
||||
#define Maj(x,y,z) (((x) & (y)) ^ ((z) & ((x) ^ (y))))
|
||||
|
||||
#define Sigma0(x) (ROTR64((x), 28) ^ ROTR64((x), 34) ^ ROTR64((x), 39))
|
||||
#define Sigma1(x) (ROTR64((x), 14) ^ ROTR64((x), 18) ^ ROTR64((x), 41))
|
||||
#define sigma0(x) (ROTR64((x), 1) ^ ROTR64((x), 8) ^ ((x) >> 7))
|
||||
#define sigma1(x) (ROTR64((x), 19) ^ ROTR64((x), 61) ^ ((x) >> 6))
|
||||
|
||||
/* Recalculate element n-th of circular buffer W using formula
|
||||
* W[n] = sigma1(W[n - 2]) + W[n - 7] + sigma0(W[n - 15]) + W[n - 16]; */
|
||||
#define RECALCULATE_W(W,n) (W[n] += \
|
||||
(sigma1(W[(n - 2) & 15]) + W[(n - 7) & 15] + sigma0(W[(n - 15) & 15])))
|
||||
|
||||
#define ROUND(a,b,c,d,e,f,g,h,k,data) { \
|
||||
uint64_t T1 = h + Sigma1(e) + Ch(e,f,g) + k + (data); \
|
||||
d += T1, h = T1 + Sigma0(a) + Maj(a,b,c); }
|
||||
#define ROUND_1_16(a,b,c,d,e,f,g,h,n) \
|
||||
ROUND(a,b,c,d,e,f,g,h, rhash_k512[n], W[n] = be2me_64(block[n]))
|
||||
#define ROUND_17_80(a,b,c,d,e,f,g,h,n) \
|
||||
ROUND(a,b,c,d,e,f,g,h, k[n], RECALCULATE_W(W, n))
|
||||
|
||||
/**
|
||||
* Initialize context before calculating hash.
|
||||
*
|
||||
* @param ctx context to initialize
|
||||
*/
|
||||
void rhash_sha512_init(sha512_ctx *ctx)
|
||||
{
|
||||
/* Initial values. These words were obtained by taking the first 32
|
||||
* bits of the fractional parts of the square roots of the first
|
||||
* eight prime numbers. */
|
||||
static const uint64_t SHA512_H0[8] = {
|
||||
I64(0x6a09e667f3bcc908), I64(0xbb67ae8584caa73b), I64(0x3c6ef372fe94f82b),
|
||||
I64(0xa54ff53a5f1d36f1), I64(0x510e527fade682d1), I64(0x9b05688c2b3e6c1f),
|
||||
I64(0x1f83d9abfb41bd6b), I64(0x5be0cd19137e2179)
|
||||
};
|
||||
|
||||
ctx->length = 0;
|
||||
ctx->digest_length = sha512_hash_size;
|
||||
|
||||
/* initialize algorithm state */
|
||||
memcpy(ctx->hash, SHA512_H0, sizeof(ctx->hash));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize context before calculaing hash.
|
||||
*
|
||||
* @param ctx context to initialize
|
||||
*/
|
||||
void rhash_sha384_init(struct sha512_ctx *ctx)
|
||||
{
|
||||
/* Initial values from FIPS 180-3. These words were obtained by taking
|
||||
* the first sixty-four bits of the fractional parts of the square
|
||||
* roots of ninth through sixteenth prime numbers. */
|
||||
static const uint64_t SHA384_H0[8] = {
|
||||
I64(0xcbbb9d5dc1059ed8), I64(0x629a292a367cd507), I64(0x9159015a3070dd17),
|
||||
I64(0x152fecd8f70e5939), I64(0x67332667ffc00b31), I64(0x8eb44a8768581511),
|
||||
I64(0xdb0c2e0d64f98fa7), I64(0x47b5481dbefa4fa4)
|
||||
};
|
||||
|
||||
ctx->length = 0;
|
||||
ctx->digest_length = sha384_hash_size;
|
||||
|
||||
memcpy(ctx->hash, SHA384_H0, sizeof(ctx->hash));
|
||||
}
|
||||
|
||||
/**
|
||||
* The core transformation. Process a 512-bit block.
|
||||
*
|
||||
* @param hash algorithm state
|
||||
* @param block the message block to process
|
||||
*/
|
||||
static void rhash_sha512_process_block(uint64_t hash[8], uint64_t block[16])
|
||||
{
|
||||
uint64_t A, B, C, D, E, F, G, H;
|
||||
uint64_t W[16];
|
||||
const uint64_t *k;
|
||||
int i;
|
||||
|
||||
A = hash[0], B = hash[1], C = hash[2], D = hash[3];
|
||||
E = hash[4], F = hash[5], G = hash[6], H = hash[7];
|
||||
|
||||
/* Compute SHA using alternate Method: FIPS 180-3 6.1.3 */
|
||||
ROUND_1_16(A, B, C, D, E, F, G, H, 0);
|
||||
ROUND_1_16(H, A, B, C, D, E, F, G, 1);
|
||||
ROUND_1_16(G, H, A, B, C, D, E, F, 2);
|
||||
ROUND_1_16(F, G, H, A, B, C, D, E, 3);
|
||||
ROUND_1_16(E, F, G, H, A, B, C, D, 4);
|
||||
ROUND_1_16(D, E, F, G, H, A, B, C, 5);
|
||||
ROUND_1_16(C, D, E, F, G, H, A, B, 6);
|
||||
ROUND_1_16(B, C, D, E, F, G, H, A, 7);
|
||||
ROUND_1_16(A, B, C, D, E, F, G, H, 8);
|
||||
ROUND_1_16(H, A, B, C, D, E, F, G, 9);
|
||||
ROUND_1_16(G, H, A, B, C, D, E, F, 10);
|
||||
ROUND_1_16(F, G, H, A, B, C, D, E, 11);
|
||||
ROUND_1_16(E, F, G, H, A, B, C, D, 12);
|
||||
ROUND_1_16(D, E, F, G, H, A, B, C, 13);
|
||||
ROUND_1_16(C, D, E, F, G, H, A, B, 14);
|
||||
ROUND_1_16(B, C, D, E, F, G, H, A, 15);
|
||||
|
||||
for (i = 16, k = &rhash_k512[16]; i < 80; i += 16, k += 16) {
|
||||
ROUND_17_80(A, B, C, D, E, F, G, H, 0);
|
||||
ROUND_17_80(H, A, B, C, D, E, F, G, 1);
|
||||
ROUND_17_80(G, H, A, B, C, D, E, F, 2);
|
||||
ROUND_17_80(F, G, H, A, B, C, D, E, 3);
|
||||
ROUND_17_80(E, F, G, H, A, B, C, D, 4);
|
||||
ROUND_17_80(D, E, F, G, H, A, B, C, 5);
|
||||
ROUND_17_80(C, D, E, F, G, H, A, B, 6);
|
||||
ROUND_17_80(B, C, D, E, F, G, H, A, 7);
|
||||
ROUND_17_80(A, B, C, D, E, F, G, H, 8);
|
||||
ROUND_17_80(H, A, B, C, D, E, F, G, 9);
|
||||
ROUND_17_80(G, H, A, B, C, D, E, F, 10);
|
||||
ROUND_17_80(F, G, H, A, B, C, D, E, 11);
|
||||
ROUND_17_80(E, F, G, H, A, B, C, D, 12);
|
||||
ROUND_17_80(D, E, F, G, H, A, B, C, 13);
|
||||
ROUND_17_80(C, D, E, F, G, H, A, B, 14);
|
||||
ROUND_17_80(B, C, D, E, F, G, H, A, 15);
|
||||
}
|
||||
|
||||
hash[0] += A, hash[1] += B, hash[2] += C, hash[3] += D;
|
||||
hash[4] += E, hash[5] += F, hash[6] += G, hash[7] += H;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate message hash.
|
||||
* Can be called repeatedly with chunks of the message to be hashed.
|
||||
*
|
||||
* @param ctx the algorithm context containing current hashing state
|
||||
* @param msg message chunk
|
||||
* @param size length of the message chunk
|
||||
*/
|
||||
void rhash_sha512_update(sha512_ctx *ctx, const unsigned char *msg, size_t size)
|
||||
{
|
||||
size_t index = (size_t)ctx->length & 127;
|
||||
ctx->length += size;
|
||||
|
||||
/* fill partial block */
|
||||
if (index) {
|
||||
size_t left = sha512_block_size - index;
|
||||
memcpy((char*)ctx->message + index, msg, (size < left ? size : left));
|
||||
if (size < left) return;
|
||||
|
||||
/* process partial block */
|
||||
rhash_sha512_process_block(ctx->hash, ctx->message);
|
||||
msg += left;
|
||||
size -= left;
|
||||
}
|
||||
while (size >= sha512_block_size) {
|
||||
uint64_t* aligned_message_block;
|
||||
if (IS_ALIGNED_64(msg)) {
|
||||
/* the most common case is processing of an already aligned message
|
||||
without copying it */
|
||||
aligned_message_block = (uint64_t*)msg;
|
||||
} else {
|
||||
memcpy(ctx->message, msg, sha512_block_size);
|
||||
aligned_message_block = ctx->message;
|
||||
}
|
||||
|
||||
rhash_sha512_process_block(ctx->hash, aligned_message_block);
|
||||
msg += sha512_block_size;
|
||||
size -= sha512_block_size;
|
||||
}
|
||||
if (size) {
|
||||
memcpy(ctx->message, msg, size); /* save leftovers */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store calculated hash into the given array.
|
||||
*
|
||||
* @param ctx the algorithm context containing current hashing state
|
||||
* @param result calculated hash in binary form
|
||||
*/
|
||||
void rhash_sha512_final(sha512_ctx *ctx, unsigned char* result)
|
||||
{
|
||||
size_t index = ((unsigned)ctx->length & 127) >> 3;
|
||||
unsigned shift = ((unsigned)ctx->length & 7) * 8;
|
||||
|
||||
/* pad message and process the last block */
|
||||
|
||||
/* append the byte 0x80 to the message */
|
||||
ctx->message[index] &= le2me_64( ~(I64(0xFFFFFFFFFFFFFFFF) << shift) );
|
||||
ctx->message[index++] ^= le2me_64( I64(0x80) << shift );
|
||||
|
||||
/* if no room left in the message to store 128-bit message length */
|
||||
if (index >= 15) {
|
||||
if (index == 15) ctx->message[index] = 0;
|
||||
rhash_sha512_process_block(ctx->hash, ctx->message);
|
||||
index = 0;
|
||||
}
|
||||
while (index < 15) {
|
||||
ctx->message[index++] = 0;
|
||||
}
|
||||
ctx->message[15] = be2me_64(ctx->length << 3);
|
||||
rhash_sha512_process_block(ctx->hash, ctx->message);
|
||||
|
||||
if (result) be64_copy(result, 0, ctx->hash, ctx->digest_length);
|
||||
}
|
32
Utilities/cmlibrhash/librhash/sha512.h
Normal file
32
Utilities/cmlibrhash/librhash/sha512.h
Normal file
@ -0,0 +1,32 @@
|
||||
/* sha.h sha512 and sha384 hash functions */
|
||||
#ifndef SHA512_H
|
||||
#define SHA512_H
|
||||
#include "ustd.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define sha512_block_size 128
|
||||
#define sha512_hash_size 64
|
||||
#define sha384_hash_size 48
|
||||
|
||||
/* algorithm context */
|
||||
typedef struct sha512_ctx
|
||||
{
|
||||
uint64_t message[16]; /* 1024-bit buffer for leftovers */
|
||||
uint64_t length; /* number of processed bytes */
|
||||
uint64_t hash[8]; /* 512-bit algorithm internal hashing state */
|
||||
unsigned digest_length; /* length of the algorithm digest in bytes */
|
||||
} sha512_ctx;
|
||||
|
||||
void rhash_sha384_init(sha512_ctx *ctx);
|
||||
void rhash_sha512_init(sha512_ctx *ctx);
|
||||
void rhash_sha512_update(sha512_ctx *ctx, const unsigned char* data, size_t length);
|
||||
void rhash_sha512_final(sha512_ctx *ctx, unsigned char* result);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* SHA512_H */
|
30
Utilities/cmlibrhash/librhash/ustd.h
Normal file
30
Utilities/cmlibrhash/librhash/ustd.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* ustd.h common macros and includes */
|
||||
#ifndef LIBRHASH_USTD_H
|
||||
#define LIBRHASH_USTD_H
|
||||
|
||||
#if _MSC_VER >= 1300
|
||||
|
||||
# define int64_t __int64
|
||||
# define int32_t __int32
|
||||
# define int16_t __int16
|
||||
# define int8_t __int8
|
||||
# define uint64_t unsigned __int64
|
||||
# define uint32_t unsigned __int32
|
||||
# define uint16_t unsigned __int16
|
||||
# define uint8_t unsigned __int8
|
||||
|
||||
/* disable warnings: The POSIX name for this item is deprecated. Use the ISO C++ conformant name. */
|
||||
#pragma warning(disable : 4996)
|
||||
|
||||
#else /* _MSC_VER >= 1300 */
|
||||
|
||||
# include <stdint.h>
|
||||
# include <unistd.h>
|
||||
|
||||
#endif /* _MSC_VER >= 1300 */
|
||||
|
||||
#if _MSC_VER <= 1300
|
||||
# include <stdlib.h> /* size_t for vc6.0 */
|
||||
#endif /* _MSC_VER <= 1300 */
|
||||
|
||||
#endif /* LIBRHASH_USTD_H */
|
31
Utilities/cmlibrhash/librhash/util.h
Normal file
31
Utilities/cmlibrhash/librhash/util.h
Normal file
@ -0,0 +1,31 @@
|
||||
/* util.h */
|
||||
#ifndef UTIL_H
|
||||
#define UTIL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if (defined(__GNUC__) && __GNUC__ >= 4 && (__GNUC__ > 4 || __GNUC_MINOR__ >= 1) \
|
||||
&& defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)) \
|
||||
|| (defined(__INTEL_COMPILER) && !defined(_WIN32))
|
||||
/* atomic operations are defined by ICC and GCC >= 4.1, but by the later one supposedly not for ARM */
|
||||
/* note: ICC on ia64 platform possibly require ia64intrin.h, need testing */
|
||||
# define atomic_compare_and_swap(ptr, oldval, newval) __sync_val_compare_and_swap(ptr, oldval, newval)
|
||||
#elif defined(_MSC_VER)
|
||||
# include <windows.h>
|
||||
# define atomic_compare_and_swap(ptr, oldval, newval) InterlockedCompareExchange(ptr, newval, oldval)
|
||||
#elif defined(__sun)
|
||||
# include <atomic.h>
|
||||
# define atomic_compare_and_swap(ptr, oldval, newval) atomic_cas_32(ptr, oldval, newval)
|
||||
#else
|
||||
/* pray that it will work */
|
||||
# define atomic_compare_and_swap(ptr, oldval, newval) { if(*(ptr) == (oldval)) *(ptr) = (newval); }
|
||||
# define NO_ATOMIC_BUILTINS
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* UTIL_H */
|
Loading…
Reference in New Issue
Block a user