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