nsec3hash.cc 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. // Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <stdint.h>
  15. #include <cassert>
  16. #include <cstring>
  17. #include <string>
  18. #include <vector>
  19. #include <boost/noncopyable.hpp>
  20. #include <exceptions/exceptions.h>
  21. #include <util/buffer.h>
  22. #include <util/encode/base32hex.h>
  23. #include <util/hash/sha1.h>
  24. #include <dns/name.h>
  25. #include <dns/nsec3hash.h>
  26. #include <dns/rdataclass.h>
  27. using namespace std;
  28. using namespace isc::util;
  29. using namespace isc::util::encode;
  30. using namespace isc::util::hash;
  31. using namespace isc::dns;
  32. using namespace isc::dns::rdata;
  33. namespace {
  34. /// \brief A derived class of \c NSEC3Hash that implements the standard hash
  35. /// calculation specified in RFC5155.
  36. ///
  37. /// Currently the only pre-defined algorithm in the RFC is SHA1. So we don't
  38. /// over-generalize it at the moment, and rather hardocde it and assume that
  39. /// specific algorithm.
  40. ///
  41. /// The implementation details are only open within this file, but to avoid
  42. /// an accidental error in this implementation we explicitly make it non
  43. /// copyable.
  44. class NSEC3HashRFC5155 : boost::noncopyable, public NSEC3Hash {
  45. private:
  46. // This is the algorithm number for SHA1/NSEC3 as defined in RFC5155.
  47. static const uint8_t NSEC3_HASH_SHA1 = 1;
  48. public:
  49. NSEC3HashRFC5155(uint8_t algorithm, uint16_t iterations,
  50. const uint8_t* salt_data, size_t salt_length) :
  51. algorithm_(algorithm), iterations_(iterations),
  52. salt_data_(NULL), salt_length_(salt_length),
  53. digest_(SHA1_HASHSIZE), obuf_(Name::MAX_WIRE)
  54. {
  55. if (algorithm_ != NSEC3_HASH_SHA1) {
  56. isc_throw(UnknownNSEC3HashAlgorithm, "Unknown NSEC3 algorithm: " <<
  57. static_cast<unsigned int>(algorithm_));
  58. }
  59. if (salt_length > 0) {
  60. salt_data_ = static_cast<uint8_t*>(std::malloc(salt_length));
  61. if (salt_data_ == NULL) {
  62. throw std::bad_alloc();
  63. }
  64. std::memcpy(salt_data_, salt_data, salt_length);
  65. }
  66. SHA1Reset(&sha1_ctx_);
  67. }
  68. ~NSEC3HashRFC5155()
  69. {
  70. if (salt_data_ != NULL) {
  71. free(salt_data_);
  72. }
  73. }
  74. virtual std::string calculate(const Name& name) const;
  75. virtual bool match(const generic::NSEC3& nsec3) const;
  76. virtual bool match(const generic::NSEC3PARAM& nsec3param) const;
  77. bool match(uint8_t algorithm, uint16_t iterations,
  78. const vector<uint8_t>& salt) const;
  79. private:
  80. const uint8_t algorithm_;
  81. const uint16_t iterations_;
  82. uint8_t* salt_data_;
  83. const size_t salt_length_;
  84. // The following members are placeholder of work place and don't hold
  85. // any state over multiple calls so can be mutable without breaking
  86. // constness.
  87. mutable SHA1Context sha1_ctx_;
  88. mutable vector<uint8_t> digest_;
  89. mutable OutputBuffer obuf_;
  90. };
  91. inline void
  92. iterateSHA1(SHA1Context* ctx, const uint8_t* input, size_t inlength,
  93. const uint8_t* salt, size_t saltlen,
  94. uint8_t output[SHA1_HASHSIZE])
  95. {
  96. SHA1Reset(ctx);
  97. SHA1Input(ctx, input, inlength);
  98. SHA1Input(ctx, salt, saltlen); // this works whether saltlen == or > 0
  99. SHA1Result(ctx, output);
  100. }
  101. string
  102. NSEC3HashRFC5155::calculate(const Name& name) const {
  103. // We first need to normalize the name by converting all upper case
  104. // characters in the labels to lower ones.
  105. obuf_.clear();
  106. Name name_copy(name);
  107. name_copy.downcase();
  108. name_copy.toWire(obuf_);
  109. const uint8_t* const salt = (salt_length_ > 0) ? salt_data_ : NULL;
  110. uint8_t* const digest = &digest_[0];
  111. assert(digest_.size() == SHA1_HASHSIZE);
  112. iterateSHA1(&sha1_ctx_, static_cast<const uint8_t*>(obuf_.getData()),
  113. obuf_.getLength(), salt, salt_length_, digest);
  114. for (unsigned int n = 0; n < iterations_; ++n) {
  115. iterateSHA1(&sha1_ctx_, digest, SHA1_HASHSIZE,
  116. salt, salt_length_, digest);
  117. }
  118. return (encodeBase32Hex(digest_));
  119. }
  120. bool
  121. NSEC3HashRFC5155::match(uint8_t algorithm, uint16_t iterations,
  122. const vector<uint8_t>& salt) const
  123. {
  124. return (algorithm_ == algorithm && iterations_ == iterations &&
  125. salt_length_ == salt.size() &&
  126. ((salt_length_ == 0) ||
  127. memcmp(salt_data_, &salt[0], salt_length_) == 0));
  128. }
  129. bool
  130. NSEC3HashRFC5155::match(const generic::NSEC3& nsec3) const {
  131. return (match(nsec3.getHashalg(), nsec3.getIterations(),
  132. nsec3.getSalt()));
  133. }
  134. bool
  135. NSEC3HashRFC5155::match(const generic::NSEC3PARAM& nsec3param) const {
  136. return (match(nsec3param.getHashalg(), nsec3param.getIterations(),
  137. nsec3param.getSalt()));
  138. }
  139. // A static pointer that refers to the currently usable creator.
  140. // Only get/setNSEC3HashCreator are expected to get access to this variable
  141. // directly.
  142. const NSEC3HashCreator* creator;
  143. // The accessor to the current creator. If it's not explicitly set or has
  144. // been reset from a customized one, the default creator will be used.
  145. const NSEC3HashCreator*
  146. getNSEC3HashCreator() {
  147. static DefaultNSEC3HashCreator default_creator;
  148. if (creator == NULL) {
  149. creator = &default_creator;
  150. }
  151. return (creator);
  152. }
  153. } // end of unnamed namespace
  154. namespace isc {
  155. namespace dns {
  156. NSEC3Hash*
  157. NSEC3Hash::create(const generic::NSEC3PARAM& param) {
  158. return (getNSEC3HashCreator()->create(param));
  159. }
  160. NSEC3Hash*
  161. NSEC3Hash::create(const generic::NSEC3& nsec3) {
  162. return (getNSEC3HashCreator()->create(nsec3));
  163. }
  164. NSEC3Hash*
  165. NSEC3Hash::create(uint8_t algorithm, uint16_t iterations,
  166. const uint8_t* salt_data, size_t salt_length) {
  167. return (getNSEC3HashCreator()->create(algorithm, iterations,
  168. salt_data, salt_length));
  169. }
  170. NSEC3Hash*
  171. DefaultNSEC3HashCreator::create(const generic::NSEC3PARAM& param) const {
  172. const vector<uint8_t>& salt = param.getSalt();
  173. return (new NSEC3HashRFC5155(param.getHashalg(), param.getIterations(),
  174. &salt[0], salt.size()));
  175. }
  176. NSEC3Hash*
  177. DefaultNSEC3HashCreator::create(const generic::NSEC3& nsec3) const {
  178. const vector<uint8_t>& salt = nsec3.getSalt();
  179. return (new NSEC3HashRFC5155(nsec3.getHashalg(), nsec3.getIterations(),
  180. &salt[0], salt.size()));
  181. }
  182. NSEC3Hash*
  183. DefaultNSEC3HashCreator::create(uint8_t algorithm, uint16_t iterations,
  184. const uint8_t* salt_data,
  185. size_t salt_length) const
  186. {
  187. return (new NSEC3HashRFC5155(algorithm, iterations,
  188. salt_data, salt_length));
  189. }
  190. void
  191. setNSEC3HashCreator(const NSEC3HashCreator* new_creator) {
  192. creator = new_creator;
  193. }
  194. } // namespace dns
  195. } // namespace isc