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