hickory_proto/rr/dnssec/verifier.rs
1// Copyright 2015-2023 Benjamin Fry <benjaminfry@me.com>
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// https://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// https://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8//! Verifier is a structure for performing many of the signing processes of the DNSSEC specification
9
10use crate::{
11 error::ProtoResult,
12 rr::{
13 dnssec::{
14 rdata::{DNSKEY, KEY, RRSIG, SIG},
15 tbs, Algorithm, PublicKey, PublicKeyEnum,
16 },
17 DNSClass, Name, Record,
18 },
19 serialize::binary::BinEncodable,
20};
21
22/// Types which are able to verify DNS based signatures
23pub trait Verifier {
24 /// Return the algorithm which this Verifier covers
25 fn algorithm(&self) -> Algorithm;
26
27 /// Return the public key associated with this verifier
28 fn key(&self) -> ProtoResult<PublicKeyEnum<'_>>;
29
30 /// Verifies the hash matches the signature with the current `key`.
31 ///
32 /// # Arguments
33 ///
34 /// * `hash` - the hash to be validated, see `rrset_tbs`
35 /// * `signature` - the signature to use to verify the hash, extracted from an `RData::RRSIG`
36 /// for example.
37 ///
38 /// # Return value
39 ///
40 /// True if and only if the signature is valid for the hash.
41 /// false if the `key`.
42 fn verify(&self, hash: &[u8], signature: &[u8]) -> ProtoResult<()> {
43 self.key()?.verify(self.algorithm(), hash, signature)
44 }
45
46 /// Verifies a message with the against the given signature, i.e. SIG0
47 ///
48 /// # Arguments
49 ///
50 /// * `message` - the message to verify
51 /// * `signature` - the signature to use for validation
52 ///
53 /// # Return value
54 ///
55 /// `true` if the message could be validated against the signature, `false` otherwise
56 fn verify_message<M: BinEncodable>(
57 &self,
58 message: &M,
59 signature: &[u8],
60 sig0: &SIG,
61 ) -> ProtoResult<()> {
62 tbs::message_tbs(message, sig0).and_then(|tbs| self.verify(tbs.as_ref(), signature))
63 }
64
65 /// Verifies an RRSig with the associated key, e.g. DNSKEY
66 ///
67 /// # Arguments
68 ///
69 /// * `name` - name associated with the rrsig being validated
70 /// * `dns_class` - DNSClass of the records, generally IN
71 /// * `sig` - signature record being validated
72 /// * `records` - Records covered by SIG
73 fn verify_rrsig(
74 &self,
75 name: &Name,
76 dns_class: DNSClass,
77 sig: &RRSIG,
78 records: &[Record],
79 ) -> ProtoResult<()> {
80 let rrset_tbs = tbs::rrset_tbs_with_sig(name, dns_class, sig, records)?;
81 self.verify(rrset_tbs.as_ref(), sig.sig())
82 }
83}
84
85impl Verifier for DNSKEY {
86 fn algorithm(&self) -> Algorithm {
87 self.algorithm()
88 }
89
90 fn key(&self) -> ProtoResult<PublicKeyEnum<'_>> {
91 PublicKeyEnum::from_public_bytes(self.public_key(), self.algorithm())
92 }
93}
94
95impl Verifier for KEY {
96 fn algorithm(&self) -> Algorithm {
97 self.algorithm()
98 }
99
100 fn key(&self) -> ProtoResult<PublicKeyEnum<'_>> {
101 PublicKeyEnum::from_public_bytes(self.public_key(), self.algorithm())
102 }
103}