nsec3hash.cc 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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 vector<uint8_t>& salt) :
  51. algorithm_(algorithm), iterations_(iterations),
  52. salt_(salt), digest_(SHA1_HASHSIZE), obuf_(Name::MAX_WIRE)
  53. {
  54. if (algorithm_ != NSEC3_HASH_SHA1) {
  55. isc_throw(UnknownNSEC3HashAlgorithm, "Unknown NSEC3 algorithm: " <<
  56. static_cast<unsigned int>(algorithm_));
  57. }
  58. SHA1Reset(&sha1_ctx_);
  59. }
  60. virtual std::string calculate(const Name& name) const;
  61. virtual bool match(const generic::NSEC3& nsec3) const;
  62. virtual bool match(const generic::NSEC3PARAM& nsec3param) const;
  63. bool match(uint8_t algorithm, uint16_t iterations,
  64. const vector<uint8_t>& salt) const;
  65. private:
  66. const uint8_t algorithm_;
  67. const uint16_t iterations_;
  68. const vector<uint8_t> salt_;
  69. // The following members are placeholder of work place and don't hold
  70. // any state over multiple calls so can be mutable without breaking
  71. // constness.
  72. mutable SHA1Context sha1_ctx_;
  73. mutable vector<uint8_t> digest_;
  74. mutable OutputBuffer obuf_;
  75. };
  76. inline void
  77. iterateSHA1(SHA1Context* ctx, const uint8_t* input, size_t inlength,
  78. const uint8_t* salt, size_t saltlen,
  79. uint8_t output[SHA1_HASHSIZE])
  80. {
  81. SHA1Reset(ctx);
  82. SHA1Input(ctx, input, inlength);
  83. SHA1Input(ctx, salt, saltlen); // this works whether saltlen == or > 0
  84. SHA1Result(ctx, output);
  85. }
  86. string
  87. NSEC3HashRFC5155::calculate(const Name& name) const {
  88. // We first need to normalize the name by converting all upper case
  89. // characters in the labels to lower ones.
  90. obuf_.clear();
  91. Name name_copy(name);
  92. name_copy.downcase();
  93. name_copy.toWire(obuf_);
  94. const uint8_t saltlen = salt_.size();
  95. const uint8_t* const salt = (saltlen > 0) ? &salt_[0] : NULL;
  96. uint8_t* const digest = &digest_[0];
  97. assert(digest_.size() == SHA1_HASHSIZE);
  98. iterateSHA1(&sha1_ctx_, static_cast<const uint8_t*>(obuf_.getData()),
  99. obuf_.getLength(), salt, saltlen, digest);
  100. for (unsigned int n = 0; n < iterations_; ++n) {
  101. iterateSHA1(&sha1_ctx_, digest, SHA1_HASHSIZE, salt, saltlen, digest);
  102. }
  103. return (encodeBase32Hex(digest_));
  104. }
  105. bool
  106. NSEC3HashRFC5155::match(uint8_t algorithm, uint16_t iterations,
  107. const vector<uint8_t>& salt) const
  108. {
  109. return (algorithm_ == algorithm && iterations_ == iterations &&
  110. salt_.size() == salt.size() &&
  111. (salt_.empty() || memcmp(&salt_[0], &salt[0], salt_.size()) == 0));
  112. }
  113. bool
  114. NSEC3HashRFC5155::match(const generic::NSEC3& nsec3) const {
  115. return (match(nsec3.getHashalg(), nsec3.getIterations(),
  116. nsec3.getSalt()));
  117. }
  118. bool
  119. NSEC3HashRFC5155::match(const generic::NSEC3PARAM& nsec3param) const {
  120. return (match(nsec3param.getHashalg(), nsec3param.getIterations(),
  121. nsec3param.getSalt()));
  122. }
  123. // A static pointer that refers to the currently usable creator.
  124. // Only get/setNSEC3HashCreator are expected to get access to this variable
  125. // directly.
  126. const NSEC3HashCreator* creator;
  127. // The accessor to the current creator. If it's not explicitly set or has
  128. // been reset from a customized one, the default creator will be used.
  129. const NSEC3HashCreator*
  130. getNSEC3HashCreator() {
  131. static DefaultNSEC3HashCreator default_creator;
  132. if (creator == NULL) {
  133. creator = &default_creator;
  134. }
  135. return (creator);
  136. }
  137. } // end of unnamed namespace
  138. namespace isc {
  139. namespace dns {
  140. NSEC3Hash*
  141. NSEC3Hash::create(const generic::NSEC3PARAM& param) {
  142. return (getNSEC3HashCreator()->create(param));
  143. }
  144. NSEC3Hash*
  145. NSEC3Hash::create(const generic::NSEC3& nsec3) {
  146. return (getNSEC3HashCreator()->create(nsec3));
  147. }
  148. NSEC3Hash*
  149. DefaultNSEC3HashCreator::create(const generic::NSEC3PARAM& param) const {
  150. return (new NSEC3HashRFC5155(param.getHashalg(), param.getIterations(),
  151. param.getSalt()));
  152. }
  153. NSEC3Hash*
  154. DefaultNSEC3HashCreator::create(const generic::NSEC3& nsec3) const {
  155. return (new NSEC3HashRFC5155(nsec3.getHashalg(), nsec3.getIterations(),
  156. nsec3.getSalt()));
  157. }
  158. void
  159. setNSEC3HashCreator(const NSEC3HashCreator* new_creator) {
  160. creator = new_creator;
  161. }
  162. } // namespace dns
  163. } // namespace isc