Kea 2.2.0
nsec3hash.cc
Go to the documentation of this file.
1// Copyright (C) 2012-2015 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
7#include <config.h>
8
9#include <stdint.h>
10
11#include <cassert>
12#include <cstring>
13#include <cstdlib>
14#include <string>
15#include <vector>
16
17#include <boost/noncopyable.hpp>
18#include <boost/scoped_ptr.hpp>
19
21
22#include <util/buffer.h>
24
27
28#include <dns/name.h>
29#include <dns/labelsequence.h>
30#include <dns/nsec3hash.h>
31#include <dns/rdataclass.h>
32#include <dns/name_internal.h>
33
34using namespace std;
35using namespace isc::util;
36using namespace isc::util::encode;
37using namespace isc::cryptolink;
38using namespace isc::dns;
39using namespace isc::dns::rdata;
40
41namespace {
42
53class NSEC3HashRFC5155 : boost::noncopyable, public NSEC3Hash {
54private:
55 // This is the algorithm number for SHA1/NSEC3 as defined in RFC5155.
56 static const uint8_t NSEC3_HASH_SHA1 = 1;
57 // For digest_ allocation
58 static const size_t DEFAULT_DIGEST_LENGTH = 32;
59
60public:
61 NSEC3HashRFC5155(uint8_t algorithm, uint16_t iterations,
62 const uint8_t* salt_data, size_t salt_length) :
63 algorithm_(algorithm), iterations_(iterations),
64 salt_data_(NULL), salt_length_(salt_length),
65 digest_(DEFAULT_DIGEST_LENGTH), obuf_(Name::MAX_WIRE)
66 {
67 if (algorithm_ != NSEC3_HASH_SHA1) {
68 isc_throw(UnknownNSEC3HashAlgorithm, "Unknown NSEC3 algorithm: " <<
69 static_cast<unsigned int>(algorithm_));
70 }
71
72 if (salt_length > 0) {
73 salt_data_ = static_cast<uint8_t*>(std::malloc(salt_length));
74 if (salt_data_ == NULL) {
75 throw std::bad_alloc();
76 }
77 std::memcpy(salt_data_, salt_data, salt_length);
78 }
79 }
80
81 virtual ~NSEC3HashRFC5155() {
82 std::free(salt_data_);
83 }
84
85 virtual std::string calculate(const Name& name) const;
86 virtual std::string calculate(const LabelSequence& ls) const;
87
88 virtual bool match(const generic::NSEC3& nsec3) const;
89 virtual bool match(const generic::NSEC3PARAM& nsec3param) const;
90 bool match(uint8_t algorithm, uint16_t iterations,
91 const vector<uint8_t>& salt) const;
92
93private:
94 std::string calculateForWiredata(const uint8_t* data, size_t length) const;
95
96 const uint8_t algorithm_;
97 const uint16_t iterations_;
98 uint8_t* salt_data_;
99 const size_t salt_length_;
100
101 // The following members are placeholder of work place and don't hold
102 // any state over multiple calls so can be mutable without breaking
103 // constness.
104 mutable OutputBuffer digest_;
105 mutable vector<uint8_t> vdigest_;
106 mutable OutputBuffer obuf_;
107};
108
109inline void
110iterateSHA1(const uint8_t* input, size_t inlength,
111 const uint8_t* salt, size_t saltlen,
112 OutputBuffer& output)
113{
114 boost::scoped_ptr<Hash> hash(CryptoLink::getCryptoLink().createHash(SHA1));
115 hash->update(input, inlength);
116 hash->update(salt, saltlen); // this works whether saltlen == or > 0
117 hash->final(output, hash->getOutputLength());
118}
119
120string
121NSEC3HashRFC5155::calculateForWiredata(const uint8_t* data,
122 size_t length) const
123{
124 // We first need to normalize the name by converting all upper case
125 // characters in the labels to lower ones.
126
127 uint8_t name_buf[256];
128 assert(length < sizeof (name_buf));
129
130 const uint8_t *p1 = data;
131 uint8_t *p2 = name_buf;
132 while (*p1 != 0) {
133 char len = *p1;
134
135 *p2++ = *p1++;
136 while (len--) {
138 }
139 }
140
141 *p2 = *p1;
142
143 digest_.clear();
144 iterateSHA1(name_buf, length,
145 salt_data_, salt_length_, digest_);
146 const uint8_t* dgst_data = static_cast<const uint8_t*>(digest_.getData());
147 size_t dgst_len = digest_.getLength();
148 for (unsigned int n = 0; n < iterations_; ++n) {
149 digest_.clear();
150 iterateSHA1(dgst_data, dgst_len, salt_data_, salt_length_, digest_);
151 }
152
153 vdigest_.resize(dgst_len);
154 std::memcpy(&vdigest_[0], dgst_data, dgst_len);
155 return (encodeBase32Hex(vdigest_));
156}
157
158string
159NSEC3HashRFC5155::calculate(const Name& name) const {
160 obuf_.clear();
161 name.toWire(obuf_);
162
163 return (calculateForWiredata(static_cast<const uint8_t*>(obuf_.getData()),
164 obuf_.getLength()));
165}
166
167string
168NSEC3HashRFC5155::calculate(const LabelSequence& ls) const {
169 assert(ls.isAbsolute());
170
171 size_t length;
172 const uint8_t* data = ls.getData(&length);
173
174 return (calculateForWiredata(data, length));
175}
176
177bool
178NSEC3HashRFC5155::match(uint8_t algorithm, uint16_t iterations,
179 const vector<uint8_t>& salt) const
180{
181 return (algorithm_ == algorithm && iterations_ == iterations &&
182 salt_length_ == salt.size() &&
183 ((salt_length_ == 0) ||
184 memcmp(salt_data_, &salt[0], salt_length_) == 0));
185}
186
187bool
188NSEC3HashRFC5155::match(const generic::NSEC3& nsec3) const {
189 return (match(nsec3.getHashalg(), nsec3.getIterations(),
190 nsec3.getSalt()));
191}
192
193bool
194NSEC3HashRFC5155::match(const generic::NSEC3PARAM& nsec3param) const {
195 return (match(nsec3param.getHashalg(), nsec3param.getIterations(),
196 nsec3param.getSalt()));
197}
198
199// A static pointer that refers to the currently usable creator.
200// Only get/setNSEC3HashCreator are expected to get access to this variable
201// directly.
202const NSEC3HashCreator* creator;
203
204// The accessor to the current creator. If it's not explicitly set or has
205// been reset from a customized one, the default creator will be used.
206const NSEC3HashCreator*
207getNSEC3HashCreator() {
208 static DefaultNSEC3HashCreator default_creator;
209 if (creator == NULL) {
210 creator = &default_creator;
211 }
212 return (creator);
213}
214
215} // end of unnamed namespace
216
217namespace isc {
218namespace dns {
219
222 return (getNSEC3HashCreator()->create(param));
223}
224
227 return (getNSEC3HashCreator()->create(nsec3));
228}
229
231NSEC3Hash::create(uint8_t algorithm, uint16_t iterations,
232 const uint8_t* salt_data, size_t salt_length) {
233 return (getNSEC3HashCreator()->create(algorithm, iterations,
234 salt_data, salt_length));
235}
236
239 const vector<uint8_t>& salt = param.getSalt();
240 return (new NSEC3HashRFC5155(param.getHashalg(), param.getIterations(),
241 salt.empty() ? NULL : &salt[0],
242 salt.size()));
243}
244
247 const vector<uint8_t>& salt = nsec3.getSalt();
248 return (new NSEC3HashRFC5155(nsec3.getHashalg(), nsec3.getIterations(),
249 salt.empty() ? NULL : &salt[0],
250 salt.size()));
251}
252
254DefaultNSEC3HashCreator::create(uint8_t algorithm, uint16_t iterations,
255 const uint8_t* salt_data,
256 size_t salt_length) const
257{
258 return (new NSEC3HashRFC5155(algorithm, iterations,
259 salt_data, salt_length));
260}
261
262void
264 creator = new_creator;
265}
266
267} // namespace dns
268} // namespace isc
The default NSEC3Hash creator.
Definition: nsec3hash.h:258
virtual NSEC3Hash * create(const rdata::generic::NSEC3PARAM &param) const
Factory method of NSECHash from NSEC3PARAM RDATA.
Definition: nsec3hash.cc:238
Light-weight Accessor to Name data.
Definition: labelsequence.h:35
bool isAbsolute() const
Checks whether the label sequence is absolute.
const uint8_t * getData(size_t *len) const
Return the wire-format data for this LabelSequence.
Factory class of NSEC3Hash.
Definition: nsec3hash.h:203
A calculator of NSEC3 hashes.
Definition: nsec3hash.h:74
virtual bool match(const rdata::generic::NSEC3 &nsec3) const =0
Match given NSEC3 parameters with that of the hash.
virtual std::string calculate(const Name &name) const =0
Calculate the NSEC3 hash (Name variant).
static NSEC3Hash * create(const rdata::generic::NSEC3PARAM &param)
Factory method of NSECHash from NSEC3PARAM RDATA.
Definition: nsec3hash.cc:221
The Name class encapsulates DNS names.
Definition: name.h:223
void toWire(AbstractMessageRenderer &renderer) const
Render the Name in the wire format with compression.
Definition: name.cc:502
An exception that is thrown for when an NSEC3Hash object is constructed with an unknown hash algorith...
Definition: nsec3hash.h:33
const std::vector< uint8_t > & getSalt() const
uint8_t getHashalg() const
Specialized methods.
const std::vector< uint8_t > & getSalt() const
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
Definition: buffer.h:294
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
const uint8_t maptolower[]
Definition: name.cc:73
void setNSEC3HashCreator(const NSEC3HashCreator *new_creator)
The registrar of NSEC3HashCreator.
Definition: nsec3hash.cc:263
std::string encodeBase32Hex(const std::vector< uint8_t > &binary)
Encode binary data in the base32hex format.
Definition: base_n.cc:459
Definition: edns.h:19
Defines the logger used by the top-level component of kea-lfc.