]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/dnscrypt.hh
rec: allow exception to proxy protocal usage for specific listen addresses
[thirdparty/pdns.git] / pdns / dnscrypt.hh
CommitLineData
12471842
PL
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 */
11e1e08b
RG
22#pragma once
23#include "config.h"
83dc6a38 24#include <memory>
11e1e08b 25
77f6a2a0
RG
26#ifndef HAVE_DNSCRYPT
27
7129b5c4
RG
28/* let's just define a few types and values so that the rest of
29 the code can ignore whether DNSCrypt support is available */
30#define DNSCRYPT_MAX_RESPONSE_PADDING_AND_MAC_SIZE (0)
31
32class DNSCryptContext
33{
34};
35
77f6a2a0
RG
36class DNSCryptQuery
37{
7129b5c4
RG
38 DNSCryptQuery(const std::shared_ptr<DNSCryptContext>& ctx): d_ctx(ctx)
39 {
40 }
41private:
42 std::shared_ptr<DNSCryptContext> d_ctx{nullptr};
77f6a2a0
RG
43};
44
7129b5c4 45#else /* HAVE_DNSCRYPT */
11e1e08b 46
11e1e08b
RG
47#include <string>
48#include <vector>
43234e76
RG
49#include <arpa/inet.h>
50
11e1e08b
RG
51#include <sodium.h>
52
53#include "dnsname.hh"
f0941861 54#include "lock.hh"
32fbb2ab 55#include "noinitvector.hh"
11e1e08b
RG
56
57#define DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE (crypto_sign_ed25519_PUBLICKEYBYTES)
58#define DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE (crypto_sign_ed25519_SECRETKEYBYTES)
43234e76
RG
59#define DNSCRYPT_SIGNATURE_SIZE (crypto_sign_ed25519_BYTES)
60
11e1e08b
RG
61#define DNSCRYPT_PUBLIC_KEY_SIZE (crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES)
62#define DNSCRYPT_PRIVATE_KEY_SIZE (crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES)
63#define DNSCRYPT_NONCE_SIZE (crypto_box_curve25519xsalsa20poly1305_NONCEBYTES)
64#define DNSCRYPT_BEFORENM_SIZE (crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES)
11e1e08b 65#define DNSCRYPT_MAC_SIZE (crypto_box_curve25519xsalsa20poly1305_MACBYTES)
43234e76
RG
66
67#ifdef HAVE_CRYPTO_BOX_CURVE25519XCHACHA20POLY1305_EASY
68static_assert(crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES == crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES, "DNSCrypt public key size should be the same for all exchange versions");
69static_assert(crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES == crypto_box_curve25519xchacha20poly1305_SECRETKEYBYTES, "DNSCrypt private key size should be the same for all exchange versions");
70static_assert(crypto_box_curve25519xchacha20poly1305_NONCEBYTES == crypto_box_curve25519xsalsa20poly1305_NONCEBYTES, "DNSCrypt nonce size should be the same for all exchange versions");
71static_assert(crypto_box_curve25519xsalsa20poly1305_MACBYTES == crypto_box_curve25519xchacha20poly1305_MACBYTES, "DNSCrypt MAC size should be the same for all exchange versions");
72static_assert(crypto_box_curve25519xchacha20poly1305_BEFORENMBYTES == crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES, "DNSCrypt BEFORENM size should be the same for all exchange versions");
73#endif /* HAVE_CRYPTO_BOX_CURVE25519XCHACHA20POLY1305_EASY */
74
11e1e08b
RG
75#define DNSCRYPT_CERT_MAGIC_SIZE (4)
76#define DNSCRYPT_CERT_MAGIC_VALUE { 0x44, 0x4e, 0x53, 0x43 }
11e1e08b
RG
77#define DNSCRYPT_CERT_PROTOCOL_MINOR_VERSION_VALUE { 0x00, 0x00 }
78#define DNSCRYPT_CLIENT_MAGIC_SIZE (8)
79#define DNSCRYPT_RESOLVER_MAGIC { 0x72, 0x36, 0x66, 0x6e, 0x76, 0x57, 0x6a, 0x38 }
80#define DNSCRYPT_RESOLVER_MAGIC_SIZE (8)
81#define DNSCRYPT_PADDED_BLOCK_SIZE (64)
82#define DNSCRYPT_MAX_TCP_PADDING_SIZE (256)
83#define DNSCRYPT_MAX_RESPONSE_PADDING_SIZE (256)
84#define DNSCRYPT_MAX_RESPONSE_PADDING_AND_MAC_SIZE (DNSCRYPT_MAX_RESPONSE_PADDING_SIZE + DNSCRYPT_MAC_SIZE)
85
86/* "The client must check for new certificates every hour", so let's use one hour TTL */
87#define DNSCRYPT_CERTIFICATE_RESPONSE_TTL (3600)
88
43234e76
RG
89static_assert(DNSCRYPT_CLIENT_MAGIC_SIZE <= DNSCRYPT_PUBLIC_KEY_SIZE, "DNSCrypt Client Nonce size should be smaller or equal to public key size.");
90
91#define DNSCRYPT_CERT_ES_VERSION1_VALUE { 0x00, 0x01 }
92#define DNSCRYPT_CERT_ES_VERSION2_VALUE { 0x00, 0x02 }
11e1e08b 93
43234e76 94class DNSCryptContext;
11e1e08b 95
43234e76 96struct DNSCryptCertSignedData
11e1e08b
RG
97{
98 unsigned char resolverPK[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE];
99 unsigned char clientMagic[DNSCRYPT_CLIENT_MAGIC_SIZE];
100 uint32_t serial;
101 uint32_t tsStart;
102 uint32_t tsEnd;
103};
104
43234e76 105class DNSCryptCert
11e1e08b 106{
43234e76
RG
107public:
108 uint32_t getSerial() const
109 {
b7bd0317 110 return ntohl(signedData.serial);
43234e76
RG
111 }
112 uint32_t getTSStart() const
113 {
114 return signedData.tsStart;
115 }
116 uint32_t getTSEnd() const
117 {
118 return signedData.tsEnd;
119 }
120 bool isValid(time_t now) const
121 {
56b827c5 122 // coverity[store_truncates_time_t]
638a7c34 123 return ntohl(getTSStart()) <= static_cast<uint32_t>(now) && static_cast<uint32_t>(now) <= ntohl(getTSEnd());
43234e76 124 }
a683e8bd 125 unsigned char magic[DNSCRYPT_CERT_MAGIC_SIZE];
11e1e08b
RG
126 unsigned char esVersion[2];
127 unsigned char protocolMinorVersion[2];
128 unsigned char signature[DNSCRYPT_SIGNATURE_SIZE];
43234e76 129 struct DNSCryptCertSignedData signedData;
11e1e08b
RG
130};
131
43234e76
RG
132static_assert((sizeof(DNSCryptCertSignedData) + DNSCRYPT_SIGNATURE_SIZE) == 116, "Dnscrypt cert signed data size + signature size should be 116!");
133static_assert(sizeof(DNSCryptCert) == 124, "Dnscrypt cert size should be 124!");
11e1e08b 134
43234e76 135struct DNSCryptQueryHeader
11e1e08b
RG
136{
137 unsigned char clientMagic[DNSCRYPT_CLIENT_MAGIC_SIZE];
138 unsigned char clientPK[DNSCRYPT_PUBLIC_KEY_SIZE];
139 unsigned char clientNonce[DNSCRYPT_NONCE_SIZE / 2];
140};
141
43234e76 142static_assert(sizeof(DNSCryptQueryHeader) == 52, "Dnscrypt query header size should be 52!");
11e1e08b 143
43234e76 144struct DNSCryptResponseHeader
8089cbe5
RG
145{
146 const unsigned char resolverMagic[DNSCRYPT_RESOLVER_MAGIC_SIZE] = DNSCRYPT_RESOLVER_MAGIC;
147 unsigned char nonce[DNSCRYPT_NONCE_SIZE];
148};
149
43234e76
RG
150typedef enum {
151 VERSION1,
152 VERSION2
153} DNSCryptExchangeVersion;
154
155class DNSCryptPrivateKey
8089cbe5
RG
156{
157public:
43234e76
RG
158 DNSCryptPrivateKey();
159 ~DNSCryptPrivateKey();
8089cbe5
RG
160 void loadFromFile(const std::string& keyFile);
161 void saveToFile(const std::string& keyFile) const;
162
163 unsigned char key[DNSCRYPT_PRIVATE_KEY_SIZE];
164};
165
43234e76
RG
166struct DNSCryptCertificatePair
167{
168 unsigned char publicKey[DNSCRYPT_PUBLIC_KEY_SIZE];
169 DNSCryptCert cert;
170 DNSCryptPrivateKey privateKey;
171 bool active;
172};
173
174class DNSCryptQuery
11e1e08b
RG
175{
176public:
f3b1a1ef 177 DNSCryptQuery(const std::shared_ptr<DNSCryptContext>& ctx): d_ctx(ctx)
43234e76 178 {
94700dd5
RG
179 memset(&d_header, 0, sizeof(d_header));
180#ifdef HAVE_CRYPTO_BOX_EASY_AFTERNM
181 memset(&d_sharedKey, 0, sizeof(d_sharedKey));
182#endif /* HAVE_CRYPTO_BOX_EASY_AFTERNM */
43234e76 183 }
94700dd5 184
43234e76
RG
185 ~DNSCryptQuery();
186
187 bool isValid() const
188 {
189 return d_valid;
190 }
191
192 const DNSName& getQName() const
8089cbe5 193 {
43234e76 194 return d_qname;
8089cbe5 195 }
43234e76
RG
196
197 uint16_t getID() const
198 {
199 return d_id;
200 }
201
202 const unsigned char* getClientMagic() const
203 {
204 return d_header.clientMagic;
205 }
206
207 bool isEncrypted() const
208 {
209 return d_encrypted;
210 }
211
f3b1a1ef 212 void setCertificatePair(const std::shared_ptr<DNSCryptCertificatePair>& pair)
43234e76
RG
213 {
214 d_pair = pair;
215 }
216
32fbb2ab
RG
217 void parsePacket(PacketBuffer& packet, bool tcp, time_t now);
218 void getDecrypted(bool tcp, PacketBuffer& packet);
219 void getCertificateResponse(time_t now, PacketBuffer& response) const;
220 int encryptResponse(PacketBuffer& response, size_t maxResponseSize, bool tcp);
43234e76
RG
221
222 static const size_t s_minUDPLength = 256;
223
224private:
225 DNSCryptExchangeVersion getVersion() const;
00ffb1c2 226#ifdef HAVE_CRYPTO_BOX_EASY_AFTERNM
43234e76 227 int computeSharedKey();
00ffb1c2 228#endif /* HAVE_CRYPTO_BOX_EASY_AFTERNM */
43234e76
RG
229 void fillServerNonce(unsigned char* dest) const;
230 uint16_t computePaddingSize(uint16_t unpaddedLen, size_t maxLen) const;
32fbb2ab
RG
231 bool parsePlaintextQuery(const PacketBuffer& packet);
232 bool isEncryptedQuery(const PacketBuffer& packet, bool tcp, time_t now);
8089cbe5 233
43234e76 234 DNSCryptQueryHeader d_header;
00ffb1c2 235#ifdef HAVE_CRYPTO_BOX_EASY_AFTERNM
43234e76 236 unsigned char d_sharedKey[crypto_box_BEFORENMBYTES];
00ffb1c2 237#endif /* HAVE_CRYPTO_BOX_EASY_AFTERNM */
43234e76
RG
238 DNSName d_qname;
239 std::shared_ptr<DNSCryptContext> d_ctx{nullptr};
240 std::shared_ptr<DNSCryptCertificatePair> d_pair{nullptr};
241 uint16_t d_id{0};
242 uint16_t d_len{0};
f3b1a1ef 243 uint16_t d_paddedLen{0};
43234e76
RG
244 bool d_encrypted{false};
245 bool d_valid{false};
246
00ffb1c2 247#ifdef HAVE_CRYPTO_BOX_EASY_AFTERNM
43234e76 248 bool d_sharedKeyComputed{false};
00ffb1c2 249#endif /* HAVE_CRYPTO_BOX_EASY_AFTERNM */
11e1e08b
RG
250};
251
43234e76 252class DNSCryptContext
11e1e08b
RG
253{
254public:
255 static void generateProviderKeys(unsigned char publicKey[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE], unsigned char privateKey[DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE]);
256 static std::string getProviderFingerprint(unsigned char publicKey[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE]);
43234e76
RG
257 static void generateCertificate(uint32_t serial, time_t begin, time_t end, const DNSCryptExchangeVersion& version, const unsigned char providerPrivateKey[DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE], DNSCryptPrivateKey& privateKey, DNSCryptCert& cert);
258 static void saveCertFromFile(const DNSCryptCert& cert, const std::string&filename);
11e1e08b 259 static std::string certificateDateToStr(uint32_t date);
43234e76
RG
260 static void generateResolverKeyPair(DNSCryptPrivateKey& privK, unsigned char pubK[DNSCRYPT_PUBLIC_KEY_SIZE]);
261 static void setExchangeVersion(const DNSCryptExchangeVersion& version, unsigned char esVersion[sizeof(DNSCryptCert::esVersion)]);
262 static DNSCryptExchangeVersion getExchangeVersion(const unsigned char esVersion[sizeof(DNSCryptCert::esVersion)]);
263 static DNSCryptExchangeVersion getExchangeVersion(const DNSCryptCert& cert);
11e1e08b 264
37b6d73d
RG
265 struct CertKeyPaths
266 {
267 std::string cert;
268 std::string key;
269 };
270
271 DNSCryptContext(const std::string& pName, const std::vector<CertKeyPaths>& certKeys);
43234e76 272 DNSCryptContext(const std::string& pName, const DNSCryptCert& certificate, const DNSCryptPrivateKey& pKey);
040793d4
OM
273 ~DNSCryptContext();
274
37b6d73d 275 void reloadCertificates();
bcc62bfb
RG
276 void loadNewCertificate(const std::string& certFile, const std::string& keyFile, bool active=true, bool reload=false);
277 void addNewCertificate(const DNSCryptCert& newCert, const DNSCryptPrivateKey& newKey, bool active=true, bool reload=false);
37b6d73d 278
43234e76
RG
279 void markActive(uint32_t serial);
280 void markInactive(uint32_t serial);
281 void removeInactiveCertificate(uint32_t serial);
5a9cff11 282 std::vector<std::shared_ptr<DNSCryptCertificatePair>> getCertificates();
43234e76 283 const DNSName& getProviderName() const { return providerName; }
11e1e08b 284
32fbb2ab 285 int encryptQuery(PacketBuffer& query, size_t maximumSize, const unsigned char clientPublicKey[DNSCRYPT_PUBLIC_KEY_SIZE], const DNSCryptPrivateKey& clientPrivateKey, const unsigned char clientNonce[DNSCRYPT_NONCE_SIZE / 2], bool tcp, const std::shared_ptr<DNSCryptCert>& cert) const;
43234e76 286 bool magicMatchesAPublicKey(DNSCryptQuery& query, time_t now);
32fbb2ab 287 void getCertificateResponse(time_t now, const DNSName& qname, uint16_t qid, PacketBuffer& response);
11e1e08b
RG
288
289private:
43234e76
RG
290 static void computePublicKeyFromPrivate(const DNSCryptPrivateKey& privK, unsigned char pubK[DNSCRYPT_PUBLIC_KEY_SIZE]);
291 static void loadCertFromFile(const std::string&filename, DNSCryptCert& dest);
37b6d73d
RG
292 static std::shared_ptr<DNSCryptCertificatePair> loadCertificatePair(const std::string& certFile, const std::string& keyFile);
293
294 void addNewCertificate(std::shared_ptr<DNSCryptCertificatePair>& newCert, bool reload=false);
11e1e08b 295
6c1813a0
RG
296 SharedLockGuarded<std::vector<std::shared_ptr<DNSCryptCertificatePair>>> d_certs;
297 SharedLockGuarded<std::vector<CertKeyPaths>> d_certKeyPaths;
43234e76 298 DNSName providerName;
11e1e08b
RG
299};
300
43234e76 301bool generateDNSCryptCertificate(const std::string& providerPrivateKeyFile, uint32_t serial, time_t begin, time_t end, DNSCryptExchangeVersion version, DNSCryptCert& certOut, DNSCryptPrivateKey& keyOut);
6bb38cd6 302
11e1e08b 303#endif