2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include "dnsparser.hh"
28 #include "dnswriter.hh"
29 #include "dnsrecords.hh"
35 #include <boost/algorithm/string.hpp>
36 #include "dnssecinfra.hh"
37 #include "dnsseckeeper.hh"
38 #include <openssl/hmac.h>
39 #include <openssl/sha.h>
40 #include <boost/assign/std/vector.hpp> // for 'operator+=()'
41 #include <boost/assign/list_inserter.hpp>
43 #include "namespaces.hh"
45 #include "pkcs11signers.hh"
47 #include "gss_context.hh"
50 using namespace boost::assign
;
52 shared_ptr
<DNSCryptoKeyEngine
> DNSCryptoKeyEngine::makeFromISCFile(DNSKEYRecordContent
& drc
, const char* fname
)
55 FILE *fp
=fopen(fname
, "r");
57 throw runtime_error("Unable to read file '"+string(fname
)+"' for generating DNS Private Key");
60 while(stringfgets(fp
, sline
)) {
64 shared_ptr
<DNSCryptoKeyEngine
> dke
= makeFromISCString(drc
, isc
);
65 if(!dke
->checkKey()) {
66 throw runtime_error("Invalid DNS Private Key in file '"+string(fname
));
71 shared_ptr
<DNSCryptoKeyEngine
> DNSCryptoKeyEngine::makeFromISCString(DNSKEYRecordContent
& drc
, const std::string
& content
)
75 string sline
, key
, value
, raw
;
76 std::istringstream
str(content
);
77 map
<string
, string
> stormap
;
79 while(std::getline(str
, sline
)) {
80 tie(key
,value
)=splitField(sline
, ':');
82 if(pdns_iequals(key
,"algorithm")) {
83 algorithm
= pdns_stou(value
);
84 stormap
["algorithm"]=std::to_string(algorithm
);
86 } else if (pdns_iequals(key
,"pin")) {
89 } else if (pdns_iequals(key
,"engine")) {
90 stormap
["engine"]=value
;
93 } else if (pdns_iequals(key
,"slot")) {
94 stormap
["slot"]=value
;
96 } else if (pdns_iequals(key
,"label")) {
97 stormap
["label"]=value
;
99 } else if (pdns_iequals(key
,"publabel")) {
100 stormap
["publabel"]=value
;
103 else if(pdns_iequals(key
, "Private-key-format"))
106 B64Decode(value
, raw
);
107 stormap
[toLower(key
)]=raw
;
109 shared_ptr
<DNSCryptoKeyEngine
> dpk
;
113 if (stormap
.find("slot") == stormap
.end())
114 throw PDNSException("Cannot load PKCS#11 key, no Slot specified");
115 // we need PIN to be at least empty
116 if (stormap
.find("pin") == stormap
.end()) stormap
["pin"] = "";
117 dpk
= PKCS11DNSCryptoKeyEngine::maker(algorithm
);
119 throw PDNSException("Cannot load PKCS#11 key without support for it");
124 dpk
->fromISCMap(drc
, stormap
);
128 std::string
DNSCryptoKeyEngine::convertToISC() const
130 typedef map
<string
, string
> stormap_t
;
131 storvector_t stormap
= this->convertToISCVector();
133 ret
<<"Private-key-format: v1.2\n";
134 for(const stormap_t::value_type
& value
: stormap
) {
135 if(value
.first
!= "Algorithm" && value
.first
!= "PIN" &&
136 value
.first
!= "Slot" && value
.first
!= "Engine" &&
137 value
.first
!= "Label" && value
.first
!= "PubLabel")
138 ret
<<value
.first
<<": "<<Base64Encode(value
.second
)<<"\n";
140 ret
<<value
.first
<<": "<<value
.second
<<"\n";
145 shared_ptr
<DNSCryptoKeyEngine
> DNSCryptoKeyEngine::make(unsigned int algo
)
147 const makers_t
& makers
= getMakers();
148 makers_t::const_iterator iter
= makers
.find(algo
);
149 if(iter
!= makers
.cend())
150 return (iter
->second
)(algo
);
152 throw runtime_error("Request to create key object for unknown algorithm number "+std::to_string(algo
));
157 * Returns the supported DNSSEC algorithms with the name of the Crypto Backend used
159 * @return A vector with pairs of (algorithm-number (int), backend-name (string))
161 vector
<pair
<uint8_t, string
>> DNSCryptoKeyEngine::listAllAlgosWithBackend()
163 vector
<pair
<uint8_t, string
>> ret
;
164 for (auto const& value
: getMakers()) {
165 shared_ptr
<DNSCryptoKeyEngine
> dcke(value
.second(value
.first
));
166 ret
.push_back(make_pair(value
.first
, dcke
->getName()));
171 void DNSCryptoKeyEngine::report(unsigned int algo
, maker_t
* maker
, bool fallback
)
173 getAllMakers()[algo
].push_back(maker
);
174 if(getMakers().count(algo
) && fallback
) {
177 getMakers()[algo
]=maker
;
180 bool DNSCryptoKeyEngine::testAll()
184 for(const allmakers_t::value_type
& value
: getAllMakers())
186 for(maker_t
* creator
: value
.second
) {
188 for(maker_t
* signer
: value
.second
) {
189 // multi_map<unsigned int, maker_t*> bestSigner, bestVerifier;
191 for(maker_t
* verifier
: value
.second
) {
193 /* pair<unsigned int, unsigned int> res=*/ testMakers(value
.first
, creator
, signer
, verifier
);
195 catch(std::exception
& e
)
197 cerr
<<e
.what()<<endl
;
207 bool DNSCryptoKeyEngine::testOne(int algo
)
211 for(maker_t
* creator
: getAllMakers()[algo
]) {
213 for(maker_t
* signer
: getAllMakers()[algo
]) {
214 // multi_map<unsigned int, maker_t*> bestSigner, bestVerifier;
216 for(maker_t
* verifier
: getAllMakers()[algo
]) {
218 /* pair<unsigned int, unsigned int> res=*/testMakers(algo
, creator
, signer
, verifier
);
220 catch(std::exception
& e
)
222 cerr
<<e
.what()<<endl
;
230 // returns times it took to sign and verify
231 pair
<unsigned int, unsigned int> DNSCryptoKeyEngine::testMakers(unsigned int algo
, maker_t
* creator
, maker_t
* signer
, maker_t
* verifier
)
233 shared_ptr
<DNSCryptoKeyEngine
> dckeCreate(creator(algo
));
234 shared_ptr
<DNSCryptoKeyEngine
> dckeSign(signer(algo
));
235 shared_ptr
<DNSCryptoKeyEngine
> dckeVerify(verifier(algo
));
237 cerr
<<"Testing algorithm "<<algo
<<": '"<<dckeCreate
->getName()<<"' ->'"<<dckeSign
->getName()<<"' -> '"<<dckeVerify
->getName()<<"' ";
241 else if(algo
== DNSSECKeeper::ECCGOST
|| algo
== DNSSECKeeper::ECDSA256
|| algo
== DNSSECKeeper::ED25519
)
243 else if(algo
== DNSSECKeeper::ECDSA384
)
245 else if(algo
== DNSSECKeeper::ED448
)
248 throw runtime_error("Can't guess key size for algorithm "+std::to_string(algo
));
250 dckeCreate
->create(bits
);
252 { // FIXME: this block copy/pasted from makeFromISCString
253 DNSKEYRecordContent dkrc
;
255 string sline
, key
, value
, raw
;
256 std::istringstream
str(dckeCreate
->convertToISC());
257 map
<string
, string
> stormap
;
259 while(std::getline(str
, sline
)) {
260 tie(key
,value
)=splitField(sline
, ':');
262 if(pdns_iequals(key
,"algorithm")) {
263 algorithm
= pdns_stou(value
);
264 stormap
["algorithm"]=std::to_string(algorithm
);
266 } else if (pdns_iequals(key
,"pin")) {
267 stormap
["pin"]=value
;
269 } else if (pdns_iequals(key
,"engine")) {
270 stormap
["engine"]=value
;
272 } else if (pdns_iequals(key
,"slot")) {
273 int slot
= std::stoi(value
);
274 stormap
["slot"]=std::to_string(slot
);
276 } else if (pdns_iequals(key
,"label")) {
277 stormap
["label"]=value
;
280 else if(pdns_iequals(key
, "Private-key-format"))
283 B64Decode(value
, raw
);
284 stormap
[toLower(key
)]=raw
;
286 dckeSign
->fromISCMap(dkrc
, stormap
);
287 if(!dckeSign
->checkKey()) {
288 throw runtime_error("Verification of key with creator "+dckeCreate
->getName()+" with signer "+dckeSign
->getName()+" and verifier "+dckeVerify
->getName()+" failed");
292 string
message("Hi! How is life?");
296 for(unsigned int n
= 0; n
< 100; ++n
)
297 signature
= dckeSign
->sign(message
);
298 unsigned int udiffSign
= dt
.udiff()/100, udiffVerify
;
300 dckeVerify
->fromPublicKeyString(dckeSign
->getPublicKeyString());
301 if (dckeVerify
->getPublicKeyString().compare(dckeSign
->getPublicKeyString())) {
302 throw runtime_error("Comparison of public key loaded into verifier produced by signer failed");
305 if(dckeVerify
->verify(message
, signature
)) {
306 udiffVerify
= dt
.udiff();
307 cerr
<<"Signature & verify ok, signature "<<udiffSign
<<"usec, verify "<<udiffVerify
<<"usec"<<endl
;
310 throw runtime_error("Verification of creator "+dckeCreate
->getName()+" with signer "+dckeSign
->getName()+" and verifier "+dckeVerify
->getName()+" failed");
312 return make_pair(udiffSign
, udiffVerify
);
315 shared_ptr
<DNSCryptoKeyEngine
> DNSCryptoKeyEngine::makeFromPublicKeyString(unsigned int algorithm
, const std::string
& content
)
317 shared_ptr
<DNSCryptoKeyEngine
> dpk
=make(algorithm
);
318 dpk
->fromPublicKeyString(content
);
323 shared_ptr
<DNSCryptoKeyEngine
> DNSCryptoKeyEngine::makeFromPEMString(DNSKEYRecordContent
& drc
, const std::string
& raw
)
326 for(const makers_t::value_type
& val
: getMakers())
328 shared_ptr
<DNSCryptoKeyEngine
> ret
=nullptr;
330 ret
= val
.second(val
.first
);
331 ret
->fromPEMString(drc
, raw
);
342 static bool sharedDNSSECCompare(const shared_ptr
<DNSRecordContent
>& a
, const shared_ptr
<DNSRecordContent
>& b
)
344 return a
->serialize(g_rootdnsname
, true, true) < b
->serialize(g_rootdnsname
, true, true);
348 * Returns the string that should be hashed to create/verify the RRSIG content
350 * @param qname DNSName of the RRSIG's owner name.
351 * @param rrc The RRSIGRecordContent we take the Type Covered and
352 * original TTL fields from.
353 * @param signRecords A vector of DNSRecordContent shared_ptr's that are covered
354 * by the RRSIG, where we get the RDATA from.
355 * @param processRRSIGLabels A boolean to trigger processing the RRSIG's "Labels"
356 * field. This is usually only needed for validation
357 * purposes, as the authoritative server correctly
358 * sets qname to the wildcard.
360 string
getMessageForRRSET(const DNSName
& qname
, const RRSIGRecordContent
& rrc
, vector
<shared_ptr
<DNSRecordContent
> >& signRecords
, bool processRRSIGLabels
)
362 sort(signRecords
.begin(), signRecords
.end(), sharedDNSSECCompare
);
365 toHash
.append(const_cast<RRSIGRecordContent
&>(rrc
).serialize(g_rootdnsname
, true, true));
366 toHash
.resize(toHash
.size() - rrc
.d_signature
.length()); // chop off the end, don't sign the signature!
368 string
nameToHash(qname
.toDNSStringLC());
370 if (processRRSIGLabels
) {
371 unsigned int rrsig_labels
= rrc
.d_labels
;
372 unsigned int fqdn_labels
= qname
.countLabels();
374 if (rrsig_labels
< fqdn_labels
) {
375 DNSName
choppedQname(qname
);
376 while (choppedQname
.countLabels() > rrsig_labels
)
377 choppedQname
.chopOff();
378 nameToHash
= "\x01*" + choppedQname
.toDNSStringLC();
379 } else if (rrsig_labels
> fqdn_labels
) {
380 // The RRSIG Labels field is a lie (or the qname is wrong) and the RRSIG
381 // can never be valid
386 for(shared_ptr
<DNSRecordContent
>& add
: signRecords
) {
387 toHash
.append(nameToHash
);
388 uint16_t tmp
=htons(rrc
.d_type
);
389 toHash
.append((char*)&tmp
, 2);
390 tmp
=htons(1); // class
391 toHash
.append((char*)&tmp
, 2);
392 uint32_t ttl
=htonl(rrc
.d_originalttl
);
393 toHash
.append((char*)&ttl
, 4);
394 // for NSEC signatures, we should not lowercase the rdata section
395 string rdata
=add
->serialize(g_rootdnsname
, true, (add
->getType() == QType::NSEC
) ? false : true); // RFC 6840, 5.1
396 tmp
=htons(rdata
.length());
397 toHash
.append((char*)&tmp
, 2);
398 toHash
.append(rdata
);
404 bool DNSCryptoKeyEngine::isAlgorithmSupported(unsigned int algo
)
406 const makers_t
& makers
= getMakers();
407 makers_t::const_iterator iter
= makers
.find(algo
);
408 return iter
!= makers
.cend();
411 static unsigned int digestToAlgorithmNumber(uint8_t digest
)
414 case DNSSECKeeper::SHA1
:
415 return DNSSECKeeper::RSASHA1
;
416 case DNSSECKeeper::SHA256
:
417 return DNSSECKeeper::RSASHA256
;
418 case DNSSECKeeper::GOST
:
419 return DNSSECKeeper::ECCGOST
;
420 case DNSSECKeeper::SHA384
:
421 return DNSSECKeeper::ECDSA384
;
423 throw std::runtime_error("Unknown digest type " + std::to_string(digest
));
428 bool DNSCryptoKeyEngine::isDigestSupported(uint8_t digest
)
431 unsigned int algo
= digestToAlgorithmNumber(digest
);
432 return isAlgorithmSupported(algo
);
434 catch(const std::exception
& e
) {
439 DSRecordContent
makeDSFromDNSKey(const DNSName
& qname
, const DNSKEYRecordContent
& drc
, uint8_t digest
)
442 toHash
.assign(qname
.toDNSStringLC());
443 toHash
.append(const_cast<DNSKEYRecordContent
&>(drc
).serialize(DNSName(), true, true));
445 DSRecordContent dsrc
;
447 unsigned int algo
= digestToAlgorithmNumber(digest
);
448 shared_ptr
<DNSCryptoKeyEngine
> dpk(DNSCryptoKeyEngine::make(algo
));
449 dsrc
.d_digest
= dpk
->hash(toHash
);
451 catch(const std::exception
& e
) {
452 throw std::runtime_error("Asked to a DS of unknown digest type " + std::to_string(digest
)+"\n");
455 dsrc
.d_algorithm
= drc
.d_algorithm
;
456 dsrc
.d_digesttype
= digest
;
457 dsrc
.d_tag
= const_cast<DNSKEYRecordContent
&>(drc
).getTag();
463 static DNSKEYRecordContent
makeDNSKEYFromDNSCryptoKeyEngine(const std::shared_ptr
<DNSCryptoKeyEngine
> pk
, uint8_t algorithm
, uint16_t flags
)
465 DNSKEYRecordContent drc
;
468 drc
.d_algorithm
= algorithm
;
471 drc
.d_key
= pk
->getPublicKeyString();
476 uint32_t getStartOfWeek()
478 uint32_t now
= time(0);
479 now
-= (now
% (7*86400));
483 string
hashQNameWithSalt(const NSEC3PARAMRecordContent
& ns3prc
, const DNSName
& qname
)
485 return hashQNameWithSalt(ns3prc
.d_salt
, ns3prc
.d_iterations
, qname
);
488 string
hashQNameWithSalt(const std::string
& salt
, unsigned int iterations
, const DNSName
& qname
)
490 unsigned int times
= iterations
;
491 unsigned char hash
[20];
492 string
toHash(qname
.toDNSStringLC());
496 SHA1((unsigned char*)toHash
.c_str(), toHash
.length(), hash
);
497 toHash
.assign((char*)hash
, sizeof(hash
));
504 void incrementHash(std::string
& raw
) // I wonder if this is correct, cmouse? ;-)
509 for(string::size_type pos
=raw
.size(); pos
; ) {
511 unsigned char c
= (unsigned char)raw
[pos
];
519 void decrementHash(std::string
& raw
) // I wonder if this is correct, cmouse? ;-)
524 for(string::size_type pos
=raw
.size(); pos
; ) {
526 unsigned char c
= (unsigned char)raw
[pos
];
534 DNSKEYRecordContent
DNSSECPrivateKey::getDNSKEY() const
536 return makeDNSKEYFromDNSCryptoKeyEngine(getKey(), d_algorithm
, d_flags
);
542 DEREater(const std::string
& str
) : d_str(str
), d_pos(0)
549 if(d_pos
>= d_str
.length()) {
552 return (uint8_t) d_str
[d_pos
++];
557 uint8_t first
= getByte();
564 for(int n
=0; n
< first
; ++n
) {
571 std::string
getBytes(unsigned int len
)
574 for(unsigned int n
=0; n
< len
; ++n
)
575 ret
.append(1, (char)getByte());
579 std::string::size_type
getOffset()
584 const std::string
& d_str
;
585 std::string::size_type d_pos
;
588 static string
calculateHMAC(const std::string
& key
, const std::string
& text
, TSIGHashEnum hasher
) {
590 const EVP_MD
* md_type
;
592 unsigned char hash
[EVP_MAX_MD_SIZE
];
598 md_type
= EVP_sha1();
601 md_type
= EVP_sha224();
604 md_type
= EVP_sha256();
607 md_type
= EVP_sha384();
610 md_type
= EVP_sha512();
613 throw PDNSException("Unknown hash algorithm requested from calculateHMAC()");
616 unsigned char* out
= HMAC(md_type
, reinterpret_cast<const unsigned char*>(key
.c_str()), key
.size(), reinterpret_cast<const unsigned char*>(text
.c_str()), text
.size(), hash
, &outlen
);
617 if (out
== NULL
|| outlen
== 0) {
618 throw PDNSException("HMAC computation failed");
621 return string((char*) hash
, outlen
);
624 static bool constantTimeStringEquals(const std::string
& a
, const std::string
& b
)
626 if (a
.size() != b
.size()) {
629 const size_t size
= a
.size();
630 #if OPENSSL_VERSION_NUMBER >= 0x0090819fL
631 return CRYPTO_memcmp(a
.c_str(), b
.c_str(), size
) == 0;
633 const volatile unsigned char *_a
= (const volatile unsigned char *) a
.c_str();
634 const volatile unsigned char *_b
= (const volatile unsigned char *) b
.c_str();
635 unsigned char res
= 0;
637 for (size_t idx
= 0; idx
< size
; idx
++) {
638 res
|= _a
[idx
] ^ _b
[idx
];
645 static string
makeTSIGPayload(const string
& previous
, const char* packetBegin
, size_t packetSize
, const DNSName
& tsigKeyName
, const TSIGRecordContent
& trc
, bool timersonly
)
649 if(!previous
.empty()) {
650 uint16_t len
= htons(previous
.length());
651 message
.append(reinterpret_cast<const char*>(&len
), sizeof(len
));
652 message
.append(previous
);
655 message
.append(packetBegin
, packetSize
);
657 vector
<uint8_t> signVect
;
658 DNSPacketWriter
dw(signVect
, DNSName(), 0);
659 auto pos
=signVect
.size();
661 dw
.xfrName(tsigKeyName
, false);
662 dw
.xfr16BitInt(QClass::ANY
); // class
663 dw
.xfr32BitInt(0); // TTL
664 dw
.xfrName(trc
.d_algoName
.makeLowerCase(), false);
667 uint32_t now
= trc
.d_time
;
669 dw
.xfr16BitInt(trc
.d_fudge
); // fudge
671 dw
.xfr16BitInt(trc
.d_eRcode
); // extended rcode
672 dw
.xfr16BitInt(trc
.d_otherData
.length()); // length of 'other' data
673 // dw.xfrBlob(trc->d_otherData);
675 message
.append(signVect
.begin()+pos
, signVect
.end());
679 static string
makeTSIGMessageFromTSIGPacket(const string
& opacket
, unsigned int tsigOffset
, const DNSName
& keyname
, const TSIGRecordContent
& trc
, const string
& previous
, bool timersonly
, unsigned int dnsHeaderOffset
=0)
682 string
packet(opacket
);
684 packet
.resize(tsigOffset
); // remove the TSIG record at the end as per RFC2845 3.4.1
685 packet
[(dnsHeaderOffset
+ sizeof(struct dnsheader
))-1]--; // Decrease ARCOUNT because we removed the TSIG RR in the previous line.
688 // Replace the message ID with the original message ID from the TSIG record.
689 // This is needed for forwarded DNS Update as they get a new ID when forwarding (section 6.1 of RFC2136). The TSIG record stores the original ID and the
690 // signature was created with the original ID, so we replace it here to get the originally signed message.
691 // If the message is not forwarded, we simply override it with the same id.
692 uint16_t origID
= htons(trc
.d_origID
);
693 packet
.replace(0, 2, (char*)&origID
, 2);
695 return makeTSIGPayload(previous
, packet
.data(), packet
.size(), keyname
, trc
, timersonly
);
698 void addTSIG(DNSPacketWriter
& pw
, TSIGRecordContent
& trc
, const DNSName
& tsigkeyname
, const string
& tsigsecret
, const string
& tsigprevious
, bool timersonly
)
701 if (!getTSIGHashEnum(trc
.d_algoName
, algo
)) {
702 throw PDNSException(string("Unsupported TSIG HMAC algorithm ") + trc
.d_algoName
.toLogString());
705 string toSign
= makeTSIGPayload(tsigprevious
, reinterpret_cast<const char*>(pw
.getContent().data()), pw
.getContent().size(), tsigkeyname
, trc
, timersonly
);
707 if (algo
== TSIG_GSS
) {
708 if (!gss_add_signature(tsigkeyname
, toSign
, trc
.d_mac
)) {
709 throw PDNSException(string("Could not add TSIG signature with algorithm 'gss-tsig' and key name '")+tsigkeyname
.toLogString()+string("'"));
712 trc
.d_mac
= calculateHMAC(tsigsecret
, toSign
, algo
);
713 // trc.d_mac[0]++; // sabotage
715 pw
.startRecord(tsigkeyname
, QType::TSIG
, 0, QClass::ANY
, DNSResourceRecord::ADDITIONAL
, false);
720 bool validateTSIG(const std::string
& packet
, size_t sigPos
, const TSIGTriplet
& tt
, const TSIGRecordContent
& trc
, const std::string
& previousMAC
, const std::string
& theirMAC
, bool timersOnly
, unsigned int dnsHeaderOffset
)
722 uint64_t delta
= std::abs((int64_t)trc
.d_time
- (int64_t)time(nullptr));
723 if(delta
> trc
.d_fudge
) {
724 throw std::runtime_error("Invalid TSIG time delta " + std::to_string(delta
) + " > fudge " + std::to_string(trc
.d_fudge
));
728 if (!getTSIGHashEnum(trc
.d_algoName
, algo
)) {
729 throw std::runtime_error("Unsupported TSIG HMAC algorithm " + trc
.d_algoName
.toLogString());
732 TSIGHashEnum expectedAlgo
;
733 if (!getTSIGHashEnum(tt
.algo
, expectedAlgo
)) {
734 throw std::runtime_error("Unsupported TSIG HMAC algorithm expected " + tt
.algo
.toLogString());
737 if (algo
!= expectedAlgo
) {
738 throw std::runtime_error("Signature with TSIG key '"+tt
.name
.toLogString()+"' does not match the expected algorithm (" + tt
.algo
.toLogString() + " / " + trc
.d_algoName
.toLogString() + ")");
742 tsigMsg
= makeTSIGMessageFromTSIGPacket(packet
, sigPos
, tt
.name
, trc
, previousMAC
, timersOnly
, dnsHeaderOffset
);
744 if (algo
== TSIG_GSS
) {
745 GssContext
gssctx(tt
.name
);
746 if (!gss_verify_signature(tt
.name
, tsigMsg
, theirMAC
)) {
747 throw std::runtime_error("Signature with TSIG key '"+tt
.name
.toLogString()+"' failed to validate");
750 string ourMac
= calculateHMAC(tt
.secret
, tsigMsg
, algo
);
752 if(!constantTimeStringEquals(ourMac
, theirMAC
)) {
753 throw std::runtime_error("Signature with TSIG key '"+tt
.name
.toLogString()+"' failed to validate");