BIND 10 trac2218_2, updated. 5b6cccfc2e34d0319e8c5358391de6fe9a5dcdf4 [2218] Remove NSEC3CalculateFn in InMemoryZoneFinder

BIND 10 source code commits bind10-changes at lists.isc.org
Mon Sep 24 21:56:10 UTC 2012


The branch, trac2218_2 has been updated
       via  5b6cccfc2e34d0319e8c5358391de6fe9a5dcdf4 (commit)
       via  56a18b6b8dc444efeec0052eefc4539633e9a762 (commit)
      from  25a4afa2395d6d9263b385a73cec2919c4a21830 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 5b6cccfc2e34d0319e8c5358391de6fe9a5dcdf4
Author: Mukund Sivaraman <muks at isc.org>
Date:   Tue Sep 25 03:25:05 2012 +0530

    [2218] Remove NSEC3CalculateFn in InMemoryZoneFinder
    
    Instead, use the facilities provided by isc::dns::NSEC3Hash and
    the TestNSEC3HashCreator in fake_nsec3.cc.

commit 56a18b6b8dc444efeec0052eefc4539633e9a762
Author: Mukund Sivaraman <muks at isc.org>
Date:   Tue Sep 25 02:50:41 2012 +0530

    [2218] Add a NSEC3Hash::create() variant to take hash params as args

-----------------------------------------------------------------------

Summary of changes:
 .../datasrc/memory/tests/zone_finder_unittest.cc   |   52 ++---------
 src/lib/datasrc/memory/zone_finder.cc              |   14 +--
 src/lib/datasrc/memory/zone_finder.h               |   17 +---
 src/lib/datasrc/tests/faked_nsec3.cc               |   59 ++++++-------
 src/lib/datasrc/tests/faked_nsec3.h                |   12 +--
 src/lib/datasrc/tests/memory_datasrc_unittest.cc   |    5 ++
 src/lib/dns/nsec3hash.cc                           |   93 +++++++++++---------
 src/lib/dns/nsec3hash.h                            |   27 ++++--
 src/lib/dns/tests/nsec3hash_unittest.cc            |   28 +++++-
 9 files changed, 150 insertions(+), 157 deletions(-)

-----------------------------------------------------------------------
diff --git a/src/lib/datasrc/memory/tests/zone_finder_unittest.cc b/src/lib/datasrc/memory/tests/zone_finder_unittest.cc
index 83c63a8..43115b2 100644
--- a/src/lib/datasrc/memory/tests/zone_finder_unittest.cc
+++ b/src/lib/datasrc/memory/tests/zone_finder_unittest.cc
@@ -48,48 +48,6 @@ namespace {
 using result::SUCCESS;
 using result::EXIST;
 
-// Proxy accessor for faked NSEC3 mapping for tests.  map isn't a trivial
-// type, so it's safer to get access to it via a proxy to avoid initialization
-// fiasco.
-NSEC3HashMap&
-getNSEC3HashMap() {
-    static NSEC3HashMap nsec3_hash_map;
-    return (nsec3_hash_map);
-}
-
-// A faked NSEC3 hash calculator for convenience. Tests that need to use
-// the faked hashed values should call setFakeNSEC3Calculate() on the
-// MyZoneFinder object at the beginning of the test (at least before
-// adding any NSEC3/NSEC3PARAM RR).
-std::string
-fakeNSEC3Calculate(const Name& name,
-                   const uint16_t,
-                   const uint8_t*,
-                   size_t)
-{
-    const NSEC3HashMap::const_iterator found = getNSEC3HashMap().find(name);
-    if (found != getNSEC3HashMap().end()) {
-        return (found->second);
-    }
-
-    isc_throw(isc::Unexpected,
-              "unexpected name for NSEC3 test: " << name);
-}
-
-class MyZoneFinder : public memory::InMemoryZoneFinder {
-public:
-    MyZoneFinder(const ZoneData& zone_data,
-                 const isc::dns::RRClass& rrclass) :
-         memory::InMemoryZoneFinder(zone_data, rrclass)
-    {
-        buildFakeNSEC3Map(getNSEC3HashMap());
-    }
-
-    void setFakeNSEC3Calculate() {
-        nsec3_calculate_ = fakeNSEC3Calculate;
-    }
-};
-
 /// \brief expensive rrset converter
 ///
 /// converts any specialized rrset (which may not have implemented some
@@ -362,7 +320,7 @@ public:
     // The zone finder to torture by tests
     MemorySegmentTest mem_sgmt_;
     memory::ZoneData* zone_data_;
-    MyZoneFinder zone_finder_;
+    memory::InMemoryZoneFinder zone_finder_;
     isc::datasrc::memory::RdataEncoder encoder_;
 
     // Placeholder for storing RRsets to be checked with rrsetsCheck()
@@ -1465,7 +1423,8 @@ TEST_F(InMemoryZoneFinderTest, cancelWildcardNSEC) {
 
 TEST_F(InMemoryZoneFinderTest, findNSEC3ForBadZone) {
     // Set up the faked hash calculator.
-    zone_finder_.setFakeNSEC3Calculate();
+    const TestNSEC3HashCreator creator;
+    setNSEC3HashCreator(&creator);
 
     // If the zone has nothing about NSEC3 (neither NSEC3 or NSEC3PARAM),
     // findNSEC3() should be rejected.
@@ -1492,7 +1451,7 @@ class InMemoryZoneFinderNSEC3Test : public InMemoryZoneFinderTest {
 public:
     InMemoryZoneFinderNSEC3Test() {
         // Set up the faked hash calculator.
-        zone_finder_.setFakeNSEC3Calculate();
+        setNSEC3HashCreator(&creator_);
 
         // Add a few NSEC3 records:
         // apex (example.org.): hash=0P..
@@ -1512,6 +1471,9 @@ public:
             string(nsec3_common);
         addZoneData(textToRRset(zzz_nsec3_text));
     }
+
+private:
+    const TestNSEC3HashCreator creator_;
 };
 
 TEST_F(InMemoryZoneFinderNSEC3Test, findNSEC3) {
diff --git a/src/lib/datasrc/memory/zone_finder.cc b/src/lib/datasrc/memory/zone_finder.cc
index ad886a2..55dec20 100644
--- a/src/lib/datasrc/memory/zone_finder.cc
+++ b/src/lib/datasrc/memory/zone_finder.cc
@@ -22,6 +22,7 @@
 #include <dns/name.h>
 #include <dns/rrset.h>
 #include <dns/rrtype.h>
+#include <dns/nsec3hash.h>
 
 #include <datasrc/logger.h>
 
@@ -652,13 +653,16 @@ InMemoryZoneFinder::findNSEC3(const isc::dns::Name& name, bool recursive) {
     // the deepest label one by one, until we find a name that has a matching
     // NSEC3 hash.
     for (unsigned int labels = qlabels; labels >= olabels; --labels) {
+        const std::vector<uint8_t> salt(nsec3_data->getSaltData(),
+                                        (nsec3_data->getSaltData() +
+                                         nsec3_data->getSaltLen()));
+        const std::auto_ptr<NSEC3Hash> hash
+            (NSEC3Hash::create(nsec3_data->hashalg,
+                               nsec3_data->iterations,
+                               salt));
         const Name& hname = (labels == qlabels ?
                              name : name.split(qlabels - labels, labels));
-        const std::string hlabel =
-            (nsec3_calculate_) (hname,
-                                nsec3_data->iterations,
-                                nsec3_data->getSaltData(),
-                                nsec3_data->getSaltLen());
+        const std::string hlabel = hash->calculate(hname);
 
         LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_MEM_FINDNSEC3_TRYHASH).
             arg(name).arg(labels).arg(hlabel);
diff --git a/src/lib/datasrc/memory/zone_finder.h b/src/lib/datasrc/memory/zone_finder.h
index f508a25..201d3e8 100644
--- a/src/lib/datasrc/memory/zone_finder.h
+++ b/src/lib/datasrc/memory/zone_finder.h
@@ -22,7 +22,6 @@
 #include <dns/name.h>
 #include <dns/rrset.h>
 #include <dns/rrtype.h>
-#include <dns/nsec3hash.h>
 
 #include <string>
 
@@ -51,12 +50,6 @@ public:
     const ZoneNode* const found_node;
 };
 
-std::string
-InMemoryZoneFinderNSEC3Calculate(const isc::dns::Name& name,
-                                 const uint16_t iterations,
-                                 const uint8_t* salt,
-                                 size_t salt_len);
-
 /// A derived zone finder class intended to be used with the memory data
 /// source, using ZoneData for its contents.
 class InMemoryZoneFinder : boost::noncopyable, public ZoneFinder {
@@ -75,8 +68,7 @@ public:
     InMemoryZoneFinder(const ZoneData& zone_data,
                        const isc::dns::RRClass& rrclass) :
         zone_data_(zone_data),
-        rrclass_(rrclass),
-        nsec3_calculate_(isc::dns::NSEC3Hash::calculate)
+        rrclass_(rrclass)
     {}
 
     /// \brief Find an RRset in the datasource
@@ -128,13 +120,6 @@ private:
 
     const ZoneData& zone_data_;
     const isc::dns::RRClass& rrclass_;
-
-protected:
-    typedef std::string (NSEC3CalculateFn) (const isc::dns::Name& name,
-                                            const uint16_t iterations,
-                                            const uint8_t* salt,
-                                            size_t salt_len);
-    NSEC3CalculateFn* nsec3_calculate_;
 };
 
 } // namespace memory
diff --git a/src/lib/datasrc/tests/faked_nsec3.cc b/src/lib/datasrc/tests/faked_nsec3.cc
index 7f17fca..382c934 100644
--- a/src/lib/datasrc/tests/faked_nsec3.cc
+++ b/src/lib/datasrc/tests/faked_nsec3.cc
@@ -53,7 +53,31 @@ private:
     NSEC3HashMap map_;
 public:
     TestNSEC3Hash() {
-        buildFakeNSEC3Map(map_);
+        // Build pre-defined hash
+        map_[Name("example.org")] = apex_hash;
+        map_[Name("www.example.org")] = "2S9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM";
+        map_[Name("xxx.example.org")] = "Q09MHAVEQVM6T7VBL5LOP2U3T2RP3TOM";
+        map_[Name("yyy.example.org")] = "0A9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM";
+        map_[Name("x.y.w.example.org")] =
+            "2VPTU5TIMAMQTTGL4LUU9KG21E0AOR3S";
+        map_[Name("y.w.example.org")] = "K8UDEMVP1J2F7EG6JEBPS17VP3N8I58H";
+        map_[Name("w.example.org")] = w_hash;
+        map_[Name("zzz.example.org")] = zzz_hash;
+        map_[Name("smallest.example.org")] =
+            "00000000000000000000000000000000";
+        map_[Name("largest.example.org")] =
+            "UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU";
+
+        // These are used by the findNSEC3Walk test.
+        map_[Name("n0.example.org")] = "00000000000000000000000000000000";
+        map_[Name("n1.example.org")] = "01UDEMVP1J2F7EG6JEBPS17VP3N8I58H";
+        map_[Name("n2.example.org")] = "02UDEMVP1J2F7EG6JEBPS17VP3N8I58H";
+        map_[Name("n3.example.org")] = "0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM";
+        map_[Name("n4.example.org")] = "11111111111111111111111111111111";
+        map_[Name("n5.example.org")] = "2T7B4G4VSA5SMI47K61MV5BV1A22BOJR";
+        map_[Name("n6.example.org")] = "44444444444444444444444444444444";
+        map_[Name("n7.example.org")] = "R53BQ7CC2UVMUBFU5OCMM6PERS9TK9EN";
+        map_[Name("n8.example.org")] = "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
     }
     virtual string calculate(const Name& name) const {
         const NSEC3HashMap::const_iterator found = map_.find(name);
@@ -81,35 +105,10 @@ NSEC3Hash* TestNSEC3HashCreator::create(const rdata::generic::NSEC3&) const {
     return (new TestNSEC3Hash);
 }
 
-void
-buildFakeNSEC3Map(NSEC3HashMap& fmap)
-{
-    // Build pre-defined hash
-    fmap.clear();
-    fmap[Name("example.org")] = apex_hash;
-    fmap[Name("www.example.org")] = "2S9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM";
-    fmap[Name("xxx.example.org")] = "Q09MHAVEQVM6T7VBL5LOP2U3T2RP3TOM";
-    fmap[Name("yyy.example.org")] = "0A9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM";
-    fmap[Name("x.y.w.example.org")] =
-        "2VPTU5TIMAMQTTGL4LUU9KG21E0AOR3S";
-    fmap[Name("y.w.example.org")] = "K8UDEMVP1J2F7EG6JEBPS17VP3N8I58H";
-    fmap[Name("w.example.org")] = w_hash;
-    fmap[Name("zzz.example.org")] = zzz_hash;
-    fmap[Name("smallest.example.org")] =
-         "00000000000000000000000000000000";
-    fmap[Name("largest.example.org")] =
-         "UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU";
-
-    // These are used by the findNSEC3Walk test.
-    fmap[Name("n0.example.org")] = "00000000000000000000000000000000";
-    fmap[Name("n1.example.org")] = "01UDEMVP1J2F7EG6JEBPS17VP3N8I58H";
-    fmap[Name("n2.example.org")] = "02UDEMVP1J2F7EG6JEBPS17VP3N8I58H";
-    fmap[Name("n3.example.org")] = "0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM";
-    fmap[Name("n4.example.org")] = "11111111111111111111111111111111";
-    fmap[Name("n5.example.org")] = "2T7B4G4VSA5SMI47K61MV5BV1A22BOJR";
-    fmap[Name("n6.example.org")] = "44444444444444444444444444444444";
-    fmap[Name("n7.example.org")] = "R53BQ7CC2UVMUBFU5OCMM6PERS9TK9EN";
-    fmap[Name("n8.example.org")] = "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
+NSEC3Hash*
+TestNSEC3HashCreator::create(uint8_t, uint16_t,
+                             const vector<uint8_t>&) const {
+    return (new TestNSEC3Hash);
 }
 
 void
diff --git a/src/lib/datasrc/tests/faked_nsec3.h b/src/lib/datasrc/tests/faked_nsec3.h
index 1552c79..bb97f18 100644
--- a/src/lib/datasrc/tests/faked_nsec3.h
+++ b/src/lib/datasrc/tests/faked_nsec3.h
@@ -18,11 +18,9 @@
 #include <datasrc/zone.h>
 
 #include <dns/nsec3hash.h>
-#include <dns/name.h>
 
 #include <stdint.h>
 #include <string>
-#include <map>
 
 namespace isc {
 namespace datasrc {
@@ -64,15 +62,11 @@ public:
         const;
     virtual isc::dns::NSEC3Hash* create(const isc::dns::rdata::generic::NSEC3&)
         const;
+    virtual isc::dns::NSEC3Hash* create(uint8_t algorithm, uint16_t iterations,
+					const std::vector<uint8_t>& salt)
+        const;
 };
 
-typedef std::map<isc::dns::Name, std::string> NSEC3HashMap;
-typedef NSEC3HashMap::value_type NSEC3HashPair;
-
-// Build the test map with the fake NSEC3 hashes.
-void
-buildFakeNSEC3Map(NSEC3HashMap& fmap);
-
 // Check the result against expected values. It directly calls EXPECT_ macros
 void
 findNSEC3Check(bool expected_matched, uint8_t expected_labels,
diff --git a/src/lib/datasrc/tests/memory_datasrc_unittest.cc b/src/lib/datasrc/tests/memory_datasrc_unittest.cc
index fcdca16..f0a0c78 100644
--- a/src/lib/datasrc/tests/memory_datasrc_unittest.cc
+++ b/src/lib/datasrc/tests/memory_datasrc_unittest.cc
@@ -357,6 +357,11 @@ public:
     virtual NSEC3Hash* create(const generic::NSEC3&) const {
         return (new TestNSEC3Hash);
     }
+    virtual NSEC3Hash* create(uint8_t, uint16_t,
+                              const vector<uint8_t>&) const {
+    return (new TestNSEC3Hash);
+}
+
 };
 
 /// \brief Test fixture for the InMemoryZoneFinder class
diff --git a/src/lib/dns/nsec3hash.cc b/src/lib/dns/nsec3hash.cc
index d6f40dd..5dc59b7 100644
--- a/src/lib/dns/nsec3hash.cc
+++ b/src/lib/dns/nsec3hash.cc
@@ -40,17 +40,6 @@ using namespace isc::dns::rdata;
 
 namespace {
 
-inline void
-iterateSHA1(SHA1Context* ctx, const uint8_t* input, size_t inlength,
-            const uint8_t* salt, size_t saltlen,
-            uint8_t output[SHA1_HASHSIZE])
-{
-    SHA1Reset(ctx);
-    SHA1Input(ctx, input, inlength);
-    SHA1Input(ctx, salt, saltlen); // this works whether saltlen == or > 0
-    SHA1Result(ctx, output);
-}
-
 /// \brief A derived class of \c NSEC3Hash that implements the standard hash
 /// calculation specified in RFC5155.
 ///
@@ -70,12 +59,13 @@ public:
     NSEC3HashRFC5155(uint8_t algorithm, uint16_t iterations,
                      const vector<uint8_t>& salt) :
         algorithm_(algorithm), iterations_(iterations),
-        salt_(salt)
+        salt_(salt), digest_(SHA1_HASHSIZE), obuf_(Name::MAX_WIRE)
     {
         if (algorithm_ != NSEC3_HASH_SHA1) {
             isc_throw(UnknownNSEC3HashAlgorithm, "Unknown NSEC3 algorithm: " <<
                       static_cast<unsigned int>(algorithm_));
         }
+        SHA1Reset(&sha1_ctx_);
     }
 
     virtual std::string calculate(const Name& name) const;
@@ -89,11 +79,47 @@ private:
     const uint8_t algorithm_;
     const uint16_t iterations_;
     const vector<uint8_t> salt_;
+
+    // The following members are placeholder of work place and don't hold
+    // any state over multiple calls so can be mutable without breaking
+    // constness.
+    mutable SHA1Context sha1_ctx_;
+    mutable vector<uint8_t> digest_;
+    mutable OutputBuffer obuf_;
 };
 
+inline void
+iterateSHA1(SHA1Context* ctx, const uint8_t* input, size_t inlength,
+            const uint8_t* salt, size_t saltlen,
+            uint8_t output[SHA1_HASHSIZE])
+{
+    SHA1Reset(ctx);
+    SHA1Input(ctx, input, inlength);
+    SHA1Input(ctx, salt, saltlen); // this works whether saltlen == or > 0
+    SHA1Result(ctx, output);
+}
+
 string
 NSEC3HashRFC5155::calculate(const Name& name) const {
-    return (NSEC3Hash::calculate(name, iterations_, &salt_[0], salt_.size()));
+    // We first need to normalize the name by converting all upper case
+    // characters in the labels to lower ones.
+    obuf_.clear();
+    Name name_copy(name);
+    name_copy.downcase();
+    name_copy.toWire(obuf_);
+
+    const uint8_t saltlen = salt_.size();
+    const uint8_t* const salt = (saltlen > 0) ? &salt_[0] : NULL;
+    uint8_t* const digest = &digest_[0];
+    assert(digest_.size() == SHA1_HASHSIZE);
+
+    iterateSHA1(&sha1_ctx_, static_cast<const uint8_t*>(obuf_.getData()),
+                obuf_.getLength(), salt, saltlen, digest);
+    for (unsigned int n = 0; n < iterations_; ++n) {
+        iterateSHA1(&sha1_ctx_, digest, SHA1_HASHSIZE, salt, saltlen, digest);
+    }
+
+    return (encodeBase32Hex(digest_));
 }
 
 bool
@@ -149,6 +175,12 @@ NSEC3Hash::create(const generic::NSEC3& nsec3) {
 }
 
 NSEC3Hash*
+NSEC3Hash::create(uint8_t algorithm, uint16_t iterations,
+                  const vector<uint8_t>& salt) {
+    return (getNSEC3HashCreator()->create(algorithm, iterations, salt));
+}
+
+NSEC3Hash*
 DefaultNSEC3HashCreator::create(const generic::NSEC3PARAM& param) const {
     return (new NSEC3HashRFC5155(param.getHashalg(), param.getIterations(),
                                  param.getSalt()));
@@ -160,39 +192,16 @@ DefaultNSEC3HashCreator::create(const generic::NSEC3& nsec3) const {
                                  nsec3.getSalt()));
 }
 
+NSEC3Hash*
+DefaultNSEC3HashCreator::create(uint8_t algorithm, uint16_t iterations,
+                                const vector<uint8_t>& salt) const {
+    return (new NSEC3HashRFC5155(algorithm, iterations, salt));
+}
+
 void
 setNSEC3HashCreator(const NSEC3HashCreator* new_creator) {
     creator = new_creator;
 }
 
-std::string
-NSEC3Hash::calculate(const Name& name,
-                     const uint16_t iterations,
-                     const uint8_t* salt,
-                     size_t salt_len)
-{
-    // We first need to normalize the name by converting all upper case
-    // characters in the labels to lower ones.
-    OutputBuffer obuf(Name::MAX_WIRE);
-    Name name_copy(name);
-    name_copy.downcase();
-    name_copy.toWire(obuf);
-
-    const uint8_t* const salt_buf = (salt_len > 0) ? salt : NULL;
-    std::vector<uint8_t> digest(SHA1_HASHSIZE);
-    uint8_t* const digest_buf = &digest[0];
-
-    SHA1Context sha1_ctx;
-    iterateSHA1(&sha1_ctx, static_cast<const uint8_t*>(obuf.getData()),
-                obuf.getLength(), salt_buf, salt_len, digest_buf);
-    for (unsigned int n = 0; n < iterations; ++n) {
-        iterateSHA1(&sha1_ctx, digest_buf, SHA1_HASHSIZE,
-                    salt_buf, salt_len,
-                    digest_buf);
-    }
-
-    return (encodeBase32Hex(digest));
-}
-
 } // namespace dns
 } // namespace isc
diff --git a/src/lib/dns/nsec3hash.h b/src/lib/dns/nsec3hash.h
index 35b7b30..357f4e7 100644
--- a/src/lib/dns/nsec3hash.h
+++ b/src/lib/dns/nsec3hash.h
@@ -16,6 +16,7 @@
 #define __NSEC3HASH_H 1
 
 #include <string>
+#include <vector>
 #include <stdint.h>
 #include <exceptions/exceptions.h>
 
@@ -115,6 +116,13 @@ public:
     /// for hash calculation from an NSEC3 RDATA object.
     static NSEC3Hash* create(const rdata::generic::NSEC3& nsec3);
 
+    /// \brief Factory method of NSECHash from args.
+    ///
+    /// This is similar to the other version, but uses the arguments
+    /// passed as the parameters for hash calculation.
+    static NSEC3Hash* create(uint8_t algorithm, uint16_t iterations,
+			     const std::vector<uint8_t>& salt);
+
     /// \brief The destructor.
     virtual ~NSEC3Hash() {}
 
@@ -131,15 +139,6 @@ public:
     /// \return Base32hex-encoded string of the hash value.
     virtual std::string calculate(const Name& name) const = 0;
 
-    /// \brief Calculate the NSEC3 SHA-1 hash.
-    ///
-    /// This method calculates the NSEC3 hash value for the given
-    /// \c name and hash parameters. It assumes the SHA-1 algorithm.
-    static std::string calculate(const Name& name,
-                                 const uint16_t iterations,
-                                 const uint8_t* salt,
-                                 size_t salt_len);
-
     /// \brief Match given NSEC3 parameters with that of the hash.
     ///
     /// This method compares NSEC3 parameters used for hash calculation
@@ -219,6 +218,14 @@ public:
     /// <code>NSEC3Hash::create(const rdata::generic::NSEC3& param)</code>
     virtual NSEC3Hash* create(const rdata::generic::NSEC3& nsec3)
         const = 0;
+
+    /// \brief Factory method of NSECHash from args.
+    ///
+    /// See
+    /// <code>NSEC3Hash::create(const rdata::generic::NSEC3& param)</code>
+    virtual NSEC3Hash* create(uint8_t algorithm, uint16_t iterations,
+			      const std::vector<uint8_t>& salt)
+        const = 0;
 };
 
 /// \brief The default NSEC3Hash creator.
@@ -234,6 +241,8 @@ class DefaultNSEC3HashCreator : public NSEC3HashCreator {
 public:
     virtual NSEC3Hash* create(const rdata::generic::NSEC3PARAM& param) const;
     virtual NSEC3Hash* create(const rdata::generic::NSEC3& nsec3) const;
+    virtual NSEC3Hash* create(uint8_t algorithm, uint16_t iterations,
+			      const std::vector<uint8_t>& salt) const;
 };
 
 /// \brief The registrar of \c NSEC3HashCreator.
diff --git a/src/lib/dns/tests/nsec3hash_unittest.cc b/src/lib/dns/tests/nsec3hash_unittest.cc
index e607c74..b27c1f0 100644
--- a/src/lib/dns/tests/nsec3hash_unittest.cc
+++ b/src/lib/dns/tests/nsec3hash_unittest.cc
@@ -20,11 +20,14 @@
 
 #include <dns/nsec3hash.h>
 #include <dns/rdataclass.h>
+#include <util/encode/hex.h>
 
 using boost::scoped_ptr;
 using namespace std;
 using namespace isc::dns;
 using namespace isc::dns::rdata;
+using namespace isc::util;
+using namespace isc::util::encode;
 
 namespace {
 typedef scoped_ptr<NSEC3Hash> NSEC3HashPtr;
@@ -39,7 +42,12 @@ protected:
         test_hash_nsec3(NSEC3Hash::create(generic::NSEC3
                                           ("1 0 12 aabbccdd " +
                                            string(nsec3_common))))
-    {}
+    {
+        std::string salt_hex("aabbccdd");
+        std::vector<uint8_t> salt;
+        decodeHex(salt_hex, salt);
+        test_hash_args.reset(NSEC3Hash::create(1, 12, salt));
+    }
 
     ~NSEC3HashTest() {
         // Make sure we reset the hash creator to the default
@@ -53,6 +61,9 @@ protected:
 
     // Similar to test_hash, but created from NSEC3 RR.
     NSEC3HashPtr test_hash_nsec3;
+
+    // Similar to test_hash, but created from passed args.
+    NSEC3HashPtr test_hash_args;
 };
 
 TEST_F(NSEC3HashTest, unknownAlgorithm) {
@@ -65,6 +76,12 @@ TEST_F(NSEC3HashTest, unknownAlgorithm) {
                          generic::NSEC3("2 0 12 aabbccdd " +
                                         string(nsec3_common)))),
                      UnknownNSEC3HashAlgorithm);
+
+    std::string salt_hex("aabbccdd");
+    std::vector<uint8_t> salt;
+    decodeHex(salt_hex, salt);
+    EXPECT_THROW(NSEC3HashPtr(NSEC3Hash::create(2, 12, salt)),
+                 UnknownNSEC3HashAlgorithm);
 }
 
 // Common checks for NSEC3 hash calculation
@@ -90,6 +107,10 @@ TEST_F(NSEC3HashTest, calculate) {
         SCOPED_TRACE("calculate check with NSEC3 based hash");
         calculateCheck(*test_hash_nsec3);
     }
+    {
+        SCOPED_TRACE("calculate check with args based hash");
+        calculateCheck(*test_hash_args);
+    }
 
     // Some boundary cases: 0-iteration and empty salt.  Borrowed from the
     // .com zone data.
@@ -177,6 +198,11 @@ public:
         }
         return (new TestNSEC3Hash);
     }
+    virtual NSEC3Hash* create(uint8_t, uint16_t,
+                              const std::vector<uint8_t>&) const {
+        isc_throw(isc::Unexpected,
+                  "This method is not implemented here.");
+    }
 private:
     DefaultNSEC3HashCreator default_creator_;
 };



More information about the bind10-changes mailing list