dnscrypt functions for encrypting DNS packets. More...
#include "config.h"
#include <stdlib.h>
#include <fcntl.h>
#include <inttypes.h>
#include <sys/time.h>
#include <sys/types.h>
#include "sldns/sbuffer.h"
#include "util/config_file.h"
#include "util/net_help.h"
#include "util/netevent.h"
#include "util/log.h"
#include "util/storage/slabhash.h"
#include "util/storage/lookup3.h"
#include "dnscrypt/cert.h"
#include "dnscrypt/dnscrypt.h"
#include "dnscrypt/dnscrypt_config.h"
#include <ctype.h>
Data Structures | |
struct | shared_secret_cache_key |
struct | nonce_cache_key |
Macros | |
#define | DNSCRYPT_QUERY_BOX_OFFSET |
#define | DNSCRYPT_REPLY_BOX_OFFSET |
#define | DNSCRYPT_SHARED_SECRET_KEY_LENGTH (1 + crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES) |
Shared secret cache key length. More... | |
Functions | |
static uint32_t | dnsc_shared_secrets_cache_key (uint8_t *key, uint8_t esversion, uint8_t *pk, uint8_t *sk) |
Generate a key suitable to find shared secret in slabhash. More... | |
static void | dnsc_shared_secret_cache_insert (struct slabhash *cache, uint8_t key[DNSCRYPT_SHARED_SECRET_KEY_LENGTH], uint32_t hash, uint8_t nmkey[crypto_box_BEFORENMBYTES]) |
Inserts a shared secret into the shared_secrets_cache slabhash. More... | |
static struct lruhash_entry * | dnsc_shared_secrets_lookup (struct slabhash *cache, uint8_t key[DNSCRYPT_SHARED_SECRET_KEY_LENGTH], uint32_t hash) |
Lookup a record in shared_secrets_cache. More... | |
static uint32_t | dnsc_nonce_cache_key_hash (const uint8_t nonce[crypto_box_HALF_NONCEBYTES], const uint8_t magic_query[DNSCRYPT_MAGIC_HEADER_LEN], const uint8_t pk[crypto_box_PUBLICKEYBYTES]) |
Generate a key hash suitable to find a nonce in slabhash. More... | |
static void | dnsc_nonce_cache_insert (struct slabhash *cache, const uint8_t nonce[crypto_box_HALF_NONCEBYTES], const uint8_t magic_query[DNSCRYPT_MAGIC_HEADER_LEN], const uint8_t pk[crypto_box_PUBLICKEYBYTES], uint32_t hash) |
Inserts a nonce, magic_query, pk tuple into the nonces_cache slabhash. More... | |
static struct lruhash_entry * | dnsc_nonces_lookup (struct slabhash *cache, const uint8_t nonce[crypto_box_HALF_NONCEBYTES], const uint8_t magic_query[DNSCRYPT_MAGIC_HEADER_LEN], const uint8_t pk[crypto_box_PUBLICKEYBYTES], uint32_t hash) |
Lookup a record in nonces_cache. More... | |
static int | dnscrypt_server_uncurve (struct dnsc_env *env, const dnsccert *cert, uint8_t client_nonce[crypto_box_HALF_NONCEBYTES], uint8_t nmkey[crypto_box_BEFORENMBYTES], struct sldns_buffer *buffer) |
Decrypt a query using the dnsccert that was found using dnsc_find_cert. More... | |
size_t | dnscrypt_pad (uint8_t *buf, const size_t len, const size_t max_len, const uint8_t *nonce, const uint8_t *secretkey) |
Add random padding to a buffer, according to a client nonce. More... | |
uint64_t | dnscrypt_hrtime (void) |
static void | add_server_nonce (uint8_t *nonce) |
Add the server nonce part to once. More... | |
static int | dnscrypt_server_curve (const dnsccert *cert, uint8_t client_nonce[crypto_box_HALF_NONCEBYTES], uint8_t nmkey[crypto_box_BEFORENMBYTES], struct sldns_buffer *buffer, uint8_t udp, size_t max_udp_size) |
Encrypt a reply using the dnsccert that was used with the query. More... | |
static int | dnsc_read_from_file (char *fname, char *buf, size_t count) |
Read the content of fname into buf. More... | |
static char * | dnsc_chroot_path (struct config_file *cfg, char *path) |
Given an absolute path on the original root, returns the absolute path within the chroot. More... | |
static int | dnsc_parse_certs (struct dnsc_env *env, struct config_file *cfg) |
Parse certificates files provided by the configuration and load them into dnsc_env. More... | |
void | dnsc_key_to_fingerprint (char fingerprint[80U], const uint8_t *const key) |
Helper function to convert a binary key into a printable fingerprint. More... | |
static const dnsccert * | dnsc_find_cert (struct dnsc_env *dnscenv, struct sldns_buffer *buffer) |
Find the cert matching a DNSCrypt query. More... | |
static int | dnsc_load_local_data (struct dnsc_env *dnscenv, struct config_file *cfg) |
Insert local-zone and local-data into configuration. More... | |
static const char * | key_get_es_version (uint8_t version[2]) |
static int | dnsc_parse_keys (struct dnsc_env *env, struct config_file *cfg) |
Parse the secret key files from dnscrypt-secret-key config and populates a list of dnsccert with es_version, magic number and secret/public keys supported by dnscrypt listener. More... | |
int | dnsc_handle_curved_request (struct dnsc_env *dnscenv, struct comm_reply *repinfo) |
int | dnsc_handle_uncurved_request (struct comm_reply *repinfo) |
struct dnsc_env * | dnsc_create (void) |
int | dnsc_apply_cfg (struct dnsc_env *env, struct config_file *cfg) |
void | dnsc_delete (struct dnsc_env *env) |
size_t | dnsc_shared_secrets_sizefunc (void *k, void *ATTR_UNUSED(d)) |
int | dnsc_shared_secrets_compfunc (void *m1, void *m2) |
void | dnsc_shared_secrets_delkeyfunc (void *k, void *ATTR_UNUSED(arg)) |
void | dnsc_shared_secrets_deldatafunc (void *d, void *ATTR_UNUSED(arg)) |
size_t | dnsc_nonces_sizefunc (void *k, void *ATTR_UNUSED(d)) |
int | dnsc_nonces_compfunc (void *m1, void *m2) |
void | dnsc_nonces_delkeyfunc (void *k, void *ATTR_UNUSED(arg)) |
void | dnsc_nonces_deldatafunc (void *ATTR_UNUSED(d), void *ATTR_UNUSED(arg)) |
dnscrypt functions for encrypting DNS packets.
#define DNSCRYPT_QUERY_BOX_OFFSET |
#define DNSCRYPT_REPLY_BOX_OFFSET |
#define DNSCRYPT_SHARED_SECRET_KEY_LENGTH (1 + crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES) |
Shared secret cache key length.
secret key. 1 byte: ES_VERSION[1] 32 bytes: client crypto_box_PUBLICKEYBYTES 32 bytes: server crypto_box_SECRETKEYBYTES
|
static |
Generate a key suitable to find shared secret in slabhash.
[in] | key | a uint8_t pointer of size DNSCRYPT_SHARED_SECRET_KEY_LENGTH |
[in] | esversion | The es version least significant byte. |
[in] | pk | The public key of the client. uint8_t pointer of size crypto_box_PUBLICKEYBYTES. |
[in] | sk | The secret key of the server matching the magic query number. uint8_t pointer of size crypto_box_SECRETKEYBYTES. |
References DNSCRYPT_SHARED_SECRET_KEY_LENGTH, hashlittle(), and lruhash_entry::key.
Referenced by dnscrypt_server_uncurve().
|
static |
Inserts a shared secret into the shared_secrets_cache slabhash.
The shared secret is copied so the caller can use it freely without caring about the cache entry being evicted or not.
[in] | cache | the slabhash in which to look for the key. |
[in] | key | a uint8_t pointer of size DNSCRYPT_SHARED_SECRET_KEY_LENGTH which contains the key of the shared secret. |
[in] | hash | the hash of the key. |
[in] | nmkey | a uint8_t pointer of size crypto_box_BEFORENMBYTES which contains the shared secret. |
References lruhash_entry::data, DNSCRYPT_SHARED_SECRET_KEY_LENGTH, shared_secret_cache_key::entry, lruhash_entry::hash, shared_secret_cache_key::key, lruhash_entry::key, lruhash_entry::lock, and slabhash_insert().
Referenced by dnscrypt_server_uncurve().
|
static |
Lookup a record in shared_secrets_cache.
[in] | cache | a pointer to shared_secrets_cache slabhash. |
[in] | key | a uint8_t pointer of size DNSCRYPT_SHARED_SECRET_KEY_LENGTH containing the key to look for. |
[in] | hash | a hash of the key. |
References lruhash_entry::hash, lruhash_entry::key, and slabhash_lookup().
Referenced by dnscrypt_server_uncurve().
|
static |
Generate a key hash suitable to find a nonce in slabhash.
[in] | nonce | a uint8_t pointer of size crypto_box_HALF_NONCEBYTES |
[in] | magic_query | a uint8_t pointer of size DNSCRYPT_MAGIC_HEADER_LEN |
[in] | pk | The public key of the client. uint8_t pointer of size crypto_box_PUBLICKEYBYTES. |
References hashlittle().
Referenced by dnscrypt_server_uncurve().
|
static |
Inserts a nonce, magic_query, pk tuple into the nonces_cache slabhash.
[in] | cache | the slabhash in which to look for the key. |
[in] | nonce | a uint8_t pointer of size crypto_box_HALF_NONCEBYTES |
[in] | magic_query | a uint8_t pointer of size DNSCRYPT_MAGIC_HEADER_LEN |
[in] | pk | The public key of the client. uint8_t pointer of size crypto_box_PUBLICKEYBYTES. |
[in] | hash | the hash of the key. |
References nonce_cache_key::client_publickey, lruhash_entry::data, nonce_cache_key::entry, lruhash_entry::hash, lruhash_entry::key, lruhash_entry::lock, nonce_cache_key::magic_query, nonce_cache_key::nonce, and slabhash_insert().
Referenced by dnscrypt_server_uncurve().
|
static |
Lookup a record in nonces_cache.
[in] | cache | the slabhash in which to look for the key. |
[in] | nonce | a uint8_t pointer of size crypto_box_HALF_NONCEBYTES |
[in] | magic_query | a uint8_t pointer of size DNSCRYPT_MAGIC_HEADER_LEN |
[in] | pk | The public key of the client. uint8_t pointer of size crypto_box_PUBLICKEYBYTES. |
[in] | hash | the hash of the key. |
References nonce_cache_key::client_publickey, nonce_cache_key::entry, lruhash_entry::hash, nonce_cache_key::magic_query, nonce_cache_key::nonce, and slabhash_lookup().
Referenced by dnscrypt_server_uncurve().
|
static |
Decrypt a query using the dnsccert that was found using dnsc_find_cert.
The client nonce will be extracted from the encrypted query and stored in client_nonce, a shared secret will be computed and stored in nmkey and the buffer will be decrypted inplace.
[in] | env | the dnscrypt environment. |
[in] | cert | the cert that matches this encrypted query. |
[in] | client_nonce | where the client nonce will be stored. |
[in] | nmkey | where the shared secret key will be written. |
[in] | buffer | the encrypted buffer. |
References dnsc_nonce_cache_insert(), dnsc_nonce_cache_key_hash(), dnsc_nonces_lookup(), dnsc_shared_secret_cache_insert(), dnsc_shared_secrets_cache_key(), dnsc_shared_secrets_lookup(), DNSCRYPT_SHARED_SECRET_KEY_LENGTH, lruhash_entry::hash, nonce_cache_key::nonce, sldns_buffer_begin(), and sldns_buffer_limit().
Referenced by dnsc_handle_curved_request().
size_t dnscrypt_pad | ( | uint8_t * | buf, |
const size_t | len, | ||
const size_t | max_len, | ||
const uint8_t * | nonce, | ||
const uint8_t * | secretkey | ||
) |
Add random padding to a buffer, according to a client nonce.
The length has to depend on the query in order to avoid reply attacks.
buf | a buffer |
len | the initial size of the buffer |
max_len | the maximum size |
nonce | a nonce, made of the client nonce repeated twice |
secretkey |
|
static |
Add the server nonce part to once.
The nonce is made half of client nonce and the second half of the server nonce, both of them of size crypto_box_HALF_NONCEBYTES.
[in] | nonce | a uint8_t* of size crypto_box_NONCEBYTES |
|
static |
Encrypt a reply using the dnsccert that was used with the query.
The client nonce will be extracted from the encrypted query and stored in The buffer will be encrypted inplace.
[in] | cert | the dnsccert that matches this encrypted query. |
[in] | client_nonce | client nonce used during the query |
[in] | nmkey | shared secret key used during the query. |
[in] | buffer | the buffer where to encrypt the reply. |
[in] | udp | if whether or not it is a UDP query. |
[in] | max_udp_size | configured max udp size. |
References sldns_buffer_begin(), and sldns_buffer_limit().
|
static |
Read the content of fname into buf.
[in] | fname | name of the file to read. |
[in] | buf | the buffer in which to read the content of the file. |
[in] | count | number of bytes to read. |
Referenced by dnsc_parse_certs(), and dnsc_parse_keys().
|
static |
Given an absolute path on the original root, returns the absolute path within the chroot.
If chroot is disabled, the path is not modified. No char * is malloced so there is no need to free this.
[in] | cfg | the configuration. |
[in] | path | the path from the original root. |
References config_file::chrootdir.
Referenced by dnsc_parse_certs(), and dnsc_parse_keys().
|
static |
Parse certificates files provided by the configuration and load them into dnsc_env.
[in] | env | the dnsc_env structure to load the certs into. |
[in] | cfg | the configuration. |
References dnsc_chroot_path(), dnsc_read_from_file(), config_file::dnscrypt_provider_cert, config_file::dnscrypt_provider_cert_rotated, config_strlist::next, and config_strlist::str.
void dnsc_key_to_fingerprint | ( | char | fingerprint[80U], |
const uint8_t *const | key | ||
) |
Helper function to convert a binary key into a printable fingerprint.
[in] | fingerprint | the buffer in which to write the printable key. |
[in] | key | the key to convert. |
|
static |
Find the cert matching a DNSCrypt query.
[in] | dnscenv | The DNSCrypt environment, which contains the list of certs supported by the server. |
[in] | buffer | The encrypted DNS query. |
References sldns_buffer_begin(), and sldns_buffer_limit().
Referenced by dnsc_handle_curved_request().
|
static |
Insert local-zone and local-data into configuration.
In order to be able to serve certs over TXT, we can reuse the local-zone and local-data config option. The zone and qname are inferred from the provider_name and the content of the TXT record from the certificate content. returns the number of certificate TXT record that were loaded. < 0 in case of error.
References cfg_str2list_insert(), cfg_strlist_insert(), config_file::local_data, config_file::local_zones, log_err(), VERB_OPS, and verbose().
|
static |
Parse the secret key files from dnscrypt-secret-key
config and populates a list of dnsccert with es_version, magic number and secret/public keys supported by dnscrypt listener.
[in] | env | The dnsc_env structure which will hold the keypairs. |
[in] | cfg | The config with the secret key file paths. |
References dnsc_chroot_path(), dnsc_read_from_file(), config_file::dnscrypt_secret_key, config_strlist::next, and config_strlist::str.
int dnsc_handle_curved_request | ( | struct dnsc_env * | dnscenv, |
struct comm_reply * | repinfo | ||
) |
References comm_point::buffer, comm_reply::c, comm_point_drop_reply(), dnsc_find_cert(), dnscrypt_server_uncurve(), comm_point::repinfo, sldns_buffer_rewind(), VERB_ALGO, and verbose().
size_t dnsc_shared_secrets_sizefunc | ( | void * | k, |
void * | ATTR_UNUSEDd | ||
) |
size_t dnsc_nonces_sizefunc | ( | void * | k, |
void * | ATTR_UNUSEDd | ||
) |