]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/test-dnssec.c
resolved: add missing error code check when initializing DNS-over-TLS
[thirdparty/systemd.git] / src / resolve / test-dnssec.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <arpa/inet.h>
4 #if HAVE_GCRYPT
5 #include <gcrypt.h>
6 #endif
7 #include <netinet/in.h>
8 #include <sys/socket.h>
9
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"
15
16 static void test_dnssec_canonicalize_one(const char *original, const char *canonical, int r) {
17 char canonicalized[DNSSEC_CANONICAL_HOSTNAME_MAX];
18
19 assert_se(dnssec_canonicalize(original, canonicalized, sizeof(canonicalized)) == r);
20 if (r < 0)
21 return;
22
23 assert_se(streq(canonicalized, canonical));
24 }
25
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);
34 }
35
36 #if HAVE_GCRYPT
37
38 static void test_dnssec_verify_dns_key(void) {
39
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,
43 };
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,
47 };
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,
66 };
67
68 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *dnskey = NULL, *ds1 = NULL, *ds2 = NULL;
69
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");
72 assert_se(ds1);
73
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);
80
81 log_info("DS1: %s", strna(dns_resource_record_to_string(ds1)));
82
83 ds2 = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "NASA.GOV");
84 assert_se(ds2);
85
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);
92
93 log_info("DS2: %s", strna(dns_resource_record_to_string(ds2)));
94
95 dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nasa.GOV");
96 assert_se(dnskey);
97
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);
104
105 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey)));
106 log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey, false));
107
108 assert_se(dnssec_verify_dnskey_by_ds(dnskey, ds1, false) > 0);
109 assert_se(dnssec_verify_dnskey_by_ds(dnskey, ds2, false) > 0);
110 }
111
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,
116 0x24, 0xe
117 };
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,
122 0xdf, 0x4e, 0x1b
123 };
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
130 };
131
132 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *dnskey = NULL, *ds = NULL, *mx = NULL,
133 *rrsig = NULL;
134 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
135 DnssecResult result;
136
137 dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "example.com.");
138 assert_se(dnskey);
139
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);
146
147 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey)));
148
149 ds = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "example.com.");
150 assert_se(ds);
151
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);
158
159 log_info("DS: %s", strna(dns_resource_record_to_string(ds)));
160
161 mx = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_MX, "example.com.");
162 assert_se(mx);
163
164 mx->mx.priority = 10;
165 mx->mx.exchange = strdup("mail.example.com.");
166 assert_se(mx->mx.exchange);
167
168 log_info("MX: %s", strna(dns_resource_record_to_string(mx)));
169
170 rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "example.com.");
171 assert_se(rrsig);
172
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);
185
186 log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig)));
187
188 assert_se(dnssec_key_match_rrsig(mx->key, rrsig) > 0);
189 assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey, false) > 0);
190
191 answer = dns_answer_new(1);
192 assert_se(answer);
193 assert_se(dns_answer_add(answer, mx, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
194
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);
199 #else
200 assert_se(result == DNSSEC_UNSUPPORTED_ALGORITHM);
201 #endif
202 }
203
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,
208 0x8a, 0x3b
209 };
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,
214 0xeb, 0x5e, 0x1c
215 };
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
222 };
223
224 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *dnskey = NULL, *ds = NULL, *mx = NULL,
225 *rrsig = NULL;
226 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
227 DnssecResult result;
228
229 dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "example.com.");
230 assert_se(dnskey);
231
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);
238
239 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey)));
240
241 ds = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "example.com.");
242 assert_se(ds);
243
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);
250
251 log_info("DS: %s", strna(dns_resource_record_to_string(ds)));
252
253 mx = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_MX, "example.com.");
254 assert_se(mx);
255
256 mx->mx.priority = 10;
257 mx->mx.exchange = strdup("mail.example.com.");
258 assert_se(mx->mx.exchange);
259
260 log_info("MX: %s", strna(dns_resource_record_to_string(mx)));
261
262 rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "example.com.");
263 assert_se(rrsig);
264
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);
277
278 log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig)));
279
280 assert_se(dnssec_key_match_rrsig(mx->key, rrsig) > 0);
281 assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey, false) > 0);
282
283 answer = dns_answer_new(1);
284 assert_se(answer);
285 assert_se(dns_answer_add(answer, mx, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
286
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);
291 #else
292 assert_se(result == DNSSEC_UNSUPPORTED_ALGORITHM);
293 #endif
294 }
295 static void test_dnssec_verify_rrset(void) {
296
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,
306 };
307
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,
318 };
319
320 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *a = NULL, *rrsig = NULL, *dnskey = NULL;
321 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
322 DnssecResult result;
323
324 a = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, "nAsA.gov");
325 assert_se(a);
326
327 a->a.in_addr.s_addr = inet_addr("52.0.14.116");
328
329 log_info("A: %s", strna(dns_resource_record_to_string(a)));
330
331 rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "NaSa.GOV.");
332 assert_se(rrsig);
333
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);
346
347 log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig)));
348
349 dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nASA.gOV");
350 assert_se(dnskey);
351
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);
358
359 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey)));
360 log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey, false));
361
362 assert_se(dnssec_key_match_rrsig(a->key, rrsig) > 0);
363 assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey, false) > 0);
364
365 answer = dns_answer_new(1);
366 assert_se(answer);
367 assert_se(dns_answer_add(answer, a, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
368
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);
372 }
373
374 static void test_dnssec_verify_rrset2(void) {
375
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,
385 };
386
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,
397 };
398
399 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *nsec = NULL, *rrsig = NULL, *dnskey = NULL;
400 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
401 DnssecResult result;
402
403 nsec = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_NSEC, "nasa.gov");
404 assert_se(nsec);
405
406 nsec->nsec.next_domain_name = strdup("3D-Printing.nasa.gov");
407 assert_se(nsec->nsec.next_domain_name);
408
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);
420
421 log_info("NSEC: %s", strna(dns_resource_record_to_string(nsec)));
422
423 rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "NaSa.GOV.");
424 assert_se(rrsig);
425
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);
438
439 log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig)));
440
441 dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nASA.gOV");
442 assert_se(dnskey);
443
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);
450
451 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey)));
452 log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey, false));
453
454 assert_se(dnssec_key_match_rrsig(nsec->key, rrsig) > 0);
455 assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey, false) > 0);
456
457 answer = dns_answer_new(1);
458 assert_se(answer);
459 assert_se(dns_answer_add(answer, nsec, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
460
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);
464 }
465
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;
472 int k;
473
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.");
476 assert_se(rr);
477
478 rr->nsec3.algorithm = DNSSEC_DIGEST_SHA1;
479 rr->nsec3.flags = 1;
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);
487
488 log_info("NSEC3: %s", strna(dns_resource_record_to_string(rr)));
489
490 k = dnssec_nsec3_hash(rr, "eurid.eu", &h);
491 assert_se(k >= 0);
492
493 b = base32hexmem(h, k, false);
494 assert_se(b);
495 assert_se(strcasecmp(b, "PJ8S08RR45VIQDAQGE7EN3VHKNROTBMM") == 0);
496 }
497
498 #endif
499
500 int main(int argc, char *argv[]) {
501
502 test_dnssec_canonicalize();
503
504 #if HAVE_GCRYPT
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();
511 #endif
512
513 return 0;
514 }