openssl_hash.cc 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. #include <cryptolink.h>
  7. #include <cryptolink/crypto_hash.h>
  8. #include <boost/scoped_ptr.hpp>
  9. #include <openssl/evp.h>
  10. #include <cryptolink/openssl_common.h>
  11. #define KEA_HASH
  12. #include <cryptolink/openssl_compat.h>
  13. #include <cstring>
  14. namespace isc {
  15. namespace cryptolink {
  16. /// @brief Decode the HashAlgorithm enum into an EVP_MD pointer (or 0)
  17. ///
  18. /// EVP_MD pointer is a OpenSSL's way of identifying hash algorithms
  19. /// @param algorithm algorithm to be converted
  20. /// @return pointer to EVP_MD which identifies the algorithm
  21. const EVP_MD*
  22. ossl::getHashAlgorithm(HashAlgorithm algorithm) {
  23. switch (algorithm) {
  24. case isc::cryptolink::MD5:
  25. return (EVP_md5());
  26. case isc::cryptolink::SHA1:
  27. return (EVP_sha1());
  28. case isc::cryptolink::SHA256:
  29. return (EVP_sha256());
  30. case isc::cryptolink::SHA224:
  31. return (EVP_sha224());
  32. case isc::cryptolink::SHA384:
  33. return (EVP_sha384());
  34. case isc::cryptolink::SHA512:
  35. return (EVP_sha512());
  36. case isc::cryptolink::UNKNOWN_HASH:
  37. return (0);
  38. }
  39. // compiler should have prevented us to reach this, since we have
  40. // no default. But we need a return value anyway
  41. return (0);
  42. }
  43. /// \brief OpenSSL implementation of Hash. Each method is the counterpart
  44. /// of the Hash corresponding method.
  45. class HashImpl {
  46. public:
  47. /// @brief Constructor for specific hash algorithm
  48. ///
  49. /// @param hash_algorithm The hash algorithm
  50. explicit HashImpl(const HashAlgorithm hash_algorithm)
  51. : hash_algorithm_(hash_algorithm), md_(0) {
  52. const EVP_MD* algo = ossl::getHashAlgorithm(hash_algorithm);
  53. if (algo == 0) {
  54. isc_throw(isc::cryptolink::UnsupportedAlgorithm,
  55. "Unknown hash algorithm: " <<
  56. static_cast<int>(hash_algorithm));
  57. }
  58. md_ = EVP_MD_CTX_new();
  59. if (md_ == 0) {
  60. isc_throw(isc::cryptolink::LibraryError,
  61. "OpenSSL EVP_MD_CTX_new() failed");
  62. }
  63. EVP_DigestInit_ex(md_, algo, NULL);
  64. }
  65. /// @brief Destructor
  66. ~HashImpl() {
  67. if (md_) {
  68. EVP_MD_CTX_free(md_);
  69. }
  70. md_ = 0;
  71. }
  72. /// @brief Returns the HashAlgorithm of the object
  73. HashAlgorithm getHashAlgorithm() const {
  74. return (hash_algorithm_);
  75. }
  76. /// @brief Returns the output size of the digest
  77. ///
  78. /// @return output size of the digest
  79. size_t getOutputLength() const {
  80. return (EVP_MD_CTX_size(md_));
  81. }
  82. /// @brief Adds data to the digest
  83. ///
  84. /// See @ref isc::cryptolink::Hash::update() for details.
  85. void update(const void* data, const size_t len) {
  86. EVP_DigestUpdate(md_, data, len);
  87. }
  88. /// @brief Calculate the final digest
  89. ///
  90. /// See @ref isc::cryptolink::Hash::final() for details.
  91. void final(isc::util::OutputBuffer& result, size_t len) {
  92. size_t size = getOutputLength();
  93. std::vector<unsigned char> digest(size);
  94. EVP_DigestFinal_ex(md_, &digest[0], NULL);
  95. if (len > size) {
  96. len = size;
  97. }
  98. result.writeData(&digest[0], len);
  99. }
  100. /// @brief Calculate the final digest
  101. ///
  102. /// See @ref isc::cryptolink::Hash::final() for details.
  103. void final(void* result, size_t len) {
  104. size_t size = getOutputLength();
  105. std::vector<unsigned char> digest(size);
  106. EVP_DigestFinal_ex(md_, &digest[0], NULL);
  107. if (len > size) {
  108. len = size;
  109. }
  110. std::memcpy(result, &digest[0], len);
  111. }
  112. /// @brief Calculate the final digest
  113. ///
  114. /// See @ref isc::cryptolink::Hash::final() for details.
  115. std::vector<uint8_t> final(size_t len) {
  116. size_t size = getOutputLength();
  117. std::vector<unsigned char> digest(size);
  118. EVP_DigestFinal_ex(md_, &digest[0], NULL);
  119. if (len < size) {
  120. digest.resize(len);
  121. }
  122. return (std::vector<uint8_t>(digest.begin(), digest.end()));
  123. }
  124. private:
  125. /// @brief The hash algorithm
  126. HashAlgorithm hash_algorithm_;
  127. /// @brief The pointer to the OpenSSL EVP_MD_CTX structure
  128. EVP_MD_CTX* md_;
  129. };
  130. Hash::Hash(const HashAlgorithm hash_algorithm)
  131. {
  132. impl_ = new HashImpl(hash_algorithm);
  133. }
  134. Hash::~Hash() {
  135. delete impl_;
  136. }
  137. HashAlgorithm
  138. Hash::getHashAlgorithm() const {
  139. return (impl_->getHashAlgorithm());
  140. }
  141. size_t
  142. Hash::getOutputLength() const {
  143. return (impl_->getOutputLength());
  144. }
  145. void
  146. Hash::update(const void* data, const size_t len) {
  147. impl_->update(data, len);
  148. }
  149. void
  150. Hash::final(isc::util::OutputBuffer& result, size_t len) {
  151. impl_->final(result, len);
  152. }
  153. void
  154. Hash::final(void* result, size_t len) {
  155. impl_->final(result, len);
  156. }
  157. std::vector<uint8_t>
  158. Hash::final(size_t len) {
  159. return impl_->final(len);
  160. }
  161. } // namespace cryptolink
  162. } // namespace isc