]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/test-dnssec.c
grypt-util: drop two emacs modelines
[thirdparty/systemd.git] / src / resolve / test-dnssec.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 Copyright 2015 Lennart Poettering
4 ***/
5
6 #include <arpa/inet.h>
7 #if HAVE_GCRYPT
8 #include <gcrypt.h>
9 #endif
10 #include <netinet/in.h>
11 #include <sys/socket.h>
12
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"
18
19 static void test_dnssec_canonicalize_one(const char *original, const char *canonical, int r) {
20 char canonicalized[DNSSEC_CANONICAL_HOSTNAME_MAX];
21
22 assert_se(dnssec_canonicalize(original, canonicalized, sizeof(canonicalized)) == r);
23 if (r < 0)
24 return;
25
26 assert_se(streq(canonicalized, canonical));
27 }
28
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);
37 }
38
39 #if HAVE_GCRYPT
40
41 static void test_dnssec_verify_dns_key(void) {
42
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,
46 };
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,
50 };
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,
69 };
70
71 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *dnskey = NULL, *ds1 = NULL, *ds2 = NULL;
72
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");
75 assert_se(ds1);
76
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);
83
84 log_info("DS1: %s", strna(dns_resource_record_to_string(ds1)));
85
86 ds2 = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "NASA.GOV");
87 assert_se(ds2);
88
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);
95
96 log_info("DS2: %s", strna(dns_resource_record_to_string(ds2)));
97
98 dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nasa.GOV");
99 assert_se(dnskey);
100
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);
107
108 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey)));
109 log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey, false));
110
111 assert_se(dnssec_verify_dnskey_by_ds(dnskey, ds1, false) > 0);
112 assert_se(dnssec_verify_dnskey_by_ds(dnskey, ds2, false) > 0);
113 }
114
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,
119 0x24, 0xe
120 };
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,
125 0xdf, 0x4e, 0x1b
126 };
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
133 };
134
135 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *dnskey = NULL, *ds = NULL, *mx = NULL,
136 *rrsig = NULL;
137 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
138 DnssecResult result;
139
140 dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "example.com.");
141 assert_se(dnskey);
142
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);
149
150 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey)));
151
152 ds = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "example.com.");
153 assert_se(ds);
154
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);
161
162 log_info("DS: %s", strna(dns_resource_record_to_string(ds)));
163
164 mx = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_MX, "example.com.");
165 assert_se(mx);
166
167 mx->mx.priority = 10;
168 mx->mx.exchange = strdup("mail.example.com.");
169 assert_se(mx->mx.exchange);
170
171 log_info("MX: %s", strna(dns_resource_record_to_string(mx)));
172
173 rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "example.com.");
174 assert_se(rrsig);
175
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);
188
189 log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig)));
190
191 assert_se(dnssec_key_match_rrsig(mx->key, rrsig) > 0);
192 assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey, false) > 0);
193
194 answer = dns_answer_new(1);
195 assert_se(answer);
196 assert_se(dns_answer_add(answer, mx, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
197
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);
202 #else
203 assert_se(result == DNSSEC_UNSUPPORTED_ALGORITHM);
204 #endif
205 }
206
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,
211 0x8a, 0x3b
212 };
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,
217 0xeb, 0x5e, 0x1c
218 };
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
225 };
226
227 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *dnskey = NULL, *ds = NULL, *mx = NULL,
228 *rrsig = NULL;
229 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
230 DnssecResult result;
231
232 dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "example.com.");
233 assert_se(dnskey);
234
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);
241
242 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey)));
243
244 ds = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "example.com.");
245 assert_se(ds);
246
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);
253
254 log_info("DS: %s", strna(dns_resource_record_to_string(ds)));
255
256 mx = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_MX, "example.com.");
257 assert_se(mx);
258
259 mx->mx.priority = 10;
260 mx->mx.exchange = strdup("mail.example.com.");
261 assert_se(mx->mx.exchange);
262
263 log_info("MX: %s", strna(dns_resource_record_to_string(mx)));
264
265 rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "example.com.");
266 assert_se(rrsig);
267
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);
280
281 log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig)));
282
283 assert_se(dnssec_key_match_rrsig(mx->key, rrsig) > 0);
284 assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey, false) > 0);
285
286 answer = dns_answer_new(1);
287 assert_se(answer);
288 assert_se(dns_answer_add(answer, mx, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
289
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);
294 #else
295 assert_se(result == DNSSEC_UNSUPPORTED_ALGORITHM);
296 #endif
297 }
298 static void test_dnssec_verify_rrset(void) {
299
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,
309 };
310
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,
321 };
322
323 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *a = NULL, *rrsig = NULL, *dnskey = NULL;
324 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
325 DnssecResult result;
326
327 a = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, "nAsA.gov");
328 assert_se(a);
329
330 a->a.in_addr.s_addr = inet_addr("52.0.14.116");
331
332 log_info("A: %s", strna(dns_resource_record_to_string(a)));
333
334 rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "NaSa.GOV.");
335 assert_se(rrsig);
336
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);
349
350 log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig)));
351
352 dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nASA.gOV");
353 assert_se(dnskey);
354
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);
361
362 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey)));
363 log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey, false));
364
365 assert_se(dnssec_key_match_rrsig(a->key, rrsig) > 0);
366 assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey, false) > 0);
367
368 answer = dns_answer_new(1);
369 assert_se(answer);
370 assert_se(dns_answer_add(answer, a, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
371
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);
375 }
376
377 static void test_dnssec_verify_rrset2(void) {
378
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,
388 };
389
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,
400 };
401
402 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *nsec = NULL, *rrsig = NULL, *dnskey = NULL;
403 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
404 DnssecResult result;
405
406 nsec = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_NSEC, "nasa.gov");
407 assert_se(nsec);
408
409 nsec->nsec.next_domain_name = strdup("3D-Printing.nasa.gov");
410 assert_se(nsec->nsec.next_domain_name);
411
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);
423
424 log_info("NSEC: %s", strna(dns_resource_record_to_string(nsec)));
425
426 rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "NaSa.GOV.");
427 assert_se(rrsig);
428
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);
441
442 log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig)));
443
444 dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nASA.gOV");
445 assert_se(dnskey);
446
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);
453
454 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey)));
455 log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey, false));
456
457 assert_se(dnssec_key_match_rrsig(nsec->key, rrsig) > 0);
458 assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey, false) > 0);
459
460 answer = dns_answer_new(1);
461 assert_se(answer);
462 assert_se(dns_answer_add(answer, nsec, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
463
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);
467 }
468
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;
475 int k;
476
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.");
479 assert_se(rr);
480
481 rr->nsec3.algorithm = DNSSEC_DIGEST_SHA1;
482 rr->nsec3.flags = 1;
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);
490
491 log_info("NSEC3: %s", strna(dns_resource_record_to_string(rr)));
492
493 k = dnssec_nsec3_hash(rr, "eurid.eu", &h);
494 assert_se(k >= 0);
495
496 b = base32hexmem(h, k, false);
497 assert_se(b);
498 assert_se(strcasecmp(b, "PJ8S08RR45VIQDAQGE7EN3VHKNROTBMM") == 0);
499 }
500
501 #endif
502
503 int main(int argc, char*argv[]) {
504
505 test_dnssec_canonicalize();
506
507 #if HAVE_GCRYPT
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();
514 #endif
515
516 return 0;
517 }