25#include <boost/shared_ptr.hpp>
37typedef boost::shared_ptr<HMAC> HMACPtr;
69 key_.getSecret(),
key_.getSecretLength(),
75 size_t digestbits =
key_.getDigestbits();
76 size_t default_digest_len =
hmac_->getOutputLength();
98 uint16_t digest_len) {
106 static_cast<const uint8_t*
>(
digest) +
120 HMACPtr ret = HMACPtr();
125 key_.getSecret(),
key_.getSecretLength(),
126 key_.getAlgorithm()),
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;
150 size_t data_len)
const;
179 buffer.writeUint16(previous_digest_len);
180 if (previous_digest_len != 0) {
183 hmac->update(buffer.getData(), buffer.getLength());
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 {
196 size_t data_size = 8;
197 if (!time_variables_only) {
198 data_size += 10 + key_.getKeyName().getLength() +
199 key_.getAlgorithmName().getLength();
203 if (!time_variables_only) {
204 key_.getKeyName().toWire(buffer);
205 buffer.writeUint16(rrclass);
206 buffer.writeUint32(rrttl);
207 key_.getAlgorithmName().toWire(buffer);
209 buffer.writeUint16(time_signed >> 32);
210 buffer.writeUint32(time_signed & 0xffffffff);
211 buffer.writeUint16(fudge);
213 if (!time_variables_only) {
214 buffer.writeUint16(error);
215 buffer.writeUint16(otherlen);
218 hmac->update(buffer.getData(), buffer.getLength());
219 if (!time_variables_only && otherlen > 0) {
220 hmac->update(otherdata, otherlen);
236const size_t MESSAGE_HEADER_LEN = 12;
241 uint16_t qid,
const void* data,
242 size_t data_len)
const {
244 const uint8_t* msgptr =
static_cast<const uint8_t*
>(data);
247 buffer.writeUint16(qid);
248 msgptr +=
sizeof(uint16_t);
251 buffer.writeData(msgptr, 8);
260 hmac->update(buffer.getData(), buffer.getLength());
261 hmac->update(msgptr, data_len - MESSAGE_HEADER_LEN);
312 const size_t digest_len =
320 return (26 + impl_->key_.getKeyName().getLength() +
321 impl_->key_.getAlgorithmName().getLength() +
322 digest_len + other_len);
327 return (impl_->state_);
332 return (impl_->error_);
337 const size_t data_len) {
340 "TSIG sign attempt after verifying a response");
343 if (!data || data_len == 0) {
348 const uint64_t now = getTSIGTime();
352 error = impl_->error_;
359 impl_->key_.getKeyName(),
360 any::TSIG(impl_->key_.getAlgorithmName(),
362 qid, error.getCode(), 0, 0)));
363 impl_->previous_digest_.clear();
368 HMACPtr hmac(impl_->createHMAC());
372 if (impl_->state_ !=
INIT) {
373 impl_->digestPreviousMAC(hmac);
377 hmac->update(data, data_len);
382 impl_->previous_timesigned_ : now;
388 otherdatabuf.writeUint16(now >> 32);
389 otherdatabuf.writeUint32(now & 0xffffffff);
391 const void*
const otherdata =
392 (otherlen == 0) ? 0 : otherdatabuf.getData();
403 vector<uint8_t>
digest = hmac->sign(impl_->digest_len_);
406 impl_->key_.getKeyName(),
407 any::TSIG(impl_->key_.getAlgorithmName(),
410 qid, error.getCode(), otherlen,
413 impl_->previous_digest_.swap(
digest);
420 const size_t data_len) {
423 "TSIG verify attempt after sending a response");
427 if (impl_->last_sig_dist_ >= 0 && impl_->last_sig_dist_ < 99) {
433 impl_->last_sig_dist_++;
444 const any::TSIG& tsig_rdata = record->getRdata();
447 if (data_len < MESSAGE_HEADER_LEN + record->getLength()) {
449 "TSIG verify: data length is invalid: " << data_len);
456 impl_->last_sig_dist_ = 0;
464 if (impl_->key_.getKeyName() != record->getName() ||
465 impl_->key_.getAlgorithmName() != tsig_rdata.getAlgorithm()) {
476 const uint64_t now = getTSIGTime();
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();
495 if (tsig_rdata.getMACSize() == 0) {
500 return (impl_->postVerifyUpdate(error, 0, 0));
503 HMACPtr hmac(impl_->createHMAC());
507 if (impl_->state_ !=
INIT) {
508 impl_->digestPreviousMAC(hmac);
512 if (tsig_rdata.getMACSize() > hmac->getOutputLength()) {
516 if ((tsig_rdata.getMACSize() < 10) ||
517 (tsig_rdata.getMACSize() < (hmac->getOutputLength() / 2))) {
521 if (tsig_rdata.getMACSize() < impl_->digest_len_) {
530 impl_->digestDNSMessage(hmac, tsig_rdata.getOriginalID(),
531 data, data_len - record->getLength());
541 tsig_rdata.getTimeSigned(),
542 tsig_rdata.getFudge(), tsig_rdata.getError(),
543 tsig_rdata.getOtherLen(),
544 tsig_rdata.getOtherData(),
548 if (hmac->verify(tsig_rdata.getMAC(), tsig_rdata.getMACSize())) {
551 tsig_rdata.getMACSize()));
559 if (impl_->last_sig_dist_ == -1) {
562 return (impl_->last_sig_dist_ == 0);
567 HMACPtr hmac(impl_->createHMAC());
569 impl_->digestPreviousMAC(hmac);
570 impl_->previous_digest_.clear();
572 hmac->update(data, len);
This is a base class for exceptions thrown from the DNS library module.
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
static CryptoLink & getCryptoLink()
Returns a reference to the singleton instance.
The Name class encapsulates DNS names.
An exception that is thrown for logic errors identified in TSIG sign/verify operations.
State
Internal state of context.
@ RECEIVED_REQUEST
Server received a signed request.
@ SENT_REQUEST
Client sent a signed request, waiting response.
@ SENT_RESPONSE
Server sent a signed response.
@ VERIFIED_RESPONSE
Client successfully verified a response.
virtual ConstTSIGRecordPtr sign(const uint16_t qid, const void *const data, const size_t data_len)
Sign a DNS message.
static const uint16_t DEFAULT_FUDGE
The recommended fudge value (in seconds) by RFC2845.
virtual TSIGError getError() const
Return the TSIG error as a result of the latest verification.
virtual size_t getTSIGLength() const
Return the expected length of TSIG RR after sign()
virtual ~TSIGContext()
The destructor.
void update(const void *const data, size_t len)
Update internal HMAC state by more data.
TSIGContext(const TSIGKey &key)
Constructor from a TSIG key.
virtual TSIGError verify(const TSIGRecord *const record, const void *const data, const size_t data_len)
Verify a DNS message.
virtual State getState() const
Return the current state of the context.
virtual bool lastHadSignature() const
Check whether the last verified message was signed.
static const TSIGError & BAD_SIG()
A constant TSIG error object for the BADSIG code (see TSIGError::BAD_SIG_CODE).
static const TSIGError & BAD_KEY()
A constant TSIG error object for the BADKEY code (see TSIGError::BAD_KEY_CODE).
static const TSIGError & BAD_TIME()
A constant TSIG error object for the BADTIME code (see TSIGError::BAD_TIME_CODE).
static const TSIGError & NOERROR()
A constant TSIG error object derived from Rcode::NOERROR()
static const TSIGError & BAD_TRUNC()
A constant TSIG error object for the BADTRUNC code (see TSIGError::BAD_TRUNC_CODE).
static const TSIGError & FORMERR()
A constant TSIG error object derived from Rcode::FORMERR()
A simple repository of a set of TSIGKey objects.
static const RRClass & getClass()
Return the RR class of TSIG.
static const uint32_t TSIG_TTL
The TTL value to be used in TSIG RRs.
rdata::TSIG class represents the TSIG RDATA as defined in RFC2845.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define isc_throw_assert(expr)
Replacement for assert() that throws if the expression is false.
void deleteHMAC(HMAC *hmac)
Delete an HMAC object.
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.
boost::shared_ptr< const TSIGRecord > ConstTSIGRecordPtr
A pointer-like type pointing to an immutable TSIGRecord object.
int64_t getTimeWrapper()
Return the current time in seconds.
uint16_t readUint16(void const *const buffer, size_t const length)
uint16_t wrapper over readUint.
Defines the logger used by the top-level component of kea-lfc.
void digestDNSMessage(HMACPtr hmac, uint16_t qid, const void *data, size_t data_len) const
void digestPreviousMAC(HMACPtr hmac)
uint64_t previous_timesigned_
TSIGContextImpl(const TSIGKey &key, TSIGError error=TSIGError::NOERROR())
TSIGError postVerifyUpdate(TSIGError error, const void *digest, uint16_t digest_len)
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
vector< uint8_t > previous_digest_
A helper structure to represent the search result of TSIGKeyRing::find().