1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright 2015 Lennart Poettering
10 #include <netinet/in.h>
11 #include <sys/socket.h>
13 #include "alloc-util.h"
14 #include "resolved-dns-dnssec.h"
15 #include "resolved-dns-rr.h"
16 #include "string-util.h"
17 #include "hexdecoct.h"
19 static void test_dnssec_canonicalize_one(const char *original
, const char *canonical
, int r
) {
20 char canonicalized
[DNSSEC_CANONICAL_HOSTNAME_MAX
];
22 assert_se(dnssec_canonicalize(original
, canonicalized
, sizeof(canonicalized
)) == r
);
26 assert_se(streq(canonicalized
, canonical
));
29 static void test_dnssec_canonicalize(void) {
30 test_dnssec_canonicalize_one("", ".", 1);
31 test_dnssec_canonicalize_one(".", ".", 1);
32 test_dnssec_canonicalize_one("foo", "foo.", 4);
33 test_dnssec_canonicalize_one("foo.", "foo.", 4);
34 test_dnssec_canonicalize_one("FOO.", "foo.", 4);
35 test_dnssec_canonicalize_one("FOO.bar.", "foo.bar.", 8);
36 test_dnssec_canonicalize_one("FOO..bar.", NULL
, -EINVAL
);
41 static void test_dnssec_verify_dns_key(void) {
43 static const uint8_t ds1_fprint
[] = {
44 0x46, 0x8B, 0xC8, 0xDD, 0xC7, 0xE8, 0x27, 0x03, 0x40, 0xBB, 0x8A, 0x1F, 0x3B, 0x2E, 0x45, 0x9D,
45 0x80, 0x67, 0x14, 0x01,
47 static const uint8_t ds2_fprint
[] = {
48 0x8A, 0xEE, 0x80, 0x47, 0x05, 0x5F, 0x83, 0xD1, 0x48, 0xBA, 0x8F, 0xF6, 0xDD, 0xA7, 0x60, 0xCE,
49 0x94, 0xF7, 0xC7, 0x5E, 0x52, 0x4C, 0xF2, 0xE9, 0x50, 0xB9, 0x2E, 0xCB, 0xEF, 0x96, 0xB9, 0x98,
51 static const uint8_t dnskey_blob
[] = {
52 0x03, 0x01, 0x00, 0x01, 0xa8, 0x12, 0xda, 0x4f, 0xd2, 0x7d, 0x54, 0x14, 0x0e, 0xcc, 0x5b, 0x5e,
53 0x45, 0x9c, 0x96, 0x98, 0xc0, 0xc0, 0x85, 0x81, 0xb1, 0x47, 0x8c, 0x7d, 0xe8, 0x39, 0x50, 0xcc,
54 0xc5, 0xd0, 0xf2, 0x00, 0x81, 0x67, 0x79, 0xf6, 0xcc, 0x9d, 0xad, 0x6c, 0xbb, 0x7b, 0x6f, 0x48,
55 0x97, 0x15, 0x1c, 0xfd, 0x0b, 0xfe, 0xd3, 0xd7, 0x7d, 0x9f, 0x81, 0x26, 0xd3, 0xc5, 0x65, 0x49,
56 0xcf, 0x46, 0x62, 0xb0, 0x55, 0x6e, 0x47, 0xc7, 0x30, 0xef, 0x51, 0xfb, 0x3e, 0xc6, 0xef, 0xde,
57 0x27, 0x3f, 0xfa, 0x57, 0x2d, 0xa7, 0x1d, 0x80, 0x46, 0x9a, 0x5f, 0x14, 0xb3, 0xb0, 0x2c, 0xbe,
58 0x72, 0xca, 0xdf, 0xb2, 0xff, 0x36, 0x5b, 0x4f, 0xec, 0x58, 0x8e, 0x8d, 0x01, 0xe9, 0xa9, 0xdf,
59 0xb5, 0x60, 0xad, 0x52, 0x4d, 0xfc, 0xa9, 0x3e, 0x8d, 0x35, 0x95, 0xb3, 0x4e, 0x0f, 0xca, 0x45,
60 0x1b, 0xf7, 0xef, 0x3a, 0x88, 0x25, 0x08, 0xc7, 0x4e, 0x06, 0xc1, 0x62, 0x1a, 0xce, 0xd8, 0x77,
61 0xbd, 0x02, 0x65, 0xf8, 0x49, 0xfb, 0xce, 0xf6, 0xa8, 0x09, 0xfc, 0xde, 0xb2, 0x09, 0x9d, 0x39,
62 0xf8, 0x63, 0x9c, 0x32, 0x42, 0x7c, 0xa0, 0x30, 0x86, 0x72, 0x7a, 0x4a, 0xc6, 0xd4, 0xb3, 0x2d,
63 0x24, 0xef, 0x96, 0x3f, 0xc2, 0xda, 0xd3, 0xf2, 0x15, 0x6f, 0xda, 0x65, 0x4b, 0x81, 0x28, 0x68,
64 0xf4, 0xfe, 0x3e, 0x71, 0x4f, 0x50, 0x96, 0x72, 0x58, 0xa1, 0x89, 0xdd, 0x01, 0x61, 0x39, 0x39,
65 0xc6, 0x76, 0xa4, 0xda, 0x02, 0x70, 0x3d, 0xc0, 0xdc, 0x8d, 0x70, 0x72, 0x04, 0x90, 0x79, 0xd4,
66 0xec, 0x65, 0xcf, 0x49, 0x35, 0x25, 0x3a, 0x14, 0x1a, 0x45, 0x20, 0xeb, 0x31, 0xaf, 0x92, 0xba,
67 0x20, 0xd3, 0xcd, 0xa7, 0x13, 0x44, 0xdc, 0xcf, 0xf0, 0x27, 0x34, 0xb9, 0xe7, 0x24, 0x6f, 0x73,
68 0xe7, 0xea, 0x77, 0x03,
71 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*dnskey
= NULL
, *ds1
= NULL
, *ds2
= NULL
;
73 /* The two DS RRs in effect for nasa.gov on 2015-12-01. */
74 ds1
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DS
, "nasa.gov");
77 ds1
->ds
.key_tag
= 47857;
78 ds1
->ds
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
79 ds1
->ds
.digest_type
= DNSSEC_DIGEST_SHA1
;
80 ds1
->ds
.digest_size
= sizeof(ds1_fprint
);
81 ds1
->ds
.digest
= memdup(ds1_fprint
, ds1
->ds
.digest_size
);
82 assert_se(ds1
->ds
.digest
);
84 log_info("DS1: %s", strna(dns_resource_record_to_string(ds1
)));
86 ds2
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DS
, "NASA.GOV");
89 ds2
->ds
.key_tag
= 47857;
90 ds2
->ds
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
91 ds2
->ds
.digest_type
= DNSSEC_DIGEST_SHA256
;
92 ds2
->ds
.digest_size
= sizeof(ds2_fprint
);
93 ds2
->ds
.digest
= memdup(ds2_fprint
, ds2
->ds
.digest_size
);
94 assert_se(ds2
->ds
.digest
);
96 log_info("DS2: %s", strna(dns_resource_record_to_string(ds2
)));
98 dnskey
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DNSKEY
, "nasa.GOV");
101 dnskey
->dnskey
.flags
= 257;
102 dnskey
->dnskey
.protocol
= 3;
103 dnskey
->dnskey
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
104 dnskey
->dnskey
.key_size
= sizeof(dnskey_blob
);
105 dnskey
->dnskey
.key
= memdup(dnskey_blob
, sizeof(dnskey_blob
));
106 assert_se(dnskey
->dnskey
.key
);
108 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey
)));
109 log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey
, false));
111 assert_se(dnssec_verify_dnskey_by_ds(dnskey
, ds1
, false) > 0);
112 assert_se(dnssec_verify_dnskey_by_ds(dnskey
, ds2
, false) > 0);
115 static void test_dnssec_verify_rfc8080_ed25519_example1(void) {
116 static const uint8_t dnskey_blob
[] = {
117 0x97, 0x4d, 0x96, 0xa2, 0x2d, 0x22, 0x4b, 0xc0, 0x1a, 0xdb, 0x91, 0x50, 0x91, 0x47, 0x7d,
118 0x44, 0xcc, 0xd9, 0x1c, 0x9a, 0x41, 0xa1, 0x14, 0x30, 0x01, 0x01, 0x17, 0xd5, 0x2c, 0x59,
121 static const uint8_t ds_fprint
[] = {
122 0xdd, 0xa6, 0xb9, 0x69, 0xbd, 0xfb, 0x79, 0xf7, 0x1e, 0xe7, 0xb7, 0xfb, 0xdf, 0xb7, 0xdc,
123 0xd7, 0xad, 0xbb, 0xd3, 0x5d, 0xdf, 0x79, 0xed, 0x3b, 0x6d, 0xd7, 0xf6, 0xe3, 0x56, 0xdd,
124 0xd7, 0x47, 0xf7, 0x6f, 0x5f, 0x7a, 0xe1, 0xa6, 0xf9, 0xe5, 0xce, 0xfc, 0x7b, 0xbf, 0x5a,
127 static const uint8_t signature_blob
[] = {
128 0xa0, 0xbf, 0x64, 0xac, 0x9b, 0xa7, 0xef, 0x17, 0xc1, 0x38, 0x85, 0x9c, 0x18, 0x78, 0xbb,
129 0x99, 0xa8, 0x39, 0xfe, 0x17, 0x59, 0xac, 0xa5, 0xb0, 0xd7, 0x98, 0xcf, 0x1a, 0xb1, 0xe9,
130 0x8d, 0x07, 0x91, 0x02, 0xf4, 0xdd, 0xb3, 0x36, 0x8f, 0x0f, 0xe4, 0x0b, 0xb3, 0x77, 0xf1,
131 0xf0, 0x0e, 0x0c, 0xdd, 0xed, 0xb7, 0x99, 0x16, 0x7d, 0x56, 0xb6, 0xe9, 0x32, 0x78, 0x30,
132 0x72, 0xba, 0x8d, 0x02
135 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*dnskey
= NULL
, *ds
= NULL
, *mx
= NULL
,
137 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
140 dnskey
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DNSKEY
, "example.com.");
143 dnskey
->dnskey
.flags
= 257;
144 dnskey
->dnskey
.protocol
= 3;
145 dnskey
->dnskey
.algorithm
= DNSSEC_ALGORITHM_ED25519
;
146 dnskey
->dnskey
.key_size
= sizeof(dnskey_blob
);
147 dnskey
->dnskey
.key
= memdup(dnskey_blob
, sizeof(dnskey_blob
));
148 assert_se(dnskey
->dnskey
.key
);
150 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey
)));
152 ds
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DS
, "example.com.");
155 ds
->ds
.key_tag
= 3613;
156 ds
->ds
.algorithm
= DNSSEC_ALGORITHM_ED25519
;
157 ds
->ds
.digest_type
= DNSSEC_DIGEST_SHA256
;
158 ds
->ds
.digest_size
= sizeof(ds_fprint
);
159 ds
->ds
.digest
= memdup(ds_fprint
, ds
->ds
.digest_size
);
160 assert_se(ds
->ds
.digest
);
162 log_info("DS: %s", strna(dns_resource_record_to_string(ds
)));
164 mx
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_MX
, "example.com.");
167 mx
->mx
.priority
= 10;
168 mx
->mx
.exchange
= strdup("mail.example.com.");
169 assert_se(mx
->mx
.exchange
);
171 log_info("MX: %s", strna(dns_resource_record_to_string(mx
)));
173 rrsig
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_RRSIG
, "example.com.");
176 rrsig
->rrsig
.type_covered
= DNS_TYPE_MX
;
177 rrsig
->rrsig
.algorithm
= DNSSEC_ALGORITHM_ED25519
;
178 rrsig
->rrsig
.labels
= 2;
179 rrsig
->rrsig
.original_ttl
= 3600;
180 rrsig
->rrsig
.expiration
= 1440021600;
181 rrsig
->rrsig
.inception
= 1438207200;
182 rrsig
->rrsig
.key_tag
= 3613;
183 rrsig
->rrsig
.signer
= strdup("example.com.");
184 assert_se(rrsig
->rrsig
.signer
);
185 rrsig
->rrsig
.signature_size
= sizeof(signature_blob
);
186 rrsig
->rrsig
.signature
= memdup(signature_blob
, rrsig
->rrsig
.signature_size
);
187 assert_se(rrsig
->rrsig
.signature
);
189 log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig
)));
191 assert_se(dnssec_key_match_rrsig(mx
->key
, rrsig
) > 0);
192 assert_se(dnssec_rrsig_match_dnskey(rrsig
, dnskey
, false) > 0);
194 answer
= dns_answer_new(1);
196 assert_se(dns_answer_add(answer
, mx
, 0, DNS_ANSWER_AUTHENTICATED
) >= 0);
198 assert_se(dnssec_verify_rrset(answer
, mx
->key
, rrsig
, dnskey
,
199 rrsig
->rrsig
.inception
* USEC_PER_SEC
, &result
) >= 0);
200 #if GCRYPT_VERSION_NUMBER >= 0x010600
201 assert_se(result
== DNSSEC_VALIDATED
);
203 assert_se(result
== DNSSEC_UNSUPPORTED_ALGORITHM
);
207 static void test_dnssec_verify_rfc8080_ed25519_example2(void) {
208 static const uint8_t dnskey_blob
[] = {
209 0xcc, 0xf9, 0xd9, 0xfd, 0x0c, 0x04, 0x7b, 0xb4, 0xbc, 0x0b, 0x94, 0x8f, 0xcf, 0x63, 0x9f,
210 0x4b, 0x94, 0x51, 0xe3, 0x40, 0x13, 0x93, 0x6f, 0xeb, 0x62, 0x71, 0x3d, 0xc4, 0x72, 0x4,
213 static const uint8_t ds_fprint
[] = {
214 0xe3, 0x4d, 0x7b, 0xf3, 0x56, 0xfd, 0xdf, 0x87, 0xb7, 0xf7, 0x67, 0x5e, 0xe3, 0xdd, 0x9e,
215 0x73, 0xbe, 0xda, 0x7b, 0x67, 0xb5, 0xe5, 0xde, 0xf4, 0x7f, 0xae, 0x7b, 0xe5, 0xad, 0x5c,
216 0xd1, 0xb7, 0x39, 0xf5, 0xce, 0x76, 0xef, 0x97, 0x34, 0xe1, 0xe6, 0xde, 0xf3, 0x47, 0x3a,
219 static const uint8_t signature_blob
[] = {
220 0xcd, 0x74, 0x34, 0x6e, 0x46, 0x20, 0x41, 0x31, 0x05, 0xc9, 0xf2, 0xf2, 0x8b, 0xd4, 0x28,
221 0x89, 0x8e, 0x83, 0xf1, 0x97, 0x58, 0xa3, 0x8c, 0x32, 0x52, 0x15, 0x62, 0xa1, 0x86, 0x57,
222 0x15, 0xd4, 0xf8, 0xd7, 0x44, 0x0f, 0x44, 0x84, 0xd0, 0x4a, 0xa2, 0x52, 0x9f, 0x34, 0x28,
223 0x4a, 0x6e, 0x69, 0xa0, 0x9e, 0xe0, 0x0f, 0xb0, 0x10, 0x47, 0x43, 0xbb, 0x2a, 0xe2, 0x39,
224 0x93, 0x6a, 0x5c, 0x06
227 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*dnskey
= NULL
, *ds
= NULL
, *mx
= NULL
,
229 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
232 dnskey
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DNSKEY
, "example.com.");
235 dnskey
->dnskey
.flags
= 257;
236 dnskey
->dnskey
.protocol
= 3;
237 dnskey
->dnskey
.algorithm
= DNSSEC_ALGORITHM_ED25519
;
238 dnskey
->dnskey
.key_size
= sizeof(dnskey_blob
);
239 dnskey
->dnskey
.key
= memdup(dnskey_blob
, sizeof(dnskey_blob
));
240 assert_se(dnskey
->dnskey
.key
);
242 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey
)));
244 ds
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DS
, "example.com.");
247 ds
->ds
.key_tag
= 35217;
248 ds
->ds
.algorithm
= DNSSEC_ALGORITHM_ED25519
;
249 ds
->ds
.digest_type
= DNSSEC_DIGEST_SHA256
;
250 ds
->ds
.digest_size
= sizeof(ds_fprint
);
251 ds
->ds
.digest
= memdup(ds_fprint
, ds
->ds
.digest_size
);
252 assert_se(ds
->ds
.digest
);
254 log_info("DS: %s", strna(dns_resource_record_to_string(ds
)));
256 mx
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_MX
, "example.com.");
259 mx
->mx
.priority
= 10;
260 mx
->mx
.exchange
= strdup("mail.example.com.");
261 assert_se(mx
->mx
.exchange
);
263 log_info("MX: %s", strna(dns_resource_record_to_string(mx
)));
265 rrsig
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_RRSIG
, "example.com.");
268 rrsig
->rrsig
.type_covered
= DNS_TYPE_MX
;
269 rrsig
->rrsig
.algorithm
= DNSSEC_ALGORITHM_ED25519
;
270 rrsig
->rrsig
.labels
= 2;
271 rrsig
->rrsig
.original_ttl
= 3600;
272 rrsig
->rrsig
.expiration
= 1440021600;
273 rrsig
->rrsig
.inception
= 1438207200;
274 rrsig
->rrsig
.key_tag
= 35217;
275 rrsig
->rrsig
.signer
= strdup("example.com.");
276 assert_se(rrsig
->rrsig
.signer
);
277 rrsig
->rrsig
.signature_size
= sizeof(signature_blob
);
278 rrsig
->rrsig
.signature
= memdup(signature_blob
, rrsig
->rrsig
.signature_size
);
279 assert_se(rrsig
->rrsig
.signature
);
281 log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig
)));
283 assert_se(dnssec_key_match_rrsig(mx
->key
, rrsig
) > 0);
284 assert_se(dnssec_rrsig_match_dnskey(rrsig
, dnskey
, false) > 0);
286 answer
= dns_answer_new(1);
288 assert_se(dns_answer_add(answer
, mx
, 0, DNS_ANSWER_AUTHENTICATED
) >= 0);
290 assert_se(dnssec_verify_rrset(answer
, mx
->key
, rrsig
, dnskey
,
291 rrsig
->rrsig
.inception
* USEC_PER_SEC
, &result
) >= 0);
292 #if GCRYPT_VERSION_NUMBER >= 0x010600
293 assert_se(result
== DNSSEC_VALIDATED
);
295 assert_se(result
== DNSSEC_UNSUPPORTED_ALGORITHM
);
298 static void test_dnssec_verify_rrset(void) {
300 static const uint8_t signature_blob
[] = {
301 0x7f, 0x79, 0xdd, 0x5e, 0x89, 0x79, 0x18, 0xd0, 0x34, 0x86, 0x8c, 0x72, 0x77, 0x75, 0x48, 0x4d,
302 0xc3, 0x7d, 0x38, 0x04, 0xab, 0xcd, 0x9e, 0x4c, 0x82, 0xb0, 0x92, 0xca, 0xe9, 0x66, 0xe9, 0x6e,
303 0x47, 0xc7, 0x68, 0x8c, 0x94, 0xf6, 0x69, 0xcb, 0x75, 0x94, 0xe6, 0x30, 0xa6, 0xfb, 0x68, 0x64,
304 0x96, 0x1a, 0x84, 0xe1, 0xdc, 0x16, 0x4c, 0x83, 0x6c, 0x44, 0xf2, 0x74, 0x4d, 0x74, 0x79, 0x8f,
305 0xf3, 0xf4, 0x63, 0x0d, 0xef, 0x5a, 0xe7, 0xe2, 0xfd, 0xf2, 0x2b, 0x38, 0x7c, 0x28, 0x96, 0x9d,
306 0xb6, 0xcd, 0x5c, 0x3b, 0x57, 0xe2, 0x24, 0x78, 0x65, 0xd0, 0x9e, 0x77, 0x83, 0x09, 0x6c, 0xff,
307 0x3d, 0x52, 0x3f, 0x6e, 0xd1, 0xed, 0x2e, 0xf9, 0xee, 0x8e, 0xa6, 0xbe, 0x9a, 0xa8, 0x87, 0x76,
308 0xd8, 0x77, 0xcc, 0x96, 0xa0, 0x98, 0xa1, 0xd1, 0x68, 0x09, 0x43, 0xcf, 0x56, 0xd9, 0xd1, 0x66,
311 static const uint8_t dnskey_blob
[] = {
312 0x03, 0x01, 0x00, 0x01, 0x9b, 0x49, 0x9b, 0xc1, 0xf9, 0x9a, 0xe0, 0x4e, 0xcf, 0xcb, 0x14, 0x45,
313 0x2e, 0xc9, 0xf9, 0x74, 0xa7, 0x18, 0xb5, 0xf3, 0xde, 0x39, 0x49, 0xdf, 0x63, 0x33, 0x97, 0x52,
314 0xe0, 0x8e, 0xac, 0x50, 0x30, 0x8e, 0x09, 0xd5, 0x24, 0x3d, 0x26, 0xa4, 0x49, 0x37, 0x2b, 0xb0,
315 0x6b, 0x1b, 0xdf, 0xde, 0x85, 0x83, 0xcb, 0x22, 0x4e, 0x60, 0x0a, 0x91, 0x1a, 0x1f, 0xc5, 0x40,
316 0xb1, 0xc3, 0x15, 0xc1, 0x54, 0x77, 0x86, 0x65, 0x53, 0xec, 0x10, 0x90, 0x0c, 0x91, 0x00, 0x5e,
317 0x15, 0xdc, 0x08, 0x02, 0x4c, 0x8c, 0x0d, 0xc0, 0xac, 0x6e, 0xc4, 0x3e, 0x1b, 0x80, 0x19, 0xe4,
318 0xf7, 0x5f, 0x77, 0x51, 0x06, 0x87, 0x61, 0xde, 0xa2, 0x18, 0x0f, 0x40, 0x8b, 0x79, 0x72, 0xfa,
319 0x8d, 0x1a, 0x44, 0x47, 0x0d, 0x8e, 0x3a, 0x2d, 0xc7, 0x39, 0xbf, 0x56, 0x28, 0x97, 0xd9, 0x20,
320 0x4f, 0x00, 0x51, 0x3b,
323 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*a
= NULL
, *rrsig
= NULL
, *dnskey
= NULL
;
324 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
327 a
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_A
, "nAsA.gov");
330 a
->a
.in_addr
.s_addr
= inet_addr("52.0.14.116");
332 log_info("A: %s", strna(dns_resource_record_to_string(a
)));
334 rrsig
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_RRSIG
, "NaSa.GOV.");
337 rrsig
->rrsig
.type_covered
= DNS_TYPE_A
;
338 rrsig
->rrsig
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
339 rrsig
->rrsig
.labels
= 2;
340 rrsig
->rrsig
.original_ttl
= 600;
341 rrsig
->rrsig
.expiration
= 0x5683135c;
342 rrsig
->rrsig
.inception
= 0x565b7da8;
343 rrsig
->rrsig
.key_tag
= 63876;
344 rrsig
->rrsig
.signer
= strdup("Nasa.Gov.");
345 assert_se(rrsig
->rrsig
.signer
);
346 rrsig
->rrsig
.signature_size
= sizeof(signature_blob
);
347 rrsig
->rrsig
.signature
= memdup(signature_blob
, rrsig
->rrsig
.signature_size
);
348 assert_se(rrsig
->rrsig
.signature
);
350 log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig
)));
352 dnskey
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DNSKEY
, "nASA.gOV");
355 dnskey
->dnskey
.flags
= 256;
356 dnskey
->dnskey
.protocol
= 3;
357 dnskey
->dnskey
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
358 dnskey
->dnskey
.key_size
= sizeof(dnskey_blob
);
359 dnskey
->dnskey
.key
= memdup(dnskey_blob
, sizeof(dnskey_blob
));
360 assert_se(dnskey
->dnskey
.key
);
362 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey
)));
363 log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey
, false));
365 assert_se(dnssec_key_match_rrsig(a
->key
, rrsig
) > 0);
366 assert_se(dnssec_rrsig_match_dnskey(rrsig
, dnskey
, false) > 0);
368 answer
= dns_answer_new(1);
370 assert_se(dns_answer_add(answer
, a
, 0, DNS_ANSWER_AUTHENTICATED
) >= 0);
372 /* Validate the RR as it if was 2015-12-2 today */
373 assert_se(dnssec_verify_rrset(answer
, a
->key
, rrsig
, dnskey
, 1449092754*USEC_PER_SEC
, &result
) >= 0);
374 assert_se(result
== DNSSEC_VALIDATED
);
377 static void test_dnssec_verify_rrset2(void) {
379 static const uint8_t signature_blob
[] = {
380 0x48, 0x45, 0xc8, 0x8b, 0xc0, 0x14, 0x92, 0xf5, 0x15, 0xc6, 0x84, 0x9d, 0x2f, 0xe3, 0x32, 0x11,
381 0x7d, 0xf1, 0xe6, 0x87, 0xb9, 0x42, 0xd3, 0x8b, 0x9e, 0xaf, 0x92, 0x31, 0x0a, 0x53, 0xad, 0x8b,
382 0xa7, 0x5c, 0x83, 0x39, 0x8c, 0x28, 0xac, 0xce, 0x6e, 0x9c, 0x18, 0xe3, 0x31, 0x16, 0x6e, 0xca,
383 0x38, 0x31, 0xaf, 0xd9, 0x94, 0xf1, 0x84, 0xb1, 0xdf, 0x5a, 0xc2, 0x73, 0x22, 0xf6, 0xcb, 0xa2,
384 0xe7, 0x8c, 0x77, 0x0c, 0x74, 0x2f, 0xc2, 0x13, 0xb0, 0x93, 0x51, 0xa9, 0x4f, 0xae, 0x0a, 0xda,
385 0x45, 0xcc, 0xfd, 0x43, 0x99, 0x36, 0x9a, 0x0d, 0x21, 0xe0, 0xeb, 0x30, 0x65, 0xd4, 0xa0, 0x27,
386 0x37, 0x3b, 0xe4, 0xc1, 0xc5, 0xa1, 0x2a, 0xd1, 0x76, 0xc4, 0x7e, 0x64, 0x0e, 0x5a, 0xa6, 0x50,
387 0x24, 0xd5, 0x2c, 0xcc, 0x6d, 0xe5, 0x37, 0xea, 0xbd, 0x09, 0x34, 0xed, 0x24, 0x06, 0xa1, 0x22,
390 static const uint8_t dnskey_blob
[] = {
391 0x03, 0x01, 0x00, 0x01, 0xc3, 0x7f, 0x1d, 0xd1, 0x1c, 0x97, 0xb1, 0x13, 0x34, 0x3a, 0x9a, 0xea,
392 0xee, 0xd9, 0x5a, 0x11, 0x1b, 0x17, 0xc7, 0xe3, 0xd4, 0xda, 0x20, 0xbc, 0x5d, 0xba, 0x74, 0xe3,
393 0x37, 0x99, 0xec, 0x25, 0xce, 0x93, 0x7f, 0xbd, 0x22, 0x73, 0x7e, 0x14, 0x71, 0xe0, 0x60, 0x07,
394 0xd4, 0x39, 0x8b, 0x5e, 0xe9, 0xba, 0x25, 0xe8, 0x49, 0xe9, 0x34, 0xef, 0xfe, 0x04, 0x5c, 0xa5,
395 0x27, 0xcd, 0xa9, 0xda, 0x70, 0x05, 0x21, 0xab, 0x15, 0x82, 0x24, 0xc3, 0x94, 0xf5, 0xd7, 0xb7,
396 0xc4, 0x66, 0xcb, 0x32, 0x6e, 0x60, 0x2b, 0x55, 0x59, 0x28, 0x89, 0x8a, 0x72, 0xde, 0x88, 0x56,
397 0x27, 0x95, 0xd9, 0xac, 0x88, 0x4f, 0x65, 0x2b, 0x68, 0xfc, 0xe6, 0x41, 0xc1, 0x1b, 0xef, 0x4e,
398 0xd6, 0xc2, 0x0f, 0x64, 0x88, 0x95, 0x5e, 0xdd, 0x3a, 0x02, 0x07, 0x50, 0xa9, 0xda, 0xa4, 0x49,
399 0x74, 0x62, 0xfe, 0xd7,
402 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*nsec
= NULL
, *rrsig
= NULL
, *dnskey
= NULL
;
403 _cleanup_(dns_answer_unrefp
) DnsAnswer
*answer
= NULL
;
406 nsec
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_NSEC
, "nasa.gov");
409 nsec
->nsec
.next_domain_name
= strdup("3D-Printing.nasa.gov");
410 assert_se(nsec
->nsec
.next_domain_name
);
412 nsec
->nsec
.types
= bitmap_new();
413 assert_se(nsec
->nsec
.types
);
414 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_A
) >= 0);
415 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_NS
) >= 0);
416 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_SOA
) >= 0);
417 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_MX
) >= 0);
418 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_TXT
) >= 0);
419 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_RRSIG
) >= 0);
420 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_NSEC
) >= 0);
421 assert_se(bitmap_set(nsec
->nsec
.types
, DNS_TYPE_DNSKEY
) >= 0);
422 assert_se(bitmap_set(nsec
->nsec
.types
, 65534) >= 0);
424 log_info("NSEC: %s", strna(dns_resource_record_to_string(nsec
)));
426 rrsig
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_RRSIG
, "NaSa.GOV.");
429 rrsig
->rrsig
.type_covered
= DNS_TYPE_NSEC
;
430 rrsig
->rrsig
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
431 rrsig
->rrsig
.labels
= 2;
432 rrsig
->rrsig
.original_ttl
= 300;
433 rrsig
->rrsig
.expiration
= 0x5689002f;
434 rrsig
->rrsig
.inception
= 0x56617230;
435 rrsig
->rrsig
.key_tag
= 30390;
436 rrsig
->rrsig
.signer
= strdup("Nasa.Gov.");
437 assert_se(rrsig
->rrsig
.signer
);
438 rrsig
->rrsig
.signature_size
= sizeof(signature_blob
);
439 rrsig
->rrsig
.signature
= memdup(signature_blob
, rrsig
->rrsig
.signature_size
);
440 assert_se(rrsig
->rrsig
.signature
);
442 log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig
)));
444 dnskey
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_DNSKEY
, "nASA.gOV");
447 dnskey
->dnskey
.flags
= 256;
448 dnskey
->dnskey
.protocol
= 3;
449 dnskey
->dnskey
.algorithm
= DNSSEC_ALGORITHM_RSASHA256
;
450 dnskey
->dnskey
.key_size
= sizeof(dnskey_blob
);
451 dnskey
->dnskey
.key
= memdup(dnskey_blob
, sizeof(dnskey_blob
));
452 assert_se(dnskey
->dnskey
.key
);
454 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey
)));
455 log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey
, false));
457 assert_se(dnssec_key_match_rrsig(nsec
->key
, rrsig
) > 0);
458 assert_se(dnssec_rrsig_match_dnskey(rrsig
, dnskey
, false) > 0);
460 answer
= dns_answer_new(1);
462 assert_se(dns_answer_add(answer
, nsec
, 0, DNS_ANSWER_AUTHENTICATED
) >= 0);
464 /* Validate the RR as it if was 2015-12-11 today */
465 assert_se(dnssec_verify_rrset(answer
, nsec
->key
, rrsig
, dnskey
, 1449849318*USEC_PER_SEC
, &result
) >= 0);
466 assert_se(result
== DNSSEC_VALIDATED
);
469 static void test_dnssec_nsec3_hash(void) {
470 static const uint8_t salt
[] = { 0xB0, 0x1D, 0xFA, 0xCE };
471 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 };
472 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
473 uint8_t h
[DNSSEC_HASH_SIZE_MAX
];
474 _cleanup_free_
char *b
= NULL
;
477 /* The NSEC3 RR for eurid.eu on 2015-12-14. */
478 rr
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_NSEC3
, "PJ8S08RR45VIQDAQGE7EN3VHKNROTBMM.eurid.eu.");
481 rr
->nsec3
.algorithm
= DNSSEC_DIGEST_SHA1
;
483 rr
->nsec3
.iterations
= 1;
484 rr
->nsec3
.salt
= memdup(salt
, sizeof(salt
));
485 assert_se(rr
->nsec3
.salt
);
486 rr
->nsec3
.salt_size
= sizeof(salt
);
487 rr
->nsec3
.next_hashed_name
= memdup(next_hashed_name
, sizeof(next_hashed_name
));
488 assert_se(rr
->nsec3
.next_hashed_name
);
489 rr
->nsec3
.next_hashed_name_size
= sizeof(next_hashed_name
);
491 log_info("NSEC3: %s", strna(dns_resource_record_to_string(rr
)));
493 k
= dnssec_nsec3_hash(rr
, "eurid.eu", &h
);
496 b
= base32hexmem(h
, k
, false);
498 assert_se(strcasecmp(b
, "PJ8S08RR45VIQDAQGE7EN3VHKNROTBMM") == 0);
503 int main(int argc
, char*argv
[]) {
505 test_dnssec_canonicalize();
508 test_dnssec_verify_dns_key();
509 test_dnssec_verify_rfc8080_ed25519_example1();
510 test_dnssec_verify_rfc8080_ed25519_example2();
511 test_dnssec_verify_rrset();
512 test_dnssec_verify_rrset2();
513 test_dnssec_nsec3_hash();