]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/test-dnscrypt_cc.cc
Merge pull request #5523 from rubenk/fix-typos-in-logmessage
[thirdparty/pdns.git] / pdns / test-dnscrypt_cc.cc
1 /*
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22 #define BOOST_TEST_DYN_LINK
23 #define BOOST_TEST_NO_MAIN
24
25 #include <boost/test/unit_test.hpp>
26
27 #include "dnscrypt.hh"
28 #include "dnsname.hh"
29 #include "dnsparser.hh"
30 #include "dnswriter.hh"
31 #include <unistd.h>
32
33 bool g_verbose{true};
34 bool g_console{true};
35 bool g_syslog{true};
36
37 BOOST_AUTO_TEST_SUITE(dnscrypt_cc)
38
39 #ifdef HAVE_DNSCRYPT
40
41 // plaintext query for cert
42 BOOST_AUTO_TEST_CASE(DNSCryptPlaintextQuery) {
43 DnsCryptPrivateKey resolverPrivateKey;
44 DnsCryptCert resolverCert;
45 unsigned char providerPublicKey[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE];
46 unsigned char providerPrivateKey[DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE];
47 time_t now = time(NULL);
48 DnsCryptContext::generateProviderKeys(providerPublicKey, providerPrivateKey);
49 DnsCryptContext::generateCertificate(1, now, now + (24 * 60 * 3600), providerPrivateKey, resolverPrivateKey, resolverCert);
50 DnsCryptContext ctx("2.name", resolverCert, resolverPrivateKey);
51
52 DNSName name("2.name.");
53 vector<uint8_t> plainQuery;
54 DNSPacketWriter pw(plainQuery, name, QType::TXT, QClass::IN, 0);
55 pw.getHeader()->rd = 0;
56 uint16_t len = plainQuery.size();
57
58 std::shared_ptr<DnsCryptQuery> query = std::make_shared<DnsCryptQuery>();
59 uint16_t decryptedLen = 0;
60
61 ctx.parsePacket((char*) plainQuery.data(), len, query, false, &decryptedLen);
62
63 BOOST_CHECK_EQUAL(query->valid, true);
64 BOOST_CHECK_EQUAL(query->encrypted, false);
65
66 std::vector<uint8_t> response;
67
68 ctx.getCertificateResponse(query, response);
69
70 MOADNSParser mdp(false, (char*) response.data(), response.size());
71
72 BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1);
73 BOOST_CHECK_EQUAL(mdp.d_header.ancount, 1);
74 BOOST_CHECK_EQUAL(mdp.d_header.nscount, 0);
75 BOOST_CHECK_EQUAL(mdp.d_header.arcount, 0);
76
77 BOOST_CHECK_EQUAL(mdp.d_qname.toString(), "2.name.");
78 BOOST_CHECK(mdp.d_qclass == QClass::IN);
79 BOOST_CHECK(mdp.d_qtype == QType::TXT);
80 }
81
82 // invalid plaintext query (A)
83 BOOST_AUTO_TEST_CASE(DNSCryptPlaintextQueryInvalidA) {
84 DnsCryptPrivateKey resolverPrivateKey;
85 DnsCryptCert resolverCert;
86 unsigned char providerPublicKey[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE];
87 unsigned char providerPrivateKey[DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE];
88 time_t now = time(NULL);
89 DnsCryptContext::generateProviderKeys(providerPublicKey, providerPrivateKey);
90 DnsCryptContext::generateCertificate(1, now, now + (24 * 60 * 3600), providerPrivateKey, resolverPrivateKey, resolverCert);
91 DnsCryptContext ctx("2.name", resolverCert, resolverPrivateKey);
92
93 DNSName name("2.name.");
94
95 vector<uint8_t> plainQuery;
96 DNSPacketWriter pw(plainQuery, name, QType::A, QClass::IN, 0);
97 pw.getHeader()->rd = 0;
98 uint16_t len = plainQuery.size();
99
100 std::shared_ptr<DnsCryptQuery> query = std::make_shared<DnsCryptQuery>();
101 uint16_t decryptedLen = 0;
102
103 ctx.parsePacket((char*) plainQuery.data(), len, query, false, &decryptedLen);
104
105 BOOST_CHECK_EQUAL(query->valid, false);
106 }
107
108 // invalid plaintext query (wrong provider name)
109 BOOST_AUTO_TEST_CASE(DNSCryptPlaintextQueryInvalidProviderName) {
110 DnsCryptPrivateKey resolverPrivateKey;
111 DnsCryptCert resolverCert;
112 unsigned char providerPublicKey[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE];
113 unsigned char providerPrivateKey[DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE];
114 time_t now = time(NULL);
115 DnsCryptContext::generateProviderKeys(providerPublicKey, providerPrivateKey);
116 DnsCryptContext::generateCertificate(1, now, now + (24 * 60 * 3600), providerPrivateKey, resolverPrivateKey, resolverCert);
117 DnsCryptContext ctx("2.name", resolverCert, resolverPrivateKey);
118
119 DNSName name("2.WRONG.name.");
120
121 vector<uint8_t> plainQuery;
122 DNSPacketWriter pw(plainQuery, name, QType::TXT, QClass::IN, 0);
123 pw.getHeader()->rd = 0;
124 uint16_t len = plainQuery.size();
125
126 std::shared_ptr<DnsCryptQuery> query = std::make_shared<DnsCryptQuery>();
127 uint16_t decryptedLen = 0;
128
129 ctx.parsePacket((char*) plainQuery.data(), len, query, false, &decryptedLen);
130
131 BOOST_CHECK_EQUAL(query->valid, false);
132 }
133
134 // valid encrypted query
135 BOOST_AUTO_TEST_CASE(DNSCryptEncryptedQueryValid) {
136 DnsCryptPrivateKey resolverPrivateKey;
137 DnsCryptCert resolverCert;
138 unsigned char providerPublicKey[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE];
139 unsigned char providerPrivateKey[DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE];
140 time_t now = time(NULL);
141 DnsCryptContext::generateProviderKeys(providerPublicKey, providerPrivateKey);
142 DnsCryptContext::generateCertificate(1, now, now + (24 * 60 * 3600), providerPrivateKey, resolverPrivateKey, resolverCert);
143 DnsCryptContext ctx("2.name", resolverCert, resolverPrivateKey);
144
145 DnsCryptPrivateKey clientPrivateKey;
146 unsigned char clientPublicKey[DNSCRYPT_PUBLIC_KEY_SIZE];
147
148 DnsCryptContext::generateResolverKeyPair(clientPrivateKey, clientPublicKey);
149
150 unsigned char clientNonce[DNSCRYPT_NONCE_SIZE / 2] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, 0x09, 0x0A, 0x0B };
151
152 DNSName name("www.powerdns.com.");
153 vector<uint8_t> plainQuery;
154 DNSPacketWriter pw(plainQuery, name, QType::AAAA, QClass::IN, 0);
155 pw.getHeader()->rd = 1;
156 size_t requiredSize = plainQuery.size() + sizeof(DnsCryptQueryHeader) + DNSCRYPT_MAC_SIZE;
157 if (requiredSize < DnsCryptQuery::minUDPLength) {
158 requiredSize = DnsCryptQuery::minUDPLength;
159 }
160
161 plainQuery.reserve(requiredSize);
162 uint16_t len = plainQuery.size();
163 uint16_t encryptedResponseLen = 0;
164
165 int res = ctx.encryptQuery((char*) plainQuery.data(), len, plainQuery.capacity(), clientPublicKey, clientPrivateKey, clientNonce, false, &encryptedResponseLen);
166
167 BOOST_CHECK_EQUAL(res, 0);
168 BOOST_CHECK(encryptedResponseLen > len);
169
170 std::shared_ptr<DnsCryptQuery> query = std::make_shared<DnsCryptQuery>();
171 uint16_t decryptedLen = 0;
172
173 ctx.parsePacket((char*) plainQuery.data(), encryptedResponseLen, query, false, &decryptedLen);
174
175 BOOST_CHECK_EQUAL(query->valid, true);
176 BOOST_CHECK_EQUAL(query->encrypted, true);
177
178 MOADNSParser mdp(true, (char*) plainQuery.data(), decryptedLen);
179
180 BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1);
181 BOOST_CHECK_EQUAL(mdp.d_header.ancount, 0);
182 BOOST_CHECK_EQUAL(mdp.d_header.nscount, 0);
183 BOOST_CHECK_EQUAL(mdp.d_header.arcount, 0);
184
185 BOOST_CHECK_EQUAL(mdp.d_qname, name);
186 BOOST_CHECK(mdp.d_qclass == QClass::IN);
187 BOOST_CHECK(mdp.d_qtype == QType::AAAA);
188 }
189
190 // valid encrypted query with not enough room
191 BOOST_AUTO_TEST_CASE(DNSCryptEncryptedQueryValidButShort) {
192 DnsCryptPrivateKey resolverPrivateKey;
193 DnsCryptCert resolverCert;
194 unsigned char providerPublicKey[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE];
195 unsigned char providerPrivateKey[DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE];
196 time_t now = time(NULL);
197 DnsCryptContext::generateProviderKeys(providerPublicKey, providerPrivateKey);
198 DnsCryptContext::generateCertificate(1, now, now + (24 * 60 * 3600), providerPrivateKey, resolverPrivateKey, resolverCert);
199 DnsCryptContext ctx("2.name", resolverCert, resolverPrivateKey);
200
201 DnsCryptPrivateKey clientPrivateKey;
202 unsigned char clientPublicKey[DNSCRYPT_PUBLIC_KEY_SIZE];
203
204 DnsCryptContext::generateResolverKeyPair(clientPrivateKey, clientPublicKey);
205
206 unsigned char clientNonce[DNSCRYPT_NONCE_SIZE / 2] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, 0x09, 0x0A, 0x0B };
207
208 DNSName name("www.powerdns.com.");
209 vector<uint8_t> plainQuery;
210 DNSPacketWriter pw(plainQuery, name, QType::AAAA, QClass::IN, 0);
211 pw.getHeader()->rd = 1;
212
213 uint16_t len = plainQuery.size();
214 uint16_t encryptedResponseLen = 0;
215
216 int res = ctx.encryptQuery((char*) plainQuery.data(), len, plainQuery.capacity(), clientPublicKey, clientPrivateKey, clientNonce, false, &encryptedResponseLen);
217
218 BOOST_CHECK_EQUAL(res, ENOBUFS);
219 }
220
221 // valid encrypted query with old key
222 BOOST_AUTO_TEST_CASE(DNSCryptEncryptedQueryValidWithOldKey) {
223 DnsCryptPrivateKey resolverPrivateKey;
224 DnsCryptCert resolverCert;
225 unsigned char providerPublicKey[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE];
226 unsigned char providerPrivateKey[DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE];
227 time_t now = time(NULL);
228 DnsCryptContext::generateProviderKeys(providerPublicKey, providerPrivateKey);
229 DnsCryptContext::generateCertificate(1, now, now + (24 * 60 * 3600), providerPrivateKey, resolverPrivateKey, resolverCert);
230 DnsCryptContext ctx("2.name", resolverCert, resolverPrivateKey);
231
232 DnsCryptPrivateKey clientPrivateKey;
233 unsigned char clientPublicKey[DNSCRYPT_PUBLIC_KEY_SIZE];
234
235 DnsCryptContext::generateResolverKeyPair(clientPrivateKey, clientPublicKey);
236
237 unsigned char clientNonce[DNSCRYPT_NONCE_SIZE / 2] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, 0x09, 0x0A, 0x0B };
238
239 DNSName name("www.powerdns.com.");
240 vector<uint8_t> plainQuery;
241 DNSPacketWriter pw(plainQuery, name, QType::AAAA, QClass::IN, 0);
242 pw.getHeader()->rd = 1;
243
244 size_t requiredSize = plainQuery.size() + sizeof(DnsCryptQueryHeader) + DNSCRYPT_MAC_SIZE;
245 if (requiredSize < DnsCryptQuery::minUDPLength) {
246 requiredSize = DnsCryptQuery::minUDPLength;
247 }
248
249 plainQuery.reserve(requiredSize);
250
251 uint16_t len = plainQuery.size();
252 uint16_t encryptedResponseLen = 0;
253
254 int res = ctx.encryptQuery((char*) plainQuery.data(), len, plainQuery.capacity(), clientPublicKey, clientPrivateKey, clientNonce, false, &encryptedResponseLen);
255
256 BOOST_CHECK_EQUAL(res, 0);
257 BOOST_CHECK(encryptedResponseLen > len);
258
259 DnsCryptContext::generateCertificate(1, now, now + (24 * 60 * 3600), providerPrivateKey, resolverPrivateKey, resolverCert);
260 ctx.setNewCertificate(resolverCert, resolverPrivateKey);
261
262 std::shared_ptr<DnsCryptQuery> query = std::make_shared<DnsCryptQuery>();
263 uint16_t decryptedLen = 0;
264
265 ctx.parsePacket((char*) plainQuery.data(), encryptedResponseLen, query, false, &decryptedLen);
266
267 BOOST_CHECK_EQUAL(query->valid, true);
268 BOOST_CHECK_EQUAL(query->encrypted, true);
269
270 MOADNSParser mdp(true, (char*) plainQuery.data(), decryptedLen);
271
272 BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1);
273 BOOST_CHECK_EQUAL(mdp.d_header.ancount, 0);
274 BOOST_CHECK_EQUAL(mdp.d_header.nscount, 0);
275 BOOST_CHECK_EQUAL(mdp.d_header.arcount, 0);
276
277 BOOST_CHECK_EQUAL(mdp.d_qname, name);
278 BOOST_CHECK(mdp.d_qclass == QClass::IN);
279 BOOST_CHECK(mdp.d_qtype == QType::AAAA);
280 }
281
282 // valid encrypted query with wrong key
283 BOOST_AUTO_TEST_CASE(DNSCryptEncryptedQueryInvalidWithWrongKey) {
284 DnsCryptPrivateKey resolverPrivateKey;
285 DnsCryptCert resolverCert;
286 unsigned char providerPublicKey[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE];
287 unsigned char providerPrivateKey[DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE];
288 time_t now = time(NULL);
289 DnsCryptContext::generateProviderKeys(providerPublicKey, providerPrivateKey);
290 DnsCryptContext::generateCertificate(1, now, now + (24 * 60 * 3600), providerPrivateKey, resolverPrivateKey, resolverCert);
291 DnsCryptContext ctx("2.name", resolverCert, resolverPrivateKey);
292
293 DnsCryptPrivateKey clientPrivateKey;
294 unsigned char clientPublicKey[DNSCRYPT_PUBLIC_KEY_SIZE];
295
296 DnsCryptContext::generateResolverKeyPair(clientPrivateKey, clientPublicKey);
297
298 unsigned char clientNonce[DNSCRYPT_NONCE_SIZE / 2] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, 0x09, 0x0A, 0x0B };
299
300 DNSName name("www.powerdns.com.");
301 vector<uint8_t> plainQuery;
302 DNSPacketWriter pw(plainQuery, name, QType::AAAA, QClass::IN, 0);
303 pw.getHeader()->rd = 1;
304
305 size_t requiredSize = plainQuery.size() + sizeof(DnsCryptQueryHeader) + DNSCRYPT_MAC_SIZE;
306 if (requiredSize < DnsCryptQuery::minUDPLength) {
307 requiredSize = DnsCryptQuery::minUDPLength;
308 }
309
310 plainQuery.reserve(requiredSize);
311
312 uint16_t len = plainQuery.size();
313 uint16_t encryptedResponseLen = 0;
314
315 int res = ctx.encryptQuery((char*) plainQuery.data(), len, plainQuery.capacity(), clientPublicKey, clientPrivateKey, clientNonce, false, &encryptedResponseLen);
316
317 BOOST_CHECK_EQUAL(res, 0);
318 BOOST_CHECK(encryptedResponseLen > len);
319
320 DnsCryptContext::generateCertificate(1, now, now + (24 * 60 * 3600), providerPrivateKey, resolverPrivateKey, resolverCert);
321 ctx.setNewCertificate(resolverCert, resolverPrivateKey);
322
323 DnsCryptContext::generateCertificate(1, now, now + (24 * 60 * 3600), providerPrivateKey, resolverPrivateKey, resolverCert);
324 ctx.setNewCertificate(resolverCert, resolverPrivateKey);
325
326 /* we have changed the key two times, we don't have the one used to encrypt this query */
327
328 std::shared_ptr<DnsCryptQuery> query = std::make_shared<DnsCryptQuery>();
329 uint16_t decryptedLen = 0;
330
331 ctx.parsePacket((char*) plainQuery.data(), encryptedResponseLen, query, false, &decryptedLen);
332
333 BOOST_CHECK_EQUAL(query->valid, false);
334 }
335
336 #endif
337
338 BOOST_AUTO_TEST_SUITE_END();