1 /* SPDX-License-Identifier: LGPL-2.1+ */
7 #include <netinet/in.h>
8 #include <sys/socket.h>
10 #include "alloc-util.h"
11 #include "resolved-dns-dnssec.h"
12 #include "resolved-dns-rr.h"
13 #include "string-util.h"
14 #include "hexdecoct.h"
16 static void test_dnssec_canonicalize_one(const char *original
, const char *canonical
, int r
) {
17 char canonicalized
[DNSSEC_CANONICAL_HOSTNAME_MAX
];
19 assert_se(dnssec_canonicalize(original
, canonicalized
, sizeof(canonicalized
)) == r
);
23 assert_se(streq(canonicalized
, canonical
));
26 static void test_dnssec_canonicalize(void) {
27 test_dnssec_canonicalize_one("", ".", 1);
28 test_dnssec_canonicalize_one(".", ".", 1);
29 test_dnssec_canonicalize_one("foo", "foo.", 4);
30 test_dnssec_canonicalize_one("foo.", "foo.", 4);
31 test_dnssec_canonicalize_one("FOO.", "foo.", 4);
32 test_dnssec_canonicalize_one("FOO.bar.", "foo.bar.", 8);
33 test_dnssec_canonicalize_one("FOO..bar.", NULL
, -EINVAL
);
38 static void test_dnssec_verify_dns_key(void) {
40 static const uint8_t ds1_fprint
[] = {
41 0x46, 0x8B, 0xC8, 0xDD, 0xC7, 0xE8, 0x27, 0x03, 0x40, 0xBB, 0x8A, 0x1F, 0x3B, 0x2E, 0x45, 0x9D,
42 0x80, 0x67, 0x14, 0x01,
44 static const uint8_t ds2_fprint
[] = {
45 0x8A, 0xEE, 0x80, 0x47, 0x05, 0x5F, 0x83, 0xD1, 0x48, 0xBA, 0x8F, 0xF6, 0xDD, 0xA7, 0x60, 0xCE,
46 0x94, 0xF7, 0xC7, 0x5E, 0x52, 0x4C, 0xF2, 0xE9, 0x50, 0xB9, 0x2E, 0xCB, 0xEF, 0x96, 0xB9, 0x98,
48 static const uint8_t dnskey_blob
[] = {
49 0x03, 0x01, 0x00, 0x01, 0xa8, 0x12, 0xda, 0x4f, 0xd2, 0x7d, 0x54, 0x14, 0x0e, 0xcc, 0x5b, 0x5e,
50 0x45, 0x9c, 0x96, 0x98, 0xc0, 0xc0, 0x85, 0x81, 0xb1, 0x47, 0x8c, 0x7d, 0xe8, 0x39, 0x50, 0xcc,
51 0xc5, 0xd0, 0xf2, 0x00, 0x81, 0x67, 0x79, 0xf6, 0xcc, 0x9d, 0xad, 0x6c, 0xbb, 0x7b, 0x6f, 0x48,
52 0x97, 0x15, 0x1c, 0xfd, 0x0b, 0xfe, 0xd3, 0xd7, 0x7d, 0x9f, 0x81, 0x26, 0xd3, 0xc5, 0x65, 0x49,
53 0xcf, 0x46, 0x62, 0xb0, 0x55, 0x6e, 0x47, 0xc7, 0x30, 0xef, 0x51, 0xfb, 0x3e, 0xc6, 0xef, 0xde,
54 0x27, 0x3f, 0xfa, 0x57, 0x2d, 0xa7, 0x1d, 0x80, 0x46, 0x9a, 0x5f, 0x14, 0xb3, 0xb0, 0x2c, 0xbe,
55 0x72, 0xca, 0xdf, 0xb2, 0xff, 0x36, 0x5b, 0x4f, 0xec, 0x58, 0x8e, 0x8d, 0x01, 0xe9, 0xa9, 0xdf,
56 0xb5, 0x60, 0xad, 0x52, 0x4d, 0xfc, 0xa9, 0x3e, 0x8d, 0x35, 0x95, 0xb3, 0x4e, 0x0f, 0xca, 0x45,
57 0x1b, 0xf7, 0xef, 0x3a, 0x88, 0x25, 0x08, 0xc7, 0x4e, 0x06, 0xc1, 0x62, 0x1a, 0xce, 0xd8, 0x77,
58 0xbd, 0x02, 0x65, 0xf8, 0x49, 0xfb, 0xce, 0xf6, 0xa8, 0x09, 0xfc, 0xde, 0xb2, 0x09, 0x9d, 0x39,
59 0xf8, 0x63, 0x9c, 0x32, 0x42, 0x7c, 0xa0, 0x30, 0x86, 0x72, 0x7a, 0x4a, 0xc6, 0xd4, 0xb3, 0x2d,
60 0x24, 0xef, 0x96, 0x3f, 0xc2, 0xda, 0xd3, 0xf2, 0x15, 0x6f, 0xda, 0x65, 0x4b, 0x81, 0x28, 0x68,
61 0xf4, 0xfe, 0x3e, 0x71, 0x4f, 0x50, 0x96, 0x72, 0x58, 0xa1, 0x89, 0xdd, 0x01, 0x61, 0x39, 0x39,
62 0xc6, 0x76, 0xa4, 0xda, 0x02, 0x70, 0x3d, 0xc0, 0xdc, 0x8d, 0x70, 0x72, 0x04, 0x90, 0x79, 0xd4,
63 0xec, 0x65, 0xcf, 0x49, 0x35, 0x25, 0x3a, 0x14, 0x1a, 0x45, 0x20, 0xeb, 0x31, 0xaf, 0x92, 0xba,
64 0x20, 0xd3, 0xcd, 0xa7, 0x13, 0x44, 0xdc, 0xcf, 0xf0, 0x27, 0x34, 0xb9, 0xe7, 0x24, 0x6f, 0x73,
65 0xe7, 0xea, 0x77, 0x03,
68 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*dnskey
= NULL
, *ds1
= NULL
, *ds2
= NULL
;
70 /* The two DS RRs in effect for nasa.gov on 2015-12-01. */
71 ds1
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DS
, "nasa.gov");
74 ds1
->ds
.key_tag
= 47857;
75 ds1
->ds
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
76 ds1
->ds
.digest_type
= DNSSEC_DIGEST_SHA1
;
77 ds1
->ds
.digest_size
= sizeof(ds1_fprint
);
78 ds1
->ds
.digest
= memdup(ds1_fprint
, ds1
->ds
.digest_size
);
79 assert_se(ds1
->ds
.digest
);
81 log_info("DS1: %s", strna(dns_resource_record_to_string(ds1
)));
83 ds2
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DS
, "NASA.GOV");
86 ds2
->ds
.key_tag
= 47857;
87 ds2
->ds
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
88 ds2
->ds
.digest_type
= DNSSEC_DIGEST_SHA256
;
89 ds2
->ds
.digest_size
= sizeof(ds2_fprint
);
90 ds2
->ds
.digest
= memdup(ds2_fprint
, ds2
->ds
.digest_size
);
91 assert_se(ds2
->ds
.digest
);
93 log_info("DS2: %s", strna(dns_resource_record_to_string(ds2
)));
95 dnskey
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DNSKEY
, "nasa.GOV");
98 dnskey
->dnskey
.flags
= 257;
99 dnskey
->dnskey
.protocol
= 3;
100 dnskey
->dnskey
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
101 dnskey
->dnskey
.key_size
= sizeof(dnskey_blob
);
102 dnskey
->dnskey
.key
= memdup(dnskey_blob
, sizeof(dnskey_blob
));
103 assert_se(dnskey
->dnskey
.key
);
105 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey
)));
106 log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey
, false));
108 assert_se(dnssec_verify_dnskey_by_ds(dnskey
, ds1
, false) > 0);
109 assert_se(dnssec_verify_dnskey_by_ds(dnskey
, ds2
, false) > 0);
112 static void test_dnssec_verify_rfc8080_ed25519_example1(void) {
113 static const uint8_t dnskey_blob
[] = {
114 0x97, 0x4d, 0x96, 0xa2, 0x2d, 0x22, 0x4b, 0xc0, 0x1a, 0xdb, 0x91, 0x50, 0x91, 0x47, 0x7d,
115 0x44, 0xcc, 0xd9, 0x1c, 0x9a, 0x41, 0xa1, 0x14, 0x30, 0x01, 0x01, 0x17, 0xd5, 0x2c, 0x59,
118 static const uint8_t ds_fprint
[] = {
119 0xdd, 0xa6, 0xb9, 0x69, 0xbd, 0xfb, 0x79, 0xf7, 0x1e, 0xe7, 0xb7, 0xfb, 0xdf, 0xb7, 0xdc,
120 0xd7, 0xad, 0xbb, 0xd3, 0x5d, 0xdf, 0x79, 0xed, 0x3b, 0x6d, 0xd7, 0xf6, 0xe3, 0x56, 0xdd,
121 0xd7, 0x47, 0xf7, 0x6f, 0x5f, 0x7a, 0xe1, 0xa6, 0xf9, 0xe5, 0xce, 0xfc, 0x7b, 0xbf, 0x5a,
124 static const uint8_t signature_blob
[] = {
125 0xa0, 0xbf, 0x64, 0xac, 0x9b, 0xa7, 0xef, 0x17, 0xc1, 0x38, 0x85, 0x9c, 0x18, 0x78, 0xbb,
126 0x99, 0xa8, 0x39, 0xfe, 0x17, 0x59, 0xac, 0xa5, 0xb0, 0xd7, 0x98, 0xcf, 0x1a, 0xb1, 0xe9,
127 0x8d, 0x07, 0x91, 0x02, 0xf4, 0xdd, 0xb3, 0x36, 0x8f, 0x0f, 0xe4, 0x0b, 0xb3, 0x77, 0xf1,
128 0xf0, 0x0e, 0x0c, 0xdd, 0xed, 0xb7, 0x99, 0x16, 0x7d, 0x56, 0xb6, 0xe9, 0x32, 0x78, 0x30,
129 0x72, 0xba, 0x8d, 0x02
132 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*dnskey
= NULL
, *ds
= NULL
, *mx
= NULL
,
134 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
137 dnskey
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DNSKEY
, "example.com.");
140 dnskey
->dnskey
.flags
= 257;
141 dnskey
->dnskey
.protocol
= 3;
142 dnskey
->dnskey
.algorithm
= DNSSEC_ALGORITHM_ED25519
;
143 dnskey
->dnskey
.key_size
= sizeof(dnskey_blob
);
144 dnskey
->dnskey
.key
= memdup(dnskey_blob
, sizeof(dnskey_blob
));
145 assert_se(dnskey
->dnskey
.key
);
147 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey
)));
149 ds
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DS
, "example.com.");
152 ds
->ds
.key_tag
= 3613;
153 ds
->ds
.algorithm
= DNSSEC_ALGORITHM_ED25519
;
154 ds
->ds
.digest_type
= DNSSEC_DIGEST_SHA256
;
155 ds
->ds
.digest_size
= sizeof(ds_fprint
);
156 ds
->ds
.digest
= memdup(ds_fprint
, ds
->ds
.digest_size
);
157 assert_se(ds
->ds
.digest
);
159 log_info("DS: %s", strna(dns_resource_record_to_string(ds
)));
161 mx
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_MX
, "example.com.");
164 mx
->mx
.priority
= 10;
165 mx
->mx
.exchange
= strdup("mail.example.com.");
166 assert_se(mx
->mx
.exchange
);
168 log_info("MX: %s", strna(dns_resource_record_to_string(mx
)));
170 rrsig
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_RRSIG
, "example.com.");
173 rrsig
->rrsig
.type_covered
= DNS_TYPE_MX
;
174 rrsig
->rrsig
.algorithm
= DNSSEC_ALGORITHM_ED25519
;
175 rrsig
->rrsig
.labels
= 2;
176 rrsig
->rrsig
.original_ttl
= 3600;
177 rrsig
->rrsig
.expiration
= 1440021600;
178 rrsig
->rrsig
.inception
= 1438207200;
179 rrsig
->rrsig
.key_tag
= 3613;
180 rrsig
->rrsig
.signer
= strdup("example.com.");
181 assert_se(rrsig
->rrsig
.signer
);
182 rrsig
->rrsig
.signature_size
= sizeof(signature_blob
);
183 rrsig
->rrsig
.signature
= memdup(signature_blob
, rrsig
->rrsig
.signature_size
);
184 assert_se(rrsig
->rrsig
.signature
);
186 log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig
)));
188 assert_se(dnssec_key_match_rrsig(mx
->key
, rrsig
) > 0);
189 assert_se(dnssec_rrsig_match_dnskey(rrsig
, dnskey
, false) > 0);
191 answer
= dns_answer_new(1);
193 assert_se(dns_answer_add(answer
, mx
, 0, DNS_ANSWER_AUTHENTICATED
) >= 0);
195 assert_se(dnssec_verify_rrset(answer
, mx
->key
, rrsig
, dnskey
,
196 rrsig
->rrsig
.inception
* USEC_PER_SEC
, &result
) >= 0);
197 #if GCRYPT_VERSION_NUMBER >= 0x010600
198 assert_se(result
== DNSSEC_VALIDATED
);
200 assert_se(result
== DNSSEC_UNSUPPORTED_ALGORITHM
);
204 static void test_dnssec_verify_rfc8080_ed25519_example2(void) {
205 static const uint8_t dnskey_blob
[] = {
206 0xcc, 0xf9, 0xd9, 0xfd, 0x0c, 0x04, 0x7b, 0xb4, 0xbc, 0x0b, 0x94, 0x8f, 0xcf, 0x63, 0x9f,
207 0x4b, 0x94, 0x51, 0xe3, 0x40, 0x13, 0x93, 0x6f, 0xeb, 0x62, 0x71, 0x3d, 0xc4, 0x72, 0x4,
210 static const uint8_t ds_fprint
[] = {
211 0xe3, 0x4d, 0x7b, 0xf3, 0x56, 0xfd, 0xdf, 0x87, 0xb7, 0xf7, 0x67, 0x5e, 0xe3, 0xdd, 0x9e,
212 0x73, 0xbe, 0xda, 0x7b, 0x67, 0xb5, 0xe5, 0xde, 0xf4, 0x7f, 0xae, 0x7b, 0xe5, 0xad, 0x5c,
213 0xd1, 0xb7, 0x39, 0xf5, 0xce, 0x76, 0xef, 0x97, 0x34, 0xe1, 0xe6, 0xde, 0xf3, 0x47, 0x3a,
216 static const uint8_t signature_blob
[] = {
217 0xcd, 0x74, 0x34, 0x6e, 0x46, 0x20, 0x41, 0x31, 0x05, 0xc9, 0xf2, 0xf2, 0x8b, 0xd4, 0x28,
218 0x89, 0x8e, 0x83, 0xf1, 0x97, 0x58, 0xa3, 0x8c, 0x32, 0x52, 0x15, 0x62, 0xa1, 0x86, 0x57,
219 0x15, 0xd4, 0xf8, 0xd7, 0x44, 0x0f, 0x44, 0x84, 0xd0, 0x4a, 0xa2, 0x52, 0x9f, 0x34, 0x28,
220 0x4a, 0x6e, 0x69, 0xa0, 0x9e, 0xe0, 0x0f, 0xb0, 0x10, 0x47, 0x43, 0xbb, 0x2a, 0xe2, 0x39,
221 0x93, 0x6a, 0x5c, 0x06
224 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*dnskey
= NULL
, *ds
= NULL
, *mx
= NULL
,
226 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
229 dnskey
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DNSKEY
, "example.com.");
232 dnskey
->dnskey
.flags
= 257;
233 dnskey
->dnskey
.protocol
= 3;
234 dnskey
->dnskey
.algorithm
= DNSSEC_ALGORITHM_ED25519
;
235 dnskey
->dnskey
.key_size
= sizeof(dnskey_blob
);
236 dnskey
->dnskey
.key
= memdup(dnskey_blob
, sizeof(dnskey_blob
));
237 assert_se(dnskey
->dnskey
.key
);
239 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey
)));
241 ds
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DS
, "example.com.");
244 ds
->ds
.key_tag
= 35217;
245 ds
->ds
.algorithm
= DNSSEC_ALGORITHM_ED25519
;
246 ds
->ds
.digest_type
= DNSSEC_DIGEST_SHA256
;
247 ds
->ds
.digest_size
= sizeof(ds_fprint
);
248 ds
->ds
.digest
= memdup(ds_fprint
, ds
->ds
.digest_size
);
249 assert_se(ds
->ds
.digest
);
251 log_info("DS: %s", strna(dns_resource_record_to_string(ds
)));
253 mx
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_MX
, "example.com.");
256 mx
->mx
.priority
= 10;
257 mx
->mx
.exchange
= strdup("mail.example.com.");
258 assert_se(mx
->mx
.exchange
);
260 log_info("MX: %s", strna(dns_resource_record_to_string(mx
)));
262 rrsig
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_RRSIG
, "example.com.");
265 rrsig
->rrsig
.type_covered
= DNS_TYPE_MX
;
266 rrsig
->rrsig
.algorithm
= DNSSEC_ALGORITHM_ED25519
;
267 rrsig
->rrsig
.labels
= 2;
268 rrsig
->rrsig
.original_ttl
= 3600;
269 rrsig
->rrsig
.expiration
= 1440021600;
270 rrsig
->rrsig
.inception
= 1438207200;
271 rrsig
->rrsig
.key_tag
= 35217;
272 rrsig
->rrsig
.signer
= strdup("example.com.");
273 assert_se(rrsig
->rrsig
.signer
);
274 rrsig
->rrsig
.signature_size
= sizeof(signature_blob
);
275 rrsig
->rrsig
.signature
= memdup(signature_blob
, rrsig
->rrsig
.signature_size
);
276 assert_se(rrsig
->rrsig
.signature
);
278 log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig
)));
280 assert_se(dnssec_key_match_rrsig(mx
->key
, rrsig
) > 0);
281 assert_se(dnssec_rrsig_match_dnskey(rrsig
, dnskey
, false) > 0);
283 answer
= dns_answer_new(1);
285 assert_se(dns_answer_add(answer
, mx
, 0, DNS_ANSWER_AUTHENTICATED
) >= 0);
287 assert_se(dnssec_verify_rrset(answer
, mx
->key
, rrsig
, dnskey
,
288 rrsig
->rrsig
.inception
* USEC_PER_SEC
, &result
) >= 0);
289 #if GCRYPT_VERSION_NUMBER >= 0x010600
290 assert_se(result
== DNSSEC_VALIDATED
);
292 assert_se(result
== DNSSEC_UNSUPPORTED_ALGORITHM
);
295 static void test_dnssec_verify_rrset(void) {
297 static const uint8_t signature_blob
[] = {
298 0x7f, 0x79, 0xdd, 0x5e, 0x89, 0x79, 0x18, 0xd0, 0x34, 0x86, 0x8c, 0x72, 0x77, 0x75, 0x48, 0x4d,
299 0xc3, 0x7d, 0x38, 0x04, 0xab, 0xcd, 0x9e, 0x4c, 0x82, 0xb0, 0x92, 0xca, 0xe9, 0x66, 0xe9, 0x6e,
300 0x47, 0xc7, 0x68, 0x8c, 0x94, 0xf6, 0x69, 0xcb, 0x75, 0x94, 0xe6, 0x30, 0xa6, 0xfb, 0x68, 0x64,
301 0x96, 0x1a, 0x84, 0xe1, 0xdc, 0x16, 0x4c, 0x83, 0x6c, 0x44, 0xf2, 0x74, 0x4d, 0x74, 0x79, 0x8f,
302 0xf3, 0xf4, 0x63, 0x0d, 0xef, 0x5a, 0xe7, 0xe2, 0xfd, 0xf2, 0x2b, 0x38, 0x7c, 0x28, 0x96, 0x9d,
303 0xb6, 0xcd, 0x5c, 0x3b, 0x57, 0xe2, 0x24, 0x78, 0x65, 0xd0, 0x9e, 0x77, 0x83, 0x09, 0x6c, 0xff,
304 0x3d, 0x52, 0x3f, 0x6e, 0xd1, 0xed, 0x2e, 0xf9, 0xee, 0x8e, 0xa6, 0xbe, 0x9a, 0xa8, 0x87, 0x76,
305 0xd8, 0x77, 0xcc, 0x96, 0xa0, 0x98, 0xa1, 0xd1, 0x68, 0x09, 0x43, 0xcf, 0x56, 0xd9, 0xd1, 0x66,
308 static const uint8_t dnskey_blob
[] = {
309 0x03, 0x01, 0x00, 0x01, 0x9b, 0x49, 0x9b, 0xc1, 0xf9, 0x9a, 0xe0, 0x4e, 0xcf, 0xcb, 0x14, 0x45,
310 0x2e, 0xc9, 0xf9, 0x74, 0xa7, 0x18, 0xb5, 0xf3, 0xde, 0x39, 0x49, 0xdf, 0x63, 0x33, 0x97, 0x52,
311 0xe0, 0x8e, 0xac, 0x50, 0x30, 0x8e, 0x09, 0xd5, 0x24, 0x3d, 0x26, 0xa4, 0x49, 0x37, 0x2b, 0xb0,
312 0x6b, 0x1b, 0xdf, 0xde, 0x85, 0x83, 0xcb, 0x22, 0x4e, 0x60, 0x0a, 0x91, 0x1a, 0x1f, 0xc5, 0x40,
313 0xb1, 0xc3, 0x15, 0xc1, 0x54, 0x77, 0x86, 0x65, 0x53, 0xec, 0x10, 0x90, 0x0c, 0x91, 0x00, 0x5e,
314 0x15, 0xdc, 0x08, 0x02, 0x4c, 0x8c, 0x0d, 0xc0, 0xac, 0x6e, 0xc4, 0x3e, 0x1b, 0x80, 0x19, 0xe4,
315 0xf7, 0x5f, 0x77, 0x51, 0x06, 0x87, 0x61, 0xde, 0xa2, 0x18, 0x0f, 0x40, 0x8b, 0x79, 0x72, 0xfa,
316 0x8d, 0x1a, 0x44, 0x47, 0x0d, 0x8e, 0x3a, 0x2d, 0xc7, 0x39, 0xbf, 0x56, 0x28, 0x97, 0xd9, 0x20,
317 0x4f, 0x00, 0x51, 0x3b,
320 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*a
= NULL
, *rrsig
= NULL
, *dnskey
= NULL
;
321 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
324 a
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_A
, "nAsA.gov");
327 a
->a
.in_addr
.s_addr
= inet_addr("52.0.14.116");
329 log_info("A: %s", strna(dns_resource_record_to_string(a
)));
331 rrsig
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_RRSIG
, "NaSa.GOV.");
334 rrsig
->rrsig
.type_covered
= DNS_TYPE_A
;
335 rrsig
->rrsig
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
336 rrsig
->rrsig
.labels
= 2;
337 rrsig
->rrsig
.original_ttl
= 600;
338 rrsig
->rrsig
.expiration
= 0x5683135c;
339 rrsig
->rrsig
.inception
= 0x565b7da8;
340 rrsig
->rrsig
.key_tag
= 63876;
341 rrsig
->rrsig
.signer
= strdup("Nasa.Gov.");
342 assert_se(rrsig
->rrsig
.signer
);
343 rrsig
->rrsig
.signature_size
= sizeof(signature_blob
);
344 rrsig
->rrsig
.signature
= memdup(signature_blob
, rrsig
->rrsig
.signature_size
);
345 assert_se(rrsig
->rrsig
.signature
);
347 log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig
)));
349 dnskey
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DNSKEY
, "nASA.gOV");
352 dnskey
->dnskey
.flags
= 256;
353 dnskey
->dnskey
.protocol
= 3;
354 dnskey
->dnskey
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
355 dnskey
->dnskey
.key_size
= sizeof(dnskey_blob
);
356 dnskey
->dnskey
.key
= memdup(dnskey_blob
, sizeof(dnskey_blob
));
357 assert_se(dnskey
->dnskey
.key
);
359 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey
)));
360 log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey
, false));
362 assert_se(dnssec_key_match_rrsig(a
->key
, rrsig
) > 0);
363 assert_se(dnssec_rrsig_match_dnskey(rrsig
, dnskey
, false) > 0);
365 answer
= dns_answer_new(1);
367 assert_se(dns_answer_add(answer
, a
, 0, DNS_ANSWER_AUTHENTICATED
) >= 0);
369 /* Validate the RR as it if was 2015-12-2 today */
370 assert_se(dnssec_verify_rrset(answer
, a
->key
, rrsig
, dnskey
, 1449092754*USEC_PER_SEC
, &result
) >= 0);
371 assert_se(result
== DNSSEC_VALIDATED
);
374 static void test_dnssec_verify_rrset2(void) {
376 static const uint8_t signature_blob
[] = {
377 0x48, 0x45, 0xc8, 0x8b, 0xc0, 0x14, 0x92, 0xf5, 0x15, 0xc6, 0x84, 0x9d, 0x2f, 0xe3, 0x32, 0x11,
378 0x7d, 0xf1, 0xe6, 0x87, 0xb9, 0x42, 0xd3, 0x8b, 0x9e, 0xaf, 0x92, 0x31, 0x0a, 0x53, 0xad, 0x8b,
379 0xa7, 0x5c, 0x83, 0x39, 0x8c, 0x28, 0xac, 0xce, 0x6e, 0x9c, 0x18, 0xe3, 0x31, 0x16, 0x6e, 0xca,
380 0x38, 0x31, 0xaf, 0xd9, 0x94, 0xf1, 0x84, 0xb1, 0xdf, 0x5a, 0xc2, 0x73, 0x22, 0xf6, 0xcb, 0xa2,
381 0xe7, 0x8c, 0x77, 0x0c, 0x74, 0x2f, 0xc2, 0x13, 0xb0, 0x93, 0x51, 0xa9, 0x4f, 0xae, 0x0a, 0xda,
382 0x45, 0xcc, 0xfd, 0x43, 0x99, 0x36, 0x9a, 0x0d, 0x21, 0xe0, 0xeb, 0x30, 0x65, 0xd4, 0xa0, 0x27,
383 0x37, 0x3b, 0xe4, 0xc1, 0xc5, 0xa1, 0x2a, 0xd1, 0x76, 0xc4, 0x7e, 0x64, 0x0e, 0x5a, 0xa6, 0x50,
384 0x24, 0xd5, 0x2c, 0xcc, 0x6d, 0xe5, 0x37, 0xea, 0xbd, 0x09, 0x34, 0xed, 0x24, 0x06, 0xa1, 0x22,
387 static const uint8_t dnskey_blob
[] = {
388 0x03, 0x01, 0x00, 0x01, 0xc3, 0x7f, 0x1d, 0xd1, 0x1c, 0x97, 0xb1, 0x13, 0x34, 0x3a, 0x9a, 0xea,
389 0xee, 0xd9, 0x5a, 0x11, 0x1b, 0x17, 0xc7, 0xe3, 0xd4, 0xda, 0x20, 0xbc, 0x5d, 0xba, 0x74, 0xe3,
390 0x37, 0x99, 0xec, 0x25, 0xce, 0x93, 0x7f, 0xbd, 0x22, 0x73, 0x7e, 0x14, 0x71, 0xe0, 0x60, 0x07,
391 0xd4, 0x39, 0x8b, 0x5e, 0xe9, 0xba, 0x25, 0xe8, 0x49, 0xe9, 0x34, 0xef, 0xfe, 0x04, 0x5c, 0xa5,
392 0x27, 0xcd, 0xa9, 0xda, 0x70, 0x05, 0x21, 0xab, 0x15, 0x82, 0x24, 0xc3, 0x94, 0xf5, 0xd7, 0xb7,
393 0xc4, 0x66, 0xcb, 0x32, 0x6e, 0x60, 0x2b, 0x55, 0x59, 0x28, 0x89, 0x8a, 0x72, 0xde, 0x88, 0x56,
394 0x27, 0x95, 0xd9, 0xac, 0x88, 0x4f, 0x65, 0x2b, 0x68, 0xfc, 0xe6, 0x41, 0xc1, 0x1b, 0xef, 0x4e,
395 0xd6, 0xc2, 0x0f, 0x64, 0x88, 0x95, 0x5e, 0xdd, 0x3a, 0x02, 0x07, 0x50, 0xa9, 0xda, 0xa4, 0x49,
396 0x74, 0x62, 0xfe, 0xd7,
399 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*nsec
= NULL
, *rrsig
= NULL
, *dnskey
= NULL
;
400 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
403 nsec
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_NSEC
, "nasa.gov");
406 nsec
->nsec
.next_domain_name
= strdup("3D-Printing.nasa.gov");
407 assert_se(nsec
->nsec
.next_domain_name
);
409 nsec
->nsec
.types
= bitmap_new();
410 assert_se(nsec
->nsec
.types
);
411 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_A
) >= 0);
412 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_NS
) >= 0);
413 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_SOA
) >= 0);
414 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_MX
) >= 0);
415 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_TXT
) >= 0);
416 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_RRSIG
) >= 0);
417 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_NSEC
) >= 0);
418 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_DNSKEY
) >= 0);
419 assert_se(bitmap_set(nsec
->nsec
.types
, 65534) >= 0);
421 log_info("NSEC: %s", strna(dns_resource_record_to_string(nsec
)));
423 rrsig
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_RRSIG
, "NaSa.GOV.");
426 rrsig
->rrsig
.type_covered
= DNS_TYPE_NSEC
;
427 rrsig
->rrsig
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
428 rrsig
->rrsig
.labels
= 2;
429 rrsig
->rrsig
.original_ttl
= 300;
430 rrsig
->rrsig
.expiration
= 0x5689002f;
431 rrsig
->rrsig
.inception
= 0x56617230;
432 rrsig
->rrsig
.key_tag
= 30390;
433 rrsig
->rrsig
.signer
= strdup("Nasa.Gov.");
434 assert_se(rrsig
->rrsig
.signer
);
435 rrsig
->rrsig
.signature_size
= sizeof(signature_blob
);
436 rrsig
->rrsig
.signature
= memdup(signature_blob
, rrsig
->rrsig
.signature_size
);
437 assert_se(rrsig
->rrsig
.signature
);
439 log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig
)));
441 dnskey
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DNSKEY
, "nASA.gOV");
444 dnskey
->dnskey
.flags
= 256;
445 dnskey
->dnskey
.protocol
= 3;
446 dnskey
->dnskey
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
447 dnskey
->dnskey
.key_size
= sizeof(dnskey_blob
);
448 dnskey
->dnskey
.key
= memdup(dnskey_blob
, sizeof(dnskey_blob
));
449 assert_se(dnskey
->dnskey
.key
);
451 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey
)));
452 log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey
, false));
454 assert_se(dnssec_key_match_rrsig(nsec
->key
, rrsig
) > 0);
455 assert_se(dnssec_rrsig_match_dnskey(rrsig
, dnskey
, false) > 0);
457 answer
= dns_answer_new(1);
459 assert_se(dns_answer_add(answer
, nsec
, 0, DNS_ANSWER_AUTHENTICATED
) >= 0);
461 /* Validate the RR as it if was 2015-12-11 today */
462 assert_se(dnssec_verify_rrset(answer
, nsec
->key
, rrsig
, dnskey
, 1449849318*USEC_PER_SEC
, &result
) >= 0);
463 assert_se(result
== DNSSEC_VALIDATED
);
466 static void test_dnssec_nsec3_hash(void) {
467 static const uint8_t salt
[] = { 0xB0, 0x1D, 0xFA, 0xCE };
468 static const uint8_t next_hashed_name
[] = { 0x84, 0x10, 0x26, 0x53, 0xc9, 0xfa, 0x4d, 0x85, 0x6c, 0x97, 0x82, 0xe2, 0x8f, 0xdf, 0x2d, 0x5e, 0x87, 0x69, 0xc4, 0x52 };
469 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
470 uint8_t h
[DNSSEC_HASH_SIZE_MAX
];
471 _cleanup_free_
char *b
= NULL
;
474 /* The NSEC3 RR for eurid.eu on 2015-12-14. */
475 rr
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_NSEC3
, "PJ8S08RR45VIQDAQGE7EN3VHKNROTBMM.eurid.eu.");
478 rr
->nsec3
.algorithm
= DNSSEC_DIGEST_SHA1
;
480 rr
->nsec3
.iterations
= 1;
481 rr
->nsec3
.salt
= memdup(salt
, sizeof(salt
));
482 assert_se(rr
->nsec3
.salt
);
483 rr
->nsec3
.salt_size
= sizeof(salt
);
484 rr
->nsec3
.next_hashed_name
= memdup(next_hashed_name
, sizeof(next_hashed_name
));
485 assert_se(rr
->nsec3
.next_hashed_name
);
486 rr
->nsec3
.next_hashed_name_size
= sizeof(next_hashed_name
);
488 log_info("NSEC3: %s", strna(dns_resource_record_to_string(rr
)));
490 k
= dnssec_nsec3_hash(rr
, "eurid.eu", &h
);
493 b
= base32hexmem(h
, k
, false);
495 assert_se(strcasecmp(b
, "PJ8S08RR45VIQDAQGE7EN3VHKNROTBMM") == 0);
500 int main(int argc
, char *argv
[]) {
502 test_dnssec_canonicalize();
505 test_dnssec_verify_dns_key();
506 test_dnssec_verify_rfc8080_ed25519_example1();
507 test_dnssec_verify_rfc8080_ed25519_example2();
508 test_dnssec_verify_rrset();
509 test_dnssec_verify_rrset2();
510 test_dnssec_nsec3_hash();