]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/test-dnssec.c
travis: turn on nonnull-attribute on Fuzzit
[thirdparty/systemd.git] / src / resolve / test-dnssec.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
2b442ac8
LP
2
3#include <arpa/inet.h>
4848b1f9 4#if HAVE_GCRYPT
cb9eeb06 5#include <gcrypt.h>
4848b1f9 6#endif
2b442ac8
LP
7#include <netinet/in.h>
8#include <sys/socket.h>
9
10#include "alloc-util.h"
11#include "resolved-dns-dnssec.h"
2b442ac8
LP
12#include "resolved-dns-rr.h"
13#include "string-util.h"
72667f08 14#include "hexdecoct.h"
2b442ac8 15
1691cfd8
ZJS
16static void test_dnssec_canonicalize_one(const char *original, const char *canonical, int r) {
17 char canonicalized[DNSSEC_CANONICAL_HOSTNAME_MAX];
a3db237b 18
1691cfd8
ZJS
19 assert_se(dnssec_canonicalize(original, canonicalized, sizeof(canonicalized)) == r);
20 if (r < 0)
21 return;
a3db237b 22
1691cfd8
ZJS
23 assert_se(streq(canonicalized, canonical));
24}
25
26static 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
349cc4a5 36#if HAVE_GCRYPT
1691cfd8
ZJS
37
38static 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 };
a3db237b 48 static const uint8_t dnskey_blob[] = {
1691cfd8
ZJS
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,
a3db237b
LP
66 };
67
1691cfd8 68 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *dnskey = NULL, *ds1 = NULL, *ds2 = NULL;
a3db237b 69
1691cfd8
ZJS
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);
a3db237b 73
1691cfd8
ZJS
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);
a3db237b 80
1691cfd8 81 log_info("DS1: %s", strna(dns_resource_record_to_string(ds1)));
a3db237b 82
1691cfd8
ZJS
83 ds2 = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "NASA.GOV");
84 assert_se(ds2);
a3db237b 85
1691cfd8
ZJS
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);
a3db237b 92
1691cfd8 93 log_info("DS2: %s", strna(dns_resource_record_to_string(ds2)));
a3db237b 94
1691cfd8 95 dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nasa.GOV");
a3db237b
LP
96 assert_se(dnskey);
97
1691cfd8 98 dnskey->dnskey.flags = 257;
a3db237b
LP
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
7b50eb2e 105 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey)));
0c857028 106 log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey, false));
a3db237b 107
1691cfd8
ZJS
108 assert_se(dnssec_verify_dnskey_by_ds(dnskey, ds1, false) > 0);
109 assert_se(dnssec_verify_dnskey_by_ds(dnskey, ds2, false) > 0);
a3db237b
LP
110}
111
cb9eeb06
MCO
112static 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
204static 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}
2b442ac8
LP
295static 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;
547973de 322 DnssecResult result;
2b442ac8
LP
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
7b50eb2e 329 log_info("A: %s", strna(dns_resource_record_to_string(a)));
2b442ac8
LP
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
7b50eb2e 347 log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig)));
2b442ac8
LP
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
7b50eb2e 359 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey)));
0c857028 360 log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey, false));
2b442ac8
LP
361
362 assert_se(dnssec_key_match_rrsig(a->key, rrsig) > 0);
0c857028 363 assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey, false) > 0);
2b442ac8
LP
364
365 answer = dns_answer_new(1);
366 assert_se(answer);
105e1512 367 assert_se(dns_answer_add(answer, a, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
2b442ac8 368
2a326321 369 /* Validate the RR as it if was 2015-12-2 today */
547973de
LP
370 assert_se(dnssec_verify_rrset(answer, a->key, rrsig, dnskey, 1449092754*USEC_PER_SEC, &result) >= 0);
371 assert_se(result == DNSSEC_VALIDATED);
2b442ac8
LP
372}
373
1691cfd8 374static void test_dnssec_verify_rrset2(void) {
2b442ac8 375
1691cfd8
ZJS
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,
2b442ac8 385 };
1691cfd8 386
2b442ac8 387 static const uint8_t dnskey_blob[] = {
1691cfd8
ZJS
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,
2b442ac8
LP
397 };
398
1691cfd8
ZJS
399 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *nsec = NULL, *rrsig = NULL, *dnskey = NULL;
400 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
401 DnssecResult result;
2b442ac8 402
1691cfd8
ZJS
403 nsec = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_NSEC, "nasa.gov");
404 assert_se(nsec);
2b442ac8 405
1691cfd8
ZJS
406 nsec->nsec.next_domain_name = strdup("3D-Printing.nasa.gov");
407 assert_se(nsec->nsec.next_domain_name);
2b442ac8 408
1691cfd8
ZJS
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);
2b442ac8 420
1691cfd8 421 log_info("NSEC: %s", strna(dns_resource_record_to_string(nsec)));
2b442ac8 422
1691cfd8
ZJS
423 rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "NaSa.GOV.");
424 assert_se(rrsig);
2b442ac8 425
1691cfd8
ZJS
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);
2b442ac8 438
1691cfd8
ZJS
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");
2b442ac8
LP
442 assert_se(dnskey);
443
1691cfd8 444 dnskey->dnskey.flags = 256;
2b442ac8
LP
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
7b50eb2e 451 log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey)));
0c857028 452 log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey, false));
2b442ac8 453
1691cfd8
ZJS
454 assert_se(dnssec_key_match_rrsig(nsec->key, rrsig) > 0);
455 assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey, false) > 0);
2b442ac8 456
1691cfd8
ZJS
457 answer = dns_answer_new(1);
458 assert_se(answer);
459 assert_se(dns_answer_add(answer, nsec, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
2b442ac8 460
1691cfd8
ZJS
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);
2b442ac8
LP
464}
465
72667f08
LP
466static 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;
72667f08 470 uint8_t h[DNSSEC_HASH_SIZE_MAX];
7b50eb2e 471 _cleanup_free_ char *b = NULL;
72667f08
LP
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
7b50eb2e 488 log_info("NSEC3: %s", strna(dns_resource_record_to_string(rr)));
72667f08
LP
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
1691cfd8
ZJS
498#endif
499
f2a3de01 500int main(int argc, char *argv[]) {
2b442ac8
LP
501
502 test_dnssec_canonicalize();
1691cfd8 503
349cc4a5 504#if HAVE_GCRYPT
2b442ac8 505 test_dnssec_verify_dns_key();
cb9eeb06
MCO
506 test_dnssec_verify_rfc8080_ed25519_example1();
507 test_dnssec_verify_rfc8080_ed25519_example2();
2b442ac8 508 test_dnssec_verify_rrset();
a3db237b 509 test_dnssec_verify_rrset2();
72667f08 510 test_dnssec_nsec3_hash();
a915abf3 511#endif
2b442ac8
LP
512
513 return 0;
514}