| Kea 3.0.2-git

tsig.cc
Go to the documentation of this file.
1// Copyright (C) 2011-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 <exceptions/exceptions.h>
10#include <exceptions/isc_assert.h>
11#include <cryptolink/cryptolink.h>
12#include <cryptolink/crypto_hmac.h>
13#include <dns/rdataclass.h>
14#include <dns/rrclass.h>
15#include <dns/time_utils.h>
16#include <dns/tsig.h>
17#include <dns/tsigerror.h>
18#include <dns/tsigkey.h>
19#include <util/buffer.h>
20
21#include <cassert>
22#include <sys/time.h>
23#include <stdint.h>
24#include <vector>
25#include <boost/shared_ptr.hpp>
26
27 using namespace isc::util;
28 using namespace isc::cryptolink;
29 using namespace isc::dns::rdata;
30
31 using namespace std;
32
33
34 namespace isc {
35 namespace dns {
36 namespace {
37 typedef boost::shared_ptr<HMAC> HMACPtr;
38
39// TSIG uses 48-bit unsigned integer to represent time signed.
40// Since getTimeWrapper() returns a 64-bit *signed* integer, we
41// make sure it's stored in an unsigned 64-bit integer variable and
42// represents a value in the expected range. (In reality, however,
43// getTimeWrapper() will return a positive integer that will fit
44// in 48 bits)
45uint64_t
46getTSIGTime() {
47 return (detail::getTimeWrapper() & 0x0000ffffffffffffULL);
48}
49}
50
51 struct TSIGContext::TSIGContextImpl {
52 TSIGContextImpl(const TSIGKey& key,
53 TSIGError error = TSIGError::NOERROR()) :
54 state_(INIT), key_(key), error_(error),
55 previous_timesigned_(0), digest_len_(0),
56 last_sig_dist_(-1) {
57 if (error == TSIGError::NOERROR()) {
58 // In normal (NOERROR) case, the key should be valid, and we
59 // should be able to pre-create a corresponding HMAC object,
60 // which will be likely to be used for sign or verify later.
61 // We do this in the constructor so that we can know the expected
62 // digest length in advance. The creation should normally succeed,
63 // but the key information could be still broken, which could
64 // trigger an exception inside the cryptolink module. We ignore
65 // it at this moment; a subsequent sign/verify operation will try
66 // to create the HMAC, which would also fail.
67 try {
68 hmac_.reset(CryptoLink::getCryptoLink().createHMAC(
69 key_.getSecret(), key_.getSecretLength(),
70 key_.getAlgorithm()),
71 deleteHMAC);
72 } catch (const isc::Exception&) {
73 return;
74 }
75 size_t digestbits = key_.getDigestbits();
76 size_t default_digest_len = hmac_->getOutputLength();
77 if (digestbits > 0) {
78 digest_len_ = (digestbits + 7) / 8;
79 // sanity (cf. RFC 4635)
80 if ((digest_len_ < 10) ||
81 (digest_len_ < (default_digest_len / 2)) ||
82 (digest_len_ > default_digest_len)) {
83 // should emit a warning?
84 digest_len_ = default_digest_len;
85 }
86 } else {
87 digest_len_ = default_digest_len;
88 }
89 }
90 }
91
92 // This helper method is used from verify(). It's expected to be called
93 // just before verify() returns. It updates internal state based on
94 // the verification result and return the TSIGError to be returned to
95 // the caller of verify(), so that verify() can call this method within
96 // its 'return' statement.
97 TSIGError postVerifyUpdate(TSIGError error, const void* digest,
98 uint16_t digest_len) {
99 if (state_ == INIT) {
100 state_ = RECEIVED_REQUEST;
101 } else if (state_ == SENT_REQUEST && error == TSIGError::NOERROR()) {
102 state_ = VERIFIED_RESPONSE;
103 }
104 if (digest) {
105 previous_digest_.assign(static_cast<const uint8_t*>(digest),
106 static_cast<const uint8_t*>(digest) +
107 digest_len);
108 }
109 error_ = error;
110 return (error);
111 }
112
113 // A shortcut method to create an HMAC object for sign/verify. If one
114 // has been successfully created in the constructor, return it; otherwise
115 // create a new one and return it. In the former case, the ownership is
116 // transferred to the caller; the stored HMAC will be reset after the
117 // call.
118 HMACPtr createHMAC() {
119 if (hmac_) {
120 HMACPtr ret = HMACPtr();
121 ret.swap(hmac_);
122 return (ret);
123 }
124 return (HMACPtr(CryptoLink::getCryptoLink().createHMAC(
125 key_.getSecret(), key_.getSecretLength(),
126 key_.getAlgorithm()),
127 deleteHMAC));
128 }
129
130 // The following three are helper methods to compute the digest for
131 // TSIG sign/verify in order to unify the common code logic for sign()
132 // and verify() and to keep these callers concise.
133 // These methods take an HMAC object, which will be updated with the
134 // calculated digest.
135 // Note: All methods construct a local OutputBuffer as a work space with a
136 // fixed initial buffer size to avoid intermediate buffer extension.
137 // This should be efficient enough, especially for fundamentally expensive
138 // operation like cryptographic sign/verify, but if the creation of the
139 // buffer in each helper method is still identified to be a severe
140 // performance bottleneck, we could have this class a buffer as a member
141 // variable and reuse it throughout the object's lifetime. Right now,
142 // we prefer keeping the scope for local things as small as possible.
143 void digestPreviousMAC(HMACPtr hmac);
144 void digestTSIGVariables(HMACPtr hmac, uint16_t rrclass, uint32_t rrttl,
145 uint64_t time_signed, uint16_t fudge,
146 uint16_t error, uint16_t otherlen,
147 const void* otherdata,
148 bool time_variables_only) const;
149 void digestDNSMessage(HMACPtr hmac, uint16_t qid, const void* data,
150 size_t data_len) const;
151 State state_;
152 const TSIGKey key_;
153 vector<uint8_t> previous_digest_;
154 TSIGError error_;
155 uint64_t previous_timesigned_; // only meaningful for response with BADTIME
156 size_t digest_len_;
157 HMACPtr hmac_;
158 // This is the distance from the last verified signed message. Value of 0
159 // means the last message was signed. Special value -1 means there was no
160 // signed message yet.
161 int last_sig_dist_;
162};
163
164 void
165 TSIGContext::TSIGContextImpl::digestPreviousMAC(HMACPtr hmac) {
166 // We should have ensured the digest size fits 16 bits within this class
167 // implementation.
168 isc_throw_assert(previous_digest_.size() <= 0xffff);
169
170 if (previous_digest_.empty()) {
171 // The previous digest was already used. We're in the middle of
172 // TCP stream somewhere and we already pushed some unsigned message
173 // into the HMAC state.
174 return;
175 }
176
177 OutputBuffer buffer(sizeof(uint16_t) + previous_digest_.size());
178 const uint16_t previous_digest_len(previous_digest_.size());
179 buffer.writeUint16(previous_digest_len);
180 if (previous_digest_len != 0) {
181 buffer.writeData(&previous_digest_[0], previous_digest_len);
182 }
183 hmac->update(buffer.getData(), buffer.getLength());
184}
185
186 void
187 TSIGContext::TSIGContextImpl::digestTSIGVariables(HMACPtr hmac, uint16_t rrclass,
188 uint32_t rrttl, uint64_t time_signed,
189 uint16_t fudge, uint16_t error,
190 uint16_t otherlen, const void* otherdata,
191 bool time_variables_only) const {
192 // It's bit complicated, but we can still predict the necessary size of
193 // the data to be digested. So we precompute it to avoid possible
194 // reallocation inside OutputBuffer (not absolutely necessary, but this
195 // is a bit more efficient)
196 size_t data_size = 8;
197 if (!time_variables_only) {
198 data_size += 10 + key_.getKeyName().getLength() +
199 key_.getAlgorithmName().getLength();
200 }
201 OutputBuffer buffer(data_size);
202
203 if (!time_variables_only) {
204 key_.getKeyName().toWire(buffer);
205 buffer.writeUint16(rrclass);
206 buffer.writeUint32(rrttl);
207 key_.getAlgorithmName().toWire(buffer);
208 }
209 buffer.writeUint16(time_signed >> 32);
210 buffer.writeUint32(time_signed & 0xffffffff);
211 buffer.writeUint16(fudge);
212
213 if (!time_variables_only) {
214 buffer.writeUint16(error);
215 buffer.writeUint16(otherlen);
216 }
217
218 hmac->update(buffer.getData(), buffer.getLength());
219 if (!time_variables_only && otherlen > 0) {
220 hmac->update(otherdata, otherlen);
221 }
222}
223
224// In digestDNSMessage, we exploit some minimum knowledge of DNS message
225// format:
226// - the header section has a fixed length of 12 octets (MESSAGE_HEADER_LEN)
227// - the offset in the header section to the ID field is 0
228// - the offset in the header section to the ARCOUNT field is 10 (and the field
229// length is 2 octets)
230// We could construct a separate Message object from the given data, adjust
231// fields via the Message interfaces and then render it back to a separate
232// buffer, but that would be overkilling. The DNS message header has a
233// fixed length and necessary modifications are quite straightforward, so
234// we do the job using lower level interfaces.
235 namespace {
236 const size_t MESSAGE_HEADER_LEN = 12;
237}
238
239 void
240 TSIGContext::TSIGContextImpl::digestDNSMessage(HMACPtr hmac,
241 uint16_t qid, const void* data,
242 size_t data_len) const {
243 OutputBuffer buffer(MESSAGE_HEADER_LEN);
244 const uint8_t* msgptr = static_cast<const uint8_t*>(data);
245
246 // Install the original ID
247 buffer.writeUint16(qid);
248 msgptr += sizeof(uint16_t);
249
250 // Copy the rest of the header except the ARCOUNT field.
251 buffer.writeData(msgptr, 8);
252 msgptr += 8;
253
254 // Install the adjusted ARCOUNT (we don't care even if the value is bogus
255 // and it underflows; it would simply result in verification failure)
256 buffer.writeUint16(InputBuffer(msgptr, sizeof(uint16_t)).readUint16() - 1);
257 msgptr += 2;
258
259 // Digest the header and the rest of the DNS message
260 hmac->update(buffer.getData(), buffer.getLength());
261 hmac->update(msgptr, data_len - MESSAGE_HEADER_LEN);
262}
263
264 TSIGContext::TSIGContext(const TSIGKey& key) : impl_(new TSIGContextImpl(key)) {
265}
266
267 TSIGContext::TSIGContext(const Name& key_name, const Name& algorithm_name,
268 const TSIGKeyRing& keyring) : impl_(0) {
269 const TSIGKeyRing::FindResult result(keyring.find(key_name,
270 algorithm_name));
271 if (result.code == TSIGKeyRing::NOTFOUND) {
272 // If not key is found, create a dummy key with the specified key
273 // parameters and empty secret. In the common scenario this will
274 // be used in subsequent response with a TSIG indicating a BADKEY
275 // error.
276 impl_.reset(new TSIGContextImpl(TSIGKey(key_name, algorithm_name, 0, 0),
277 TSIGError::BAD_KEY()));
278 } else {
279 impl_.reset(new TSIGContextImpl(*result.key));
280 }
281}
282
283 TSIGContext::~TSIGContext() {
284}
285
286 size_t
287 TSIGContext::getTSIGLength() const {
288 //
289 // The space required for an TSIG record is:
290 //
291 // n1 bytes for the (key) name
292 // 2 bytes for the type
293 // 2 bytes for the class
294 // 4 bytes for the ttl
295 // 2 bytes for the rdlength
296 // n2 bytes for the algorithm name
297 // 6 bytes for the time signed
298 // 2 bytes for the fudge
299 // 2 bytes for the MAC size
300 // x bytes for the MAC
301 // 2 bytes for the original id
302 // 2 bytes for the error
303 // 2 bytes for the other data length
304 // y bytes for the other data (at most)
305 // ---------------------------------
306 // 26 + n1 + n2 + x + y bytes
307 //
308
309 // Normally the digest length ("x") is the length of the underlying
310 // hash output. If a key related error occurred, however, the
311 // corresponding TSIG will be "unsigned", and the digest length will be 0.
312 const size_t digest_len =
313 (impl_->error_ == TSIGError::BAD_KEY() ||
314 impl_->error_ == TSIGError::BAD_SIG()) ? 0 : impl_->digest_len_;
315
316 // Other Len ("y") is normally 0; if BAD_TIME error occurred, the
317 // subsequent TSIG will contain 48 bits of the server current time.
318 const size_t other_len = (impl_->error_ == TSIGError::BAD_TIME()) ? 6 : 0;
319
320 return (26 + impl_->key_.getKeyName().getLength() +
321 impl_->key_.getAlgorithmName().getLength() +
322 digest_len + other_len);
323}
324
325 TSIGContext::State
326 TSIGContext::getState() const {
327 return (impl_->state_);
328}
329
330 TSIGError
331 TSIGContext::getError() const {
332 return (impl_->error_);
333}
334
335 ConstTSIGRecordPtr
336 TSIGContext::sign(const uint16_t qid, const void* const data,
337 const size_t data_len) {
338 if (impl_->state_ == VERIFIED_RESPONSE) {
339 isc_throw(TSIGContextError,
340 "TSIG sign attempt after verifying a response");
341 }
342
343 if (!data || data_len == 0) {
344 isc_throw(InvalidParameter, "TSIG sign error: empty data is given");
345 }
346
347 TSIGError error(TSIGError::NOERROR());
348 const uint64_t now = getTSIGTime();
349
350 // For responses adjust the error code.
351 if (impl_->state_ == RECEIVED_REQUEST) {
352 error = impl_->error_;
353 }
354
355 // For errors related to key or MAC, return an unsigned response as
356 // specified in Section 4.3 of RFC2845.
357 if (error == TSIGError::BAD_SIG() || error == TSIGError::BAD_KEY()) {
358 ConstTSIGRecordPtr tsig(new TSIGRecord(
359 impl_->key_.getKeyName(),
360 any::TSIG(impl_->key_.getAlgorithmName(),
361 now, DEFAULT_FUDGE, 0, 0,
362 qid, error.getCode(), 0, 0)));
363 impl_->previous_digest_.clear();
364 impl_->state_ = SENT_RESPONSE;
365 return (tsig);
366 }
367
368 HMACPtr hmac(impl_->createHMAC());
369
370 // If the context has previous MAC (either the Request MAC or its own
371 // previous MAC), digest it.
372 if (impl_->state_ != INIT) {
373 impl_->digestPreviousMAC(hmac);
374 }
375
376 // Digest the message (without TSIG)
377 hmac->update(data, data_len);
378
379 // Digest TSIG variables.
380 // First, prepare some non constant variables.
381 const uint64_t time_signed = (error == TSIGError::BAD_TIME()) ?
382 impl_->previous_timesigned_ : now;
383 // For BADTIME error, we include 6 bytes of other data.
384 // (6 bytes = size of time signed value)
385 const uint16_t otherlen = (error == TSIGError::BAD_TIME()) ? 6 : 0;
386 OutputBuffer otherdatabuf(otherlen);
387 if (error == TSIGError::BAD_TIME()) {
388 otherdatabuf.writeUint16(now >> 32);
389 otherdatabuf.writeUint32(now & 0xffffffff);
390 }
391 const void* const otherdata =
392 (otherlen == 0) ? 0 : otherdatabuf.getData();
393 // Then calculate the digest. If state_ is SENT_RESPONSE we are sending
394 // a continued message in the same TCP stream so skip digesting
395 // variables except for time related variables (RFC2845 4.4).
396 impl_->digestTSIGVariables(hmac, TSIGRecord::getClass().getCode(),
397 TSIGRecord::TSIG_TTL, time_signed,
398 DEFAULT_FUDGE, error.getCode(),
399 otherlen, otherdata,
400 impl_->state_ == SENT_RESPONSE);
401
402 // Get the final digest, update internal state, then finish.
403 vector<uint8_t> digest = hmac->sign(impl_->digest_len_);
404 isc_throw_assert(digest.size() <= 0xffff); // cryptolink API should have ensured it.
405 ConstTSIGRecordPtr tsig(new TSIGRecord(
406 impl_->key_.getKeyName(),
407 any::TSIG(impl_->key_.getAlgorithmName(),
408 time_signed, DEFAULT_FUDGE,
409 digest.size(), &digest[0],
410 qid, error.getCode(), otherlen,
411 otherdata)));
412 // Exception free from now on.
413 impl_->previous_digest_.swap(digest);
414 impl_->state_ = (impl_->state_ == INIT) ? SENT_REQUEST : SENT_RESPONSE;
415 return (tsig);
416}
417
418 TSIGError
419 TSIGContext::verify(const TSIGRecord* const record, const void* const data,
420 const size_t data_len) {
421 if (impl_->state_ == SENT_RESPONSE) {
422 isc_throw(TSIGContextError,
423 "TSIG verify attempt after sending a response");
424 }
425
426 if (!record) {
427 if (impl_->last_sig_dist_ >= 0 && impl_->last_sig_dist_ < 99) {
428 // It is not signed, but in the middle of TCP stream. We just
429 // update the HMAC state and consider this message OK.
430 update(data, data_len);
431 // This one is not signed, the last signed is one message further
432 // now.
433 impl_->last_sig_dist_++;
434 // No digest to return now. Just say it's OK.
435 return (impl_->postVerifyUpdate(TSIGError::NOERROR(), 0, 0));
436 }
437 // This case happens when we sent a signed request and have received an
438 // unsigned response. According to RFC2845 Section 4.6 this case should be
439 // considered a "format error" (although the specific error code
440 // wouldn't matter much for the caller).
441 return (impl_->postVerifyUpdate(TSIGError::FORMERR(), 0, 0));
442 }
443
444 const any::TSIG& tsig_rdata = record->getRdata();
445
446 // Reject some obviously invalid data
447 if (data_len < MESSAGE_HEADER_LEN + record->getLength()) {
448 isc_throw(InvalidParameter,
449 "TSIG verify: data length is invalid: " << data_len);
450 }
451 if (!data) {
452 isc_throw(InvalidParameter, "TSIG verify: empty data is invalid");
453 }
454
455 // This message is signed and we won't throw any more.
456 impl_->last_sig_dist_ = 0;
457
458 // Check key: whether we first verify it with a known key or we verify
459 // it using the consistent key in the context. If the check fails we are
460 // done with BADKEY.
461 if (impl_->state_ == INIT && impl_->error_ == TSIGError::BAD_KEY()) {
462 return (impl_->postVerifyUpdate(TSIGError::BAD_KEY(), 0, 0));
463 }
464 if (impl_->key_.getKeyName() != record->getName() ||
465 impl_->key_.getAlgorithmName() != tsig_rdata.getAlgorithm()) {
466 return (impl_->postVerifyUpdate(TSIGError::BAD_KEY(), 0, 0));
467 }
468
469 // Check time: the current time must be in the range of
470 // [time signed - fudge, time signed + fudge]. Otherwise verification
471 // fails with BADTIME. (RFC2845 Section 4.6.2)
472 // Note: for simplicity we don't explicitly catch the case of too small
473 // current time causing underflow. With the fact that fudge is quite
474 // small and (for now) non configurable, it shouldn't be a real concern
475 // in practice.
476 const uint64_t now = getTSIGTime();
477 if (tsig_rdata.getTimeSigned() + DEFAULT_FUDGE < now ||
478 tsig_rdata.getTimeSigned() - DEFAULT_FUDGE > now) {
479 const void* digest = 0;
480 size_t digest_len = 0;
481 if (impl_->state_ == INIT) {
482 digest = tsig_rdata.getMAC();
483 digest_len = tsig_rdata.getMACSize();
484 impl_->previous_timesigned_ = tsig_rdata.getTimeSigned();
485 }
486 return (impl_->postVerifyUpdate(TSIGError::BAD_TIME(), digest,
487 digest_len));
488 }
489
490 // Handling empty MAC. While RFC2845 doesn't explicitly prohibit other
491 // cases, it can only reasonably happen in a response with BADSIG or
492 // BADKEY. We reject other cases as if it were BADSIG to avoid unexpected
493 // acceptance of a bogus signature. This behavior follows the BIND 9
494 // implementation.
495 if (tsig_rdata.getMACSize() == 0) {
496 TSIGError error = TSIGError(tsig_rdata.getError());
497 if (error != TSIGError::BAD_SIG() && error != TSIGError::BAD_KEY()) {
498 error = TSIGError::BAD_SIG();
499 }
500 return (impl_->postVerifyUpdate(error, 0, 0));
501 }
502
503 HMACPtr hmac(impl_->createHMAC());
504
505 // If the context has previous MAC (either the Request MAC or its own
506 // previous MAC), digest it.
507 if (impl_->state_ != INIT) {
508 impl_->digestPreviousMAC(hmac);
509 }
510
511 // Signature length check based on RFC 4635 3.1
512 if (tsig_rdata.getMACSize() > hmac->getOutputLength()) {
513 // signature length too big
514 return (impl_->postVerifyUpdate(TSIGError::FORMERR(), 0, 0));
515 }
516 if ((tsig_rdata.getMACSize() < 10) ||
517 (tsig_rdata.getMACSize() < (hmac->getOutputLength() / 2))) {
518 // signature length below minimum
519 return (impl_->postVerifyUpdate(TSIGError::FORMERR(), 0, 0));
520 }
521 if (tsig_rdata.getMACSize() < impl_->digest_len_) {
522 // (truncated) signature length too small
523 return (impl_->postVerifyUpdate(TSIGError::BAD_TRUNC(), 0, 0));
524 }
525
526 //
527 // Digest DNS message (excluding the trailing TSIG RR and adjusting the
528 // QID and ARCOUNT header fields)
529 //
530 impl_->digestDNSMessage(hmac, tsig_rdata.getOriginalID(),
531 data, data_len - record->getLength());
532
533 // Digest TSIG variables. If state_ is VERIFIED_RESPONSE, it's a
534 // continuation of the same TCP stream and skip digesting them except
535 // for time related variables (RFC2845 4.4).
536 // Note: we use the constant values for RR class and TTL specified
537 // in RFC2845, not received values (we reject other values in constructing
538 // the TSIGRecord).
539 impl_->digestTSIGVariables(hmac, TSIGRecord::getClass().getCode(),
540 TSIGRecord::TSIG_TTL,
541 tsig_rdata.getTimeSigned(),
542 tsig_rdata.getFudge(), tsig_rdata.getError(),
543 tsig_rdata.getOtherLen(),
544 tsig_rdata.getOtherData(),
545 impl_->state_ == VERIFIED_RESPONSE);
546
547 // Verify the digest with the received signature.
548 if (hmac->verify(tsig_rdata.getMAC(), tsig_rdata.getMACSize())) {
549 return (impl_->postVerifyUpdate(TSIGError::NOERROR(),
550 tsig_rdata.getMAC(),
551 tsig_rdata.getMACSize()));
552 }
553
554 return (impl_->postVerifyUpdate(TSIGError::BAD_SIG(), 0, 0));
555}
556
557 bool
558 TSIGContext::lastHadSignature() const {
559 if (impl_->last_sig_dist_ == -1) {
560 isc_throw(TSIGContextError, "No message was verified yet");
561 }
562 return (impl_->last_sig_dist_ == 0);
563}
564
565 void
566 TSIGContext::update(const void* const data, size_t len) {
567 HMACPtr hmac(impl_->createHMAC());
568 // Use the previous digest and never use it again
569 impl_->digestPreviousMAC(hmac);
570 impl_->previous_digest_.clear();
571 // Push the message there
572 hmac->update(data, len);
573 impl_->hmac_ = hmac;
574}
575
576} // namespace dns
577} // namespace isc
buffer.h
isc::Exception
This is a base class for exceptions thrown from the DNS library module.
Definition exceptions/exceptions.h:23
isc::InvalidParameter
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
Definition exceptions/exceptions.h:124
isc::cryptolink::CryptoLink::getCryptoLink
static CryptoLink & getCryptoLink()
Returns a reference to the singleton instance.
Definition cryptolink.cc:17
isc::dns::Name
The Name class encapsulates DNS names.
Definition name.h:219
isc::dns::TSIGContextError
An exception that is thrown for logic errors identified in TSIG sign/verify operations.
Definition tsig.h:31
isc::dns::TSIGContext::State
State
Internal state of context.
Definition tsig.h:181
isc::dns::TSIGContext::RECEIVED_REQUEST
@ RECEIVED_REQUEST
Server received a signed request.
Definition tsig.h:184
isc::dns::TSIGContext::SENT_REQUEST
@ SENT_REQUEST
Client sent a signed request, waiting response.
Definition tsig.h:183
isc::dns::TSIGContext::SENT_RESPONSE
@ SENT_RESPONSE
Server sent a signed response.
Definition tsig.h:185
isc::dns::TSIGContext::VERIFIED_RESPONSE
@ VERIFIED_RESPONSE
Client successfully verified a response.
Definition tsig.h:186
isc::dns::TSIGContext::INIT
@ INIT
Initial state.
Definition tsig.h:182
isc::dns::TSIGContext::sign
virtual ConstTSIGRecordPtr sign(const uint16_t qid, const void *const data, const size_t data_len)
Sign a DNS message.
Definition tsig.cc:336
isc::dns::TSIGContext::DEFAULT_FUDGE
static const uint16_t DEFAULT_FUDGE
The recommended fudge value (in seconds) by RFC2845.
Definition tsig.h:414
isc::dns::TSIGContext::getError
virtual TSIGError getError() const
Return the TSIG error as a result of the latest verification.
Definition tsig.cc:331
isc::dns::TSIGContext::getTSIGLength
virtual size_t getTSIGLength() const
Return the expected length of TSIG RR after sign().
Definition tsig.cc:287
isc::dns::TSIGContext::~TSIGContext
virtual ~TSIGContext()
The destructor.
Definition tsig.cc:283
isc::dns::TSIGContext::update
void update(const void *const data, size_t len)
Update internal HMAC state by more data.
Definition tsig.cc:566
isc::dns::TSIGContext::TSIGContext
TSIGContext(const TSIGKey &key)
Constructor from a TSIG key.
Definition tsig.cc:264
isc::dns::TSIGContext::verify
virtual TSIGError verify(const TSIGRecord *const record, const void *const data, const size_t data_len)
Verify a DNS message.
Definition tsig.cc:419
isc::dns::TSIGContext::getState
virtual State getState() const
Return the current state of the context.
Definition tsig.cc:326
isc::dns::TSIGContext::lastHadSignature
virtual bool lastHadSignature() const
Check whether the last verified message was signed.
Definition tsig.cc:558
isc::dns::TSIGError
TSIG errors.
Definition tsigerror.h:22
isc::dns::TSIGError::BAD_SIG
static const TSIGError & BAD_SIG()
A constant TSIG error object for the BADSIG code (see TSIGError::BAD_SIG_CODE).
Definition tsigerror.h:323
isc::dns::TSIGError::BAD_KEY
static const TSIGError & BAD_KEY()
A constant TSIG error object for the BADKEY code (see TSIGError::BAD_KEY_CODE).
Definition tsigerror.h:329
isc::dns::TSIGError::BAD_TIME
static const TSIGError & BAD_TIME()
A constant TSIG error object for the BADTIME code (see TSIGError::BAD_TIME_CODE).
Definition tsigerror.h:335
isc::dns::TSIGError::NOERROR
static const TSIGError & NOERROR()
A constant TSIG error object derived from Rcode::NOERROR().
Definition tsigerror.h:227
isc::dns::TSIGError::BAD_TRUNC
static const TSIGError & BAD_TRUNC()
A constant TSIG error object for the BADTRUNC code (see TSIGError::BAD_TRUNC_CODE).
Definition tsigerror.h:359
isc::dns::TSIGError::FORMERR
static const TSIGError & FORMERR()
A constant TSIG error object derived from Rcode::FORMERR().
Definition tsigerror.h:233
isc::dns::TSIGKeyRing
A simple repository of a set of TSIGKey objects.
Definition tsigkey.h:245
isc::dns::TSIGKeyRing::find
FindResult find(const Name &key_name) const
Find a TSIGKey for the given name in the TSIGKeyRing.
Definition tsigkey.cc:283
isc::dns::TSIGKeyRing::NOTFOUND
@ NOTFOUND
Definition tsigkey.h:251
isc::dns::TSIGKey
TSIG key.
Definition tsigkey.h:56
isc::dns::TSIGRecord
TSIG resource record.
Definition tsigrecord.h:51
isc::dns::TSIGRecord::getClass
static const RRClass & getClass()
Return the RR class of TSIG.
Definition tsigrecord.cc:79
isc::dns::TSIGRecord::TSIG_TTL
static const uint32_t TSIG_TTL
The TTL value to be used in TSIG RRs.
Definition tsigrecord.h:270
isc::dns::TSIGRecord::getLength
size_t getLength() const
Return the length of the TSIG record.
Definition tsigrecord.h:211
isc::dns::TSIGRecord::getName
const Name & getName() const
Return the owner name of the TSIG RR, which is the TSIG key name.
Definition tsigrecord.h:168
isc::dns::TSIGRecord::getRdata
const rdata::any::TSIG & getRdata() const
Return the RDATA of the TSIG RR.
Definition tsigrecord.h:175
isc::dns::rdata::any::TSIG
rdata::TSIG class represents the TSIG RDATA as defined in RFC2845.
Definition rdataclass.h:44
isc::dns::rdata::any::TSIG::getOriginalID
uint16_t getOriginalID() const
Return the value of the Original ID field.
isc::dns::rdata::any::TSIG::getError
uint16_t getError() const
Return the value of the Error field.
isc::dns::rdata::any::TSIG::getAlgorithm
const Name & getAlgorithm() const
Return the algorithm name.
isc::dns::rdata::any::TSIG::getOtherLen
uint16_t getOtherLen() const
Return the value of the Other Len field.
isc::dns::rdata::any::TSIG::getOtherData
const void * getOtherData() const
Return the value of the Other Data field.
isc::dns::rdata::any::TSIG::getMAC
const void * getMAC() const
Return the value of the MAC field.
isc::dns::rdata::any::TSIG::getFudge
uint16_t getFudge() const
Return the value of the Fudge field.
isc::dns::rdata::any::TSIG::getMACSize
uint16_t getMACSize() const
Return the value of the MAC Size field.
isc::dns::rdata::any::TSIG::getTimeSigned
uint64_t getTimeSigned() const
Return the value of the Time Signed field.
isc::util::InputBuffer
The InputBuffer class is a buffer abstraction for manipulating read-only data.
Definition buffer.h:81
isc::util::OutputBuffer
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
Definition buffer.h:346
isc::util::OutputBuffer::writeUint16
void writeUint16(uint16_t data)
Write an unsigned 16-bit integer in host byte order into the buffer in network byte order.
Definition buffer.h:501
isc::util::OutputBuffer::writeData
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
Definition buffer.h:559
isc::util::OutputBuffer::writeUint32
void writeUint32(uint32_t data)
Write an unsigned 32-bit integer in host byte order into the buffer in network byte order.
Definition buffer.h:531
isc::util::OutputBuffer::getData
const uint8_t * getData() const
Return a pointer to the head of the data stored in the buffer.
Definition buffer.h:398
isc::util::OutputBuffer::getLength
size_t getLength() const
Return the length of data written in the buffer.
Definition buffer.h:412
crypto_hmac.h
cryptolink.h
exceptions.h
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition exceptions/exceptions.h:210
isc_assert.h
isc_throw_assert
#define isc_throw_assert(expr)
Replacement for assert() that throws if the expression is false.
Definition isc_assert.h:18
isc::cryptolink
Definition botan_common.h:8
isc::cryptolink::deleteHMAC
void deleteHMAC(HMAC *hmac)
Delete an HMAC object.
Definition crypto_hmac.cc:54
isc::cryptolink::digest
void digest(const void *data, const size_t data_len, const HashAlgorithm hash_algorithm, isc::util::OutputBuffer &result, size_t len)
Create an Hash digest for the given data.
Definition crypto_hash.cc:20
isc::data
Definition base_stamped_element.cc:12
isc::dns::rdata
Definition char_string.cc:27
isc::dns
Definition char_string.cc:26
isc::dns::ConstTSIGRecordPtr
boost::shared_ptr< const TSIGRecord > ConstTSIGRecordPtr
A pointer-like type pointing to an immutable TSIGRecord object.
Definition tsigrecord.h:283
isc::util::detail::getTimeWrapper
int64_t getTimeWrapper()
Return the current time in seconds.
Definition time_utils.cc:72
isc::util
Definition time_utils.cc:43
isc::util::readUint16
uint16_t readUint16(void const *const buffer, size_t const length)
uint16_t wrapper over readUint.
Definition io.h:76
isc
Defines the logger used by the top-level component of kea-lfc.
Definition agent_parser.cc:148
rdataclass.h
rrclass.h
isc::dns::TSIGContext::TSIGContextImpl
Definition tsig.cc:51
isc::dns::TSIGContext::TSIGContextImpl::digestDNSMessage
void digestDNSMessage(HMACPtr hmac, uint16_t qid, const void *data, size_t data_len) const
Definition tsig.cc:240
isc::dns::TSIGContext::TSIGContextImpl::error_
TSIGError error_
Definition tsig.cc:154
isc::dns::TSIGContext::TSIGContextImpl::key_
const TSIGKey key_
Definition tsig.cc:152
isc::dns::TSIGContext::TSIGContextImpl::hmac_
HMACPtr hmac_
Definition tsig.cc:157
isc::dns::TSIGContext::TSIGContextImpl::digestPreviousMAC
void digestPreviousMAC(HMACPtr hmac)
Definition tsig.cc:165
isc::dns::TSIGContext::TSIGContextImpl::last_sig_dist_
int last_sig_dist_
Definition tsig.cc:161
isc::dns::TSIGContext::TSIGContextImpl::previous_timesigned_
uint64_t previous_timesigned_
Definition tsig.cc:155
isc::dns::TSIGContext::TSIGContextImpl::createHMAC
HMACPtr createHMAC()
Definition tsig.cc:118
isc::dns::TSIGContext::TSIGContextImpl::state_
State state_
Definition tsig.cc:151
isc::dns::TSIGContext::TSIGContextImpl::digest_len_
size_t digest_len_
Definition tsig.cc:156
isc::dns::TSIGContext::TSIGContextImpl::TSIGContextImpl
TSIGContextImpl(const TSIGKey &key, TSIGError error=TSIGError::NOERROR())
Definition tsig.cc:52
isc::dns::TSIGContext::TSIGContextImpl::postVerifyUpdate
TSIGError postVerifyUpdate(TSIGError error, const void *digest, uint16_t digest_len)
Definition tsig.cc:97
isc::dns::TSIGContext::TSIGContextImpl::digestTSIGVariables
void digestTSIGVariables(HMACPtr hmac, uint16_t rrclass, uint32_t rrttl, uint64_t time_signed, uint16_t fudge, uint16_t error, uint16_t otherlen, const void *otherdata, bool time_variables_only) const
Definition tsig.cc:187
isc::dns::TSIGContext::TSIGContextImpl::previous_digest_
vector< uint8_t > previous_digest_
Definition tsig.cc:153
isc::dns::TSIGKeyRing::FindResult
A helper structure to represent the search result of TSIGKeyRing::find().
Definition tsigkey.h:269
isc::dns::TSIGKeyRing::FindResult::code
const Result code
Definition tsigkey.h:273
isc::dns::TSIGKeyRing::FindResult::key
const TSIGKey *const key
Definition tsigkey.h:274
time_utils.h
tsig.h
tsigerror.h
tsigkey.h