/* */ #ifndef _D_MESSAGE_DIGEST_H_ #define _D_MESSAGE_DIGEST_H_ #include "common.h" #include #include #include "SharedHandle.h" #include "DlAbortEx.h" #include "StringFormat.h" #ifdef HAVE_LIBSSL #include #endif // HAVE_LIBSSL #ifdef HAVE_LIBGCRYPT #include #endif // HAVE_LIBGCRYPT namespace aria2 { class MessageDigestContext { public: #ifdef HAVE_LIBSSL typedef const EVP_MD* DigestAlgo; #endif // HAVE_LIBSSL #ifdef HAVE_LIBGCRYPT typedef int DigestAlgo; #endif // HAVE_LIBGCRYPT static const std::string SHA1; static const std::string SHA256; static const std::string MD5; private: #ifdef HAVE_LIBSSL EVP_MD_CTX _ctx; #endif // HAVE_LIBSSL #ifdef HAVE_LIBGCRYPT gcry_md_hd_t _ctx; #endif // HAVE_LIBGCRYPT DigestAlgo _algo; public: MessageDigestContext():_algo(getDigestAlgo(MessageDigestContext::SHA1)) {} ~MessageDigestContext() { digestFree(); } void trySetAlgo(const std::string& algostring) { _algo = getDigestAlgo(algostring); } static bool supports(const std::string& algostring); static DigestAlgo getDigestAlgo(const std::string& algostring); static std::string getSupportedAlgoString(); static size_t digestLength(const std::string& algostring) { return digestLength(getDigestAlgo(algostring)); } // Returns true if hash algorithm specified by lhs is stronger than // the one specified by rhs. If either lhs or rhs is not supported // or both are not supported, returns false. static bool isStronger(const std::string& lhs, const std::string& rhs); static bool isValidHash (const std::string& algostring, const std::string& hashstring); // Returns canonical hash algorithm name of given algostring. If // given algostring is not supported, then returns algostring // unchanged. static std::string getCanonicalAlgo(const std::string& algostring); std::string digestFinal(); #if defined(HAVE_OLD_LIBSSL) void digestInit() { EVP_DigestInit(&_ctx, _algo); } void digestReset() { EVP_DigestInit(&_ctx, _algo); } void digestUpdate(const void* data, size_t length) { EVP_DigestUpdate(&_ctx, data, length); } void digestFinal(unsigned char* md) { unsigned int len; EVP_DigestFinal(&_ctx, md, &len); } void digestFree() {/*empty*/} size_t digestLength() const { return digestLength(_algo); } static size_t digestLength(DigestAlgo algo) { return EVP_MD_size(algo); } #elif defined(HAVE_LIBSSL) void digestInit() { EVP_MD_CTX_init(&_ctx); digestReset(); } void digestReset() { EVP_DigestInit_ex(&_ctx, _algo, 0); } void digestUpdate(const void* data, size_t length) { EVP_DigestUpdate(&_ctx, data, length); } void digestFinal(unsigned char* md) { unsigned int len; EVP_DigestFinal_ex(&_ctx, md, &len); } void digestFree() { EVP_MD_CTX_cleanup(&_ctx); } size_t digestLength() const { return digestLength(_algo); } static size_t digestLength(DigestAlgo algo) { return EVP_MD_size(algo); } #elif defined(HAVE_LIBGCRYPT) void digestInit() { gcry_md_open(&_ctx, _algo, 0); } void digestReset() { gcry_md_reset(_ctx); } void digestUpdate(const void* data, size_t length) { gcry_md_write(_ctx, data, length); } void digestFinal(unsigned char* md) { gcry_md_final(_ctx); memcpy(md, gcry_md_read(_ctx, 0), gcry_md_get_algo_dlen(_algo)); } void digestFree() { gcry_md_close(_ctx); } size_t digestLength() const { return digestLength(_algo); } static size_t digestLength(DigestAlgo algo) { return gcry_md_get_algo_dlen(algo); } #endif // HAVE_LIBGCRYPT }; typedef SharedHandle MessageDigestContextHandle; } // namespace aria2 #endif // _D_MESSAGE_DIGEST_H_