Kea 2.5.7
nsec3hash.cc
Go to the documentation of this file.
1// Copyright (C) 2012-2024 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>
23#include <util/encode/encode.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 if (algorithm_ != NSEC3_HASH_SHA1) {
67 isc_throw(UnknownNSEC3HashAlgorithm, "Unknown NSEC3 algorithm: " <<
68 static_cast<unsigned int>(algorithm_));
69 }
70
71 if (salt_length > 0) {
72 if (salt_data == NULL) {
73 isc_throw(isc::BadValue, "salt data is NULL");
74 }
75 salt_data_ = static_cast<uint8_t*>(std::malloc(salt_length));
76 if (salt_data_ == NULL) {
77 throw std::bad_alloc();
78 }
79 std::memcpy(salt_data_, salt_data, salt_length);
80 }
81 }
82
83 virtual ~NSEC3HashRFC5155() {
84 std::free(salt_data_);
85 }
86
87 virtual std::string calculate(const Name& name) const;
88 virtual std::string calculate(const LabelSequence& ls) const;
89
90 virtual bool match(const generic::NSEC3& nsec3) const;
91 virtual bool match(const generic::NSEC3PARAM& nsec3param) const;
92 bool match(uint8_t algorithm, uint16_t iterations,
93 const vector<uint8_t>& salt) const;
94
95private:
96 std::string calculateForWiredata(const uint8_t* data, size_t length) const;
97
98 const uint8_t algorithm_;
99 const uint16_t iterations_;
100 uint8_t* salt_data_;
101 const size_t salt_length_;
102
103 // The following members are placeholder of work place and don't hold
104 // any state over multiple calls so can be mutable without breaking
105 // constness.
106 mutable OutputBuffer digest_;
107 mutable vector<uint8_t> vdigest_;
108 mutable OutputBuffer obuf_;
109};
110
111inline void
112iterateSHA1(const uint8_t* input, size_t inlength,
113 const uint8_t* salt, size_t saltlen,
114 OutputBuffer& output)
115{
116 boost::scoped_ptr<Hash> hash(CryptoLink::getCryptoLink().createHash(SHA1));
117 hash->update(input, inlength);
118 hash->update(salt, saltlen); // this works whether saltlen == or > 0
119 hash->final(output, hash->getOutputLength());
120}
121
122string
123NSEC3HashRFC5155::calculateForWiredata(const uint8_t* data,
124 size_t length) const
125{
126 // We first need to normalize the name by converting all upper case
127 // characters in the labels to lower ones.
128
129 uint8_t name_buf[256];
130 assert(length < sizeof (name_buf));
131
132 const uint8_t *p1 = data;
133 uint8_t *p2 = name_buf;
134 while (*p1 != 0) {
135 char len = *p1;
136
137 *p2++ = *p1++;
138 while (len--) {
140 }
141 }
142
143 *p2 = *p1;
144
145 digest_.clear();
146 iterateSHA1(name_buf, length,
147 salt_data_, salt_length_, digest_);
148 const uint8_t* dgst_data = static_cast<const uint8_t*>(digest_.getData());
149 size_t dgst_len = digest_.getLength();
150 for (unsigned int n = 0; n < iterations_; ++n) {
151 digest_.clear();
152 iterateSHA1(dgst_data, dgst_len, salt_data_, salt_length_, digest_);
153 }
154
155 vdigest_.resize(dgst_len);
156 std::memcpy(&vdigest_[0], dgst_data, dgst_len);
157 return (encodeBase32Hex(vdigest_));
158}
159
160string
161NSEC3HashRFC5155::calculate(const Name& name) const {
162 obuf_.clear();
163 name.toWire(obuf_);
164
165 return (calculateForWiredata(static_cast<const uint8_t*>(obuf_.getData()),
166 obuf_.getLength()));
167}
168
169string
170NSEC3HashRFC5155::calculate(const LabelSequence& ls) const {
171 assert(ls.isAbsolute());
172
173 size_t length;
174 const uint8_t* data = ls.getData(&length);
175
176 return (calculateForWiredata(data, length));
177}
178
179bool
180NSEC3HashRFC5155::match(uint8_t algorithm, uint16_t iterations,
181 const vector<uint8_t>& salt) const
182{
183 return (algorithm_ == algorithm && iterations_ == iterations &&
184 salt_length_ == salt.size() &&
185 ((salt_length_ == 0) ||
186 memcmp(salt_data_, &salt[0], salt_length_) == 0));
187}
188
189bool
190NSEC3HashRFC5155::match(const generic::NSEC3& nsec3) const {
191 return (match(nsec3.getHashalg(), nsec3.getIterations(),
192 nsec3.getSalt()));
193}
194
195bool
196NSEC3HashRFC5155::match(const generic::NSEC3PARAM& nsec3param) const {
197 return (match(nsec3param.getHashalg(), nsec3param.getIterations(),
198 nsec3param.getSalt()));
199}
200
201// A static pointer that refers to the currently usable creator.
202// Only get/setNSEC3HashCreator are expected to get access to this variable
203// directly.
204const NSEC3HashCreator* creator;
205
206// The accessor to the current creator. If it's not explicitly set or has
207// been reset from a customized one, the default creator will be used.
208const NSEC3HashCreator*
209getNSEC3HashCreator() {
210 static DefaultNSEC3HashCreator default_creator;
211 if (creator == NULL) {
212 creator = &default_creator;
213 }
214 return (creator);
215}
216
217} // end of unnamed namespace
218
219namespace isc {
220namespace dns {
221
224 return (getNSEC3HashCreator()->create(param));
225}
226
229 return (getNSEC3HashCreator()->create(nsec3));
230}
231
233NSEC3Hash::create(uint8_t algorithm, uint16_t iterations,
234 const uint8_t* salt_data, size_t salt_length) {
235 return (getNSEC3HashCreator()->create(algorithm, iterations,
236 salt_data, salt_length));
237}
238
241 const vector<uint8_t>& salt = param.getSalt();
242 return (new NSEC3HashRFC5155(param.getHashalg(), param.getIterations(),
243 salt.empty() ? NULL : &salt[0],
244 salt.size()));
245}
246
249 const vector<uint8_t>& salt = nsec3.getSalt();
250 return (new NSEC3HashRFC5155(nsec3.getHashalg(), nsec3.getIterations(),
251 salt.empty() ? NULL : &salt[0],
252 salt.size()));
253}
254
256DefaultNSEC3HashCreator::create(uint8_t algorithm, uint16_t iterations,
257 const uint8_t* salt_data,
258 size_t salt_length) const
259{
260 return (new NSEC3HashRFC5155(algorithm, iterations,
261 salt_data, salt_length));
262}
263
264void
266 creator = new_creator;
267}
268
269} // namespace dns
270} // namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
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:240
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:223
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:501
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:265
string encodeBase32Hex(const vector< uint8_t > &binary)
Encode binary data in the base32-hex format.
Definition: encode.cc:349
Definition: edns.h:19
Defines the logger used by the top-level component of kea-lfc.