diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | nDPId-test.c | 122 | ||||
-rw-r--r-- | nDPId.c | 155 | ||||
-rw-r--r-- | ncrypt.c | 812 | ||||
-rw-r--r-- | ncrypt.h | 109 | ||||
-rwxr-xr-x | scripts/gen-cacerts.sh | 70 | ||||
-rwxr-xr-x | scripts/gen_keypair.sh | 21 |
7 files changed, 247 insertions, 1044 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index f784e69df..01f8d1b81 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -397,7 +397,7 @@ endif() if(ENABLE_CRYPTO) find_package(OpenSSL REQUIRED) set(OSSL_DEFS "-DENABLE_CRYPTO=1") - set(OSSL_LIBRARY "${OPENSSL_CRYPTO_LIBRARY}") + set(OSSL_LIBRARY "${OPENSSL_SSL_LIBRARY}" "${OPENSSL_CRYPTO_LIBRARY}") endif() if(STATIC_LIBNDPI_INSTALLDIR OR BUILD_NDPI OR NDPI_NO_PKGCONFIG) diff --git a/nDPId-test.c b/nDPId-test.c index eb7cf06b4..db4d650cb 100644 --- a/nDPId-test.c +++ b/nDPId-test.c @@ -10,9 +10,6 @@ extern void nDPIsrvd_memprof_log_free(size_t free_size); // #define VERBOSE_MEMORY_PROFILING 1 #define NO_MAIN 1 #include "utils.c" -#ifdef ENABLE_CRYPTO -#include "ncrypt.c" -#endif #include "nio.c" #include "nDPIsrvd.c" #include "nDPId.c" @@ -1542,7 +1539,7 @@ static int nio_selftest() goto error; } - int pipefds[2]; + int pipefds[2] = {-1, -1}; int rv = pipe(pipefds); if (rv < 0) { @@ -1635,122 +1632,16 @@ static int nio_selftest() } nio_free(&io); + close(pipefds[0]); + close(pipefds[1]); return 0; error: nio_free(&io); + close(pipefds[0]); + close(pipefds[1]); return 1; } -#ifdef ENABLE_CRYPTO -static int ncrypt_selftest() -{ - int ret = 0; - struct ncrypt nc_peer1 = {}; - struct ncrypt nc_peer2 = {}; - struct aes aes_peer1 = {}; - struct aes aes_peer2 = {}; - unsigned char peer1_priv_key[NCRYPT_X25519_KEYLEN]; - unsigned char peer2_priv_key[NCRYPT_X25519_KEYLEN]; - unsigned char peer1_pub_key[NCRYPT_X25519_KEYLEN]; - unsigned char peer2_pub_key[NCRYPT_X25519_KEYLEN]; - unsigned char iv[NCRYPT_AES_IVLEN]; - char const plaintext[] = "Secret Message!"; - unsigned char encrypted[NCRYPT_BUFFER_SIZE]; - unsigned char tag[NCRYPT_TAG_SIZE]; - char decrypted[NCRYPT_BUFFER_SIZE]; - - memset(iv, 0x41, sizeof(iv)); - - if (ncrypt_keygen(peer1_priv_key, peer1_pub_key) != 0) - { - ret++; - } - if (ncrypt_keygen(peer2_priv_key, peer2_pub_key) != 0) - { - ret++; - } - if (ncrypt_init(&nc_peer1, peer1_priv_key, peer2_pub_key) != 0) - { - ret++; - } - if (ncrypt_init(&nc_peer2, peer2_priv_key, peer1_pub_key) != 0) - { - ret++; - } - if (ncrypt_init_encrypt(&nc_peer1, &aes_peer1) != 0) - { - ret++; - } - if (ncrypt_init_decrypt(&nc_peer2, &aes_peer2) != 0) - { - ret++; - } - int enc_bytes = ncrypt_encrypt(&aes_peer1, plaintext, sizeof(plaintext), iv, encrypted, tag); - int dec_bytes = ncrypt_decrypt(&aes_peer2, encrypted, enc_bytes, iv, tag, decrypted); - if (enc_bytes < 0 || dec_bytes < 0) - { - ret++; - } - if (memcmp(plaintext, decrypted, sizeof(plaintext)) != 0) - { - ret++; - } - - ncrypt_free_aes(&aes_peer2); - ncrypt_free_aes(&aes_peer1); - memset(decrypted, '\0', sizeof(decrypted)); - - struct nDPIsrvd_address listen_address; - if (nDPIsrvd_setup_address(&listen_address, "127.0.0.1:17443") != 0) - { - ret++; - } - if (ncrypt_add_peer(&nc_peer1, &listen_address) != 0) - { - ret++; - } - if (ncrypt_init_encrypt2(&nc_peer1, &listen_address) != 0) - { - ret++; - } - - int udp_sockfd_listen = socket(listen_address.raw.sa_family, SOCK_DGRAM, 0); - int udp_sockfd_connect = socket(listen_address.raw.sa_family, SOCK_DGRAM, 0); - if (udp_sockfd_listen < 0 || udp_sockfd_connect < 0) - { - ret++; - } - if (bind(udp_sockfd_listen, &listen_address.raw, listen_address.size) != 0) - { - ret++; - } else - if (connect(udp_sockfd_connect, &listen_address.raw, listen_address.size) < 0) - { - ret++; - } else - if (ncrypt_dgram_send(&nc_peer1, udp_sockfd_connect, plaintext, sizeof(plaintext)) != 0) - { - ret++; - } else - if (ncrypt_dgram_recv(&nc_peer2, udp_sockfd_listen, decrypted, sizeof(decrypted)) != 0) - { - ret++; - } - - if (memcmp(plaintext, decrypted, sizeof(plaintext)) != 0) - { - ret++; - } - - close(udp_sockfd_listen); - close(udp_sockfd_connect); - ncrypt_free(&nc_peer2); - ncrypt_free(&nc_peer1); - - return ret; -} -#endif - #define THREADS_RETURNED_ERROR() \ (nDPId_return.thread_return_value.val != 0 || nDPIsrvd_return.val != 0 || \ distributor_return.thread_return_value.val != 0) @@ -1784,9 +1675,6 @@ int main(int argc, char ** argv) retval += base64_selftest(); retval += nio_selftest(); -#ifdef ENABLE_CRYPTO - retval += ncrypt_selftest(); -#endif logger(1, "Selftest returned: %d%s", retval, (retval == 0 ? " (OK)" : "")); return retval; @@ -311,7 +311,7 @@ struct nDPId_workflow uint64_t current_compression_diff; #endif #ifdef ENABLE_CRYPTO - struct ncrypt crypto; + struct ncrypt_entity ncrypt_entity; #endif uint64_t last_scan_time; @@ -472,6 +472,9 @@ static MT_VALUE(zlib_compression_diff, uint64_t) = MT_INIT(0); static MT_VALUE(zlib_compression_bytes, uint64_t) = MT_INIT(0); #endif +#ifdef ENABLE_CRYPTO +static struct ncrypt_ctx ncrypt_ctx; +#endif static struct { /* options which are resolved automatically */ @@ -508,8 +511,9 @@ static struct struct cmdarg use_pfring; #endif #ifdef ENABLE_CRYPTO - struct cmdarg local_private_key_file; - struct cmdarg remote_public_key_file; + struct cmdarg client_crt_pem_file; + struct cmdarg client_key_pem_file; + struct cmdarg server_ca_pem_file; #endif /* subopts */ struct cmdarg max_flows_per_thread; @@ -562,8 +566,9 @@ static struct .use_pfring = CMDARG_BOOL(0), #endif #ifdef ENABLE_CRYPTO - .local_private_key_file = CMDARG_STR(NULL), - .remote_public_key_file = CMDARG_STR(NULL), + .client_crt_pem_file = CMDARG_STR(NULL), + .client_key_pem_file = CMDARG_STR(NULL), + .server_ca_pem_file = CMDARG_STR(NULL), #endif .max_flows_per_thread = CMDARG_ULL(nDPId_MAX_FLOWS_PER_THREAD / 2), .max_idle_flows_per_thread = CMDARG_ULL(nDPId_MAX_IDLE_FLOWS_PER_THREAD / 2), @@ -1576,68 +1581,6 @@ static struct nDPId_workflow * init_workflow(char const * const file_or_device) return NULL; } -#ifdef ENABLE_CRYPTO - if (IS_CMDARG_SET(nDPId_options.local_private_key_file) != 0 && - IS_CMDARG_SET(nDPId_options.remote_public_key_file) != 0) - { - unsigned char local_priv_key[NCRYPT_X25519_KEYLEN]; - unsigned char remote_pub_key[NCRYPT_X25519_KEYLEN]; - int rv; - - rv = chmod_chown(GET_CMDARG_STR(nDPId_options.local_private_key_file), S_IRUSR | S_IWUSR, "root", "root"); - if (rv != 0) - { - logger_early(1, - "Could not chmod/chown private key file `%s' to 0600/root: %s", - GET_CMDARG_STR(nDPId_options.local_private_key_file), - strerror(rv)); - free_workflow(&workflow); - return NULL; - } - rv = ncrypt_load_privkey(GET_CMDARG_STR(nDPId_options.local_private_key_file), local_priv_key); - if (rv != 0) - { - logger_early(1, - "Could not load (local) private key file `%s': %d", - GET_CMDARG_STR(nDPId_options.local_private_key_file), - rv); - free_workflow(&workflow); - return NULL; - } - rv = ncrypt_load_pubkey(GET_CMDARG_STR(nDPId_options.remote_public_key_file), remote_pub_key); - if (rv != 0) - { - logger_early(1, - "Could not load (remote) public key file `%s': %d", - GET_CMDARG_STR(nDPId_options.remote_public_key_file), - rv); - free_workflow(&workflow); - return NULL; - } - rv = ncrypt_init(&workflow->crypto, local_priv_key, remote_pub_key); - if (rv != 0) - { - logger_early(1, "Could not init crypto system: %d", rv); - free_workflow(&workflow); - return NULL; - } - rv = ncrypt_add_peer(&workflow->crypto, &nDPId_options.parsed_collector_address); - if (rv != 0) - { - logger(1, "Could not add peer: %d", rv); - free_workflow(&workflow); - return NULL; - } - rv = ncrypt_init_encrypt2(&workflow->crypto, &nDPId_options.parsed_collector_address); - if (rv != 0) - { - logger_early(1, "Could not init encryption mode: %d", rv); - free_workflow(&workflow); - return NULL; - } - } -#endif - return workflow; } @@ -1766,13 +1709,6 @@ static void free_workflow(struct nDPId_workflow ** const workflow) npfring_close(&w->npf); } #endif -#ifdef ENABLE_CRYPTO - if (IS_CMDARG_SET(nDPId_options.local_private_key_file) != 0 && - IS_CMDARG_SET(nDPId_options.remote_public_key_file) != 0) - { - ncrypt_free(&w->crypto); - } -#endif if (w->pcap_handle != NULL) { @@ -2690,28 +2626,6 @@ static void send_to_collector(struct nDPId_reader_thread * const reader_thread, } } -#ifdef ENABLE_CRYPTO - if (IS_CMDARG_SET(nDPId_options.local_private_key_file) != 0 && - IS_CMDARG_SET(nDPId_options.remote_public_key_file) != 0) - { - int rv; - - errno = 0; - rv = ncrypt_dgram_send(&workflow->crypto, reader_thread->collector_sockfd, newline_json_msg, (size_t)s_ret); - if (rv != 0) - { - logger(1, - "[%8llu, %zu] Crypto: encrypt and send returned %d (buffer size %d): %s", - workflow->packets_captured, - reader_thread->array_index, - rv, - s_ret, - strerror(errno)); - } - return; - } -#endif - errno = 0; ssize_t written; if (reader_thread->collector_sock_last_errno == 0 && @@ -5564,9 +5478,11 @@ static void print_usage(char const * const arg0) "\t-c\tPath to a UNIX socket (nDPIsrvd Collector) or a custom UDP endpoint.\n" "\t \tDefault: `%s'\n" #ifdef ENABLE_CRYPTO - "\t-k\tPath to the local private key file (PEM format)\n" + "\t-k\tPath to the client certificate file (PEM format)\n" + "\t \tDefault: disabled\n" + "\t-K\tPath to the client key file (PEM format)\n" "\t \tDefault: disabled\n" - "\t-K\tPath to the remote public key file (PEM format)\n" + "\t-F\tPath to the server CA file (PEM format)\n" "\t \tDefault: disabled\n" #endif #ifdef ENABLE_EPOLL @@ -5687,7 +5603,7 @@ static int nDPId_parse_options(int argc, char ** argv) { int opt; - while ((opt = getopt(argc, argv, "f:i:rIEB:tlL:c:k:K:edp:u:g:R:P:C:J:S:a:U:Azo:vh")) != -1) + while ((opt = getopt(argc, argv, "f:i:rIEB:tlL:c:k:K:F:edp:u:g:R:P:C:J:S:a:U:Azo:vh")) != -1) { switch (opt) { @@ -5731,7 +5647,7 @@ static int nDPId_parse_options(int argc, char ** argv) break; case 'k': #ifdef ENABLE_CRYPTO - set_cmdarg_string(&nDPId_options.local_private_key_file, optarg); + set_cmdarg_string(&nDPId_options.client_crt_pem_file, optarg); break; #else logger(1, "%s", "nDPId was built w/o OpenSSL/Crypto support"); @@ -5739,7 +5655,15 @@ static int nDPId_parse_options(int argc, char ** argv) #endif case 'K': #ifdef ENABLE_CRYPTO - set_cmdarg_string(&nDPId_options.remote_public_key_file, optarg); + set_cmdarg_string(&nDPId_options.client_key_pem_file, optarg); + break; +#else + logger(1, "%s", "nDPId was built w/o OpenSSL/Crypto support"); + return 1; +#endif + case 'F': +#ifdef ENABLE_CRYPTO + set_cmdarg_string(&nDPId_options.server_ca_pem_file, optarg); break; #else logger(1, "%s", "nDPId was built w/o OpenSSL/Crypto support"); @@ -6104,12 +6028,14 @@ static int validate_options(void) logger_early(1, "%s", "Higher values of max-packets-per-flow-to-send may cause superfluous network usage."); } #ifdef ENABLE_CRYPTO - if ((IS_CMDARG_SET(nDPId_options.local_private_key_file) != 0 && - IS_CMDARG_SET(nDPId_options.remote_public_key_file) == 0) || - (IS_CMDARG_SET(nDPId_options.local_private_key_file) == 0 && - IS_CMDARG_SET(nDPId_options.remote_public_key_file) != 0)) - { - logger_early(1, "%s", "Encryption requires a local private key file and a remote public key file to be set."); + if ((IS_CMDARG_SET(nDPId_options.client_crt_pem_file) != 0 && + IS_CMDARG_SET(nDPId_options.client_key_pem_file) == 0) || + (IS_CMDARG_SET(nDPId_options.client_crt_pem_file) == 0 && + IS_CMDARG_SET(nDPId_options.client_key_pem_file) != 0) || + (IS_CMDARG_SET(nDPId_options.client_crt_pem_file) != 0 && + IS_CMDARG_SET(nDPId_options.server_ca_pem_file) == 0)) + { + logger_early(1, "%s", "Encryption requires a client certificate, key and a server CA file to be set. See `-k', `-K' and `-F'."); retval = 1; } #endif @@ -6206,6 +6132,10 @@ int main(int argc, char ** argv) set_ndpi_flow_free(NULL); init_logging("nDPId"); +#ifdef ENABLE_CRYPTO + ncrypt_init(); + ncrypt_ctx_init(&ncrypt_ctx); +#endif if (nDPId_parse_options(argc, argv) != 0) { @@ -6243,6 +6173,17 @@ int main(int argc, char ** argv) return 1; } +#ifdef ENABLE_CRYPTO + if (IS_CMDARG_SET(nDPId_options.server_ca_pem_file) != 0 && + ncrypt_init_client(&ncrypt_ctx, GET_CMDARG_STR(nDPId_options.server_ca_pem_file), + GET_CMDARG_STR(nDPId_options.client_key_pem_file), + GET_CMDARG_STR(nDPId_options.client_crt_pem_file)) != NCRYPT_SUCCESS) + { + logger_early(1, "%s", "Could not initialize crypto."); + return 1; + } +#endif + log_app_info(); nDPId_print_deps_version(stdout); @@ -4,798 +4,160 @@ #include <openssl/conf.h> #include <openssl/core_names.h> #include <openssl/err.h> -#include <openssl/evp.h> -#include <openssl/kdf.h> #include <openssl/pem.h> -#include <stdlib.h> -#include <string.h> +#include <openssl/ssl.h> #include <unistd.h> -#define OPENSSL_DUMP(ptr, siz) \ - do \ - { \ - fprintf(stderr, "Raw output (%s, %zu):\n", #ptr, siz); \ - BIO_dump_indent_fp(stderr, ptr, siz, 2); \ - fputc('\n', stderr); \ - } while (0); -#define OPENSSL_ERROR(retval) \ - do \ - { \ - fprintf(stderr, "OpenSSL Error: %s\n", ERR_error_string(ERR_get_error(), NULL)); \ - } while (0); -#define PACKET_TYPE_KEYEX 0x00u -#define PACKET_TYPE_JSON 0xFFu -#define PACKET_JSON_OVERHEAD (NCRYPT_AAD_SIZE + NCRYPT_AES_IVLEN + NCRYPT_TAG_SIZE) -#define PACKET_BUFFER_SIZE (PACKET_JSON_OVERHEAD + NCRYPT_BUFFER_SIZE) -#define NCRYPT_PACKED __attribute__((__packed__)) - -static unsigned char hkdf_salt[] = {0xf2, 0xad, 0xc9, 0xca, 0x6e, 0xb3, 0xd9, 0xcd, 0x3b, 0x34, 0xf3, 0x8d, 0x75, - 0x91, 0x84, 0xbe, 0x7b, 0x1a, 0x5f, 0x80, 0x5f, 0x20, 0x86, 0x97, 0x37, 0xec, - 0x72, 0x25, 0x2a, 0x4c, 0x9d, 0x0e, 0x10, 0x8e, 0xaf, 0xf0, 0x43, 0x04, 0xb4, - 0x9e, 0xe5, 0x46, 0x41, 0xb0, 0xb1, 0xc3, 0x7c, 0x5a, 0x35, 0x2b, 0x75, 0xa9, - 0x36, 0xfc, 0x5e, 0x6c, 0xed, 0x32, 0x00, 0xd1, 0xf0, 0xb1, 0xc3, 0x0d}; - -union iv -{ - struct - { - uint32_t upper; - uint64_t lower; - } NCRYPT_PACKED numeric; - unsigned char buffer[NCRYPT_AES_IVLEN]; -}; - -union packet -{ - unsigned char raw[PACKET_BUFFER_SIZE]; - struct - { - union - { - unsigned char raw[NCRYPT_AAD_SIZE]; - struct - { - unsigned char type; - uint16_t size; - } NCRYPT_PACKED; - } NCRYPT_PACKED aad; - union - { - struct - { - unsigned char pubkey[NCRYPT_X25519_KEYLEN]; - unsigned char signature[32]; - } keyex; - struct - { - unsigned char iv[NCRYPT_AES_IVLEN]; - unsigned char tag[NCRYPT_TAG_SIZE]; - unsigned char data[NCRYPT_BUFFER_SIZE]; - } json; - }; - } NCRYPT_PACKED; -} NCRYPT_PACKED; - -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L -_Static_assert(sizeof(((union packet *)0)->aad.raw) == - sizeof(((union packet *)0)->aad.type) + sizeof(((union packet *)0)->aad.size), - "NCrypt packet AAD is not equal the expected size"); -_Static_assert(sizeof(((union packet *)0)->raw) == - sizeof(((union packet *)0)->aad) + sizeof(((union packet *)0)->json.iv) + - sizeof(((union packet *)0)->json.tag) + sizeof(((union packet *)0)->json.data), - "NCrypt packet is not equal the expected size"); -_Static_assert(sizeof(((union iv *)0)->buffer) == sizeof(((union iv *)0)->numeric), - "IV buffer must be of the same size as the numerics"); -#endif - -static inline nDPIsrvd_hashkey peer_build_hashkey(struct nDPIsrvd_address const * const peer_address) -{ - uint32_t hash = nDPIsrvd_HASHKEY_SEED; - - socklen_t slen = peer_address->size; - while (slen-- > 0) - { - hash = ((hash << 5) + hash) + ((uint8_t *)&peer_address->raw)[slen]; - } - - return hash; -} - -int ncrypt_add_peer(struct ncrypt * const nc, struct nDPIsrvd_address const * const peer_address) -{ - nDPIsrvd_hashkey peer_key = peer_build_hashkey(peer_address); - if (peer_key == nDPIsrvd_HASHKEY_SEED) - { - return -1; - } - - struct peer * peer = (struct peer *)calloc(1, sizeof(*peer)); - if (peer == NULL) - { - return -2; - } - - peer->hash_key = peer_key; - peer->address = *peer_address; - HASH_ADD_INT(nc->peers, hash_key, peer); - return 0; -} - -struct peer * ncrypt_get_peer(struct ncrypt * const nc, struct nDPIsrvd_address const * const peer_address) -{ - nDPIsrvd_hashkey peer_key = peer_build_hashkey(peer_address); - if (peer_key == nDPIsrvd_HASHKEY_SEED) - { - return NULL; - } - - struct peer * peer; - HASH_FIND_INT(nc->peers, &peer_key, peer); - if (peer == NULL) - { - return NULL; - } - - return peer; -} - -int ncrypt_keygen(unsigned char priv_key[NCRYPT_X25519_KEYLEN], unsigned char pub_key[NCRYPT_X25519_KEYLEN]) -{ - EVP_PKEY * const pkey = EVP_PKEY_Q_keygen(NULL, NULL, "X25519"); - size_t klen = NCRYPT_X25519_KEYLEN; - - if (EVP_PKEY_get_raw_private_key(pkey, priv_key, &klen) == 0 || klen != NCRYPT_X25519_KEYLEN) - { - EVP_PKEY_free(pkey); - return -1; - } - if (EVP_PKEY_get_raw_public_key(pkey, pub_key, &klen) == 0 || klen != NCRYPT_X25519_KEYLEN) - { - return -2; - EVP_PKEY_free(pkey); - } - - EVP_PKEY_free(pkey); - return 0; -} - -int ncrypt_load_privkey(char const * const private_key_file, unsigned char priv_key[NCRYPT_X25519_KEYLEN]) -{ - FILE * const pkfp = fopen(private_key_file, "r+b"); - EVP_PKEY * pkey = NULL; - size_t klen = NCRYPT_X25519_KEYLEN; - - if (pkfp == NULL) - { - return -1; - } - - pkey = PEM_read_PrivateKey(pkfp, NULL, NULL, NULL); - if (pkey == NULL) - { - fclose(pkfp); - return -2; - } - fclose(pkfp); - - if (EVP_PKEY_get_raw_private_key(pkey, priv_key, &klen) == 0 || klen != NCRYPT_X25519_KEYLEN) - { - EVP_PKEY_free(pkey); - return -3; - } - - EVP_PKEY_free(pkey); - return 0; -} - -int ncrypt_load_pubkey(char const * const public_key_file, unsigned char pub_key[NCRYPT_X25519_KEYLEN]) -{ - FILE * const pkfp = fopen(public_key_file, "r+b"); - EVP_PKEY * pkey = NULL; - size_t klen = NCRYPT_X25519_KEYLEN; - - if (pkfp == NULL) - { - return -1; - } - - pkey = PEM_read_PUBKEY(pkfp, NULL, NULL, NULL); - if (pkey == NULL) - { - fclose(pkfp); - return -2; - } - fclose(pkfp); - - if (EVP_PKEY_get_raw_public_key(pkey, pub_key, &klen) == 0 || klen != NCRYPT_X25519_KEYLEN) - { - EVP_PKEY_free(pkey); - return -3; - } - - EVP_PKEY_free(pkey); - return 0; -} - -static int init_iv(struct peer * const peer) -{ - FILE * rnd_fp; - - rnd_fp = fopen("/dev/random", "r+b"); - - if (rnd_fp == NULL) - { - return -1; - } - - if (fread(&peer->iv[0], sizeof(peer->iv[0]), sizeof(peer->iv) / sizeof(peer->iv[0]), rnd_fp) != NCRYPT_AES_IVLEN) - { - fclose(rnd_fp); - return -2; - } - - fclose(rnd_fp); - - return 0; -} - -static void next_iv(struct peer * const peer) -{ - union iv * const iv = (union iv *)&peer->iv[0]; - - uint64_t lower = be64toh(iv->numeric.lower); - lower++; - iv->numeric.lower = htobe64(lower); - - if (iv->numeric.lower == 0) - { - uint32_t upper = be32toh(iv->numeric.upper); - upper++; - iv->numeric.upper = htobe32(upper); - } -} - -static int hkdf_x25519(unsigned char shared_secret[NCRYPT_X25519_KEYLEN], - char * label, - unsigned char out[NCRYPT_X25519_KEYLEN]) -{ - EVP_KDF * kdf; - EVP_KDF_CTX * kctx; - OSSL_PARAM params[5], *p = params; - - kdf = EVP_KDF_fetch(NULL, "HKDF", NULL); - kctx = EVP_KDF_CTX_new(kdf); - EVP_KDF_free(kdf); - - *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, SN_sha256, strlen(SN_sha256)); - *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, shared_secret, NCRYPT_X25519_KEYLEN); - *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, label, strlen(label)); - *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, hkdf_salt, sizeof(hkdf_salt)); - *p = OSSL_PARAM_construct_end(); - if (EVP_KDF_derive(kctx, out, NCRYPT_X25519_KEYLEN, params) <= 0) - { - return -1; - } - - EVP_KDF_CTX_free(kctx); - return 0; -} - -int ncrypt_init(struct ncrypt * const nc, - unsigned char local_priv_key[NCRYPT_X25519_KEYLEN], - unsigned char remote_pub_key[NCRYPT_X25519_KEYLEN]) -{ - int rv = 0; - EVP_PKEY_CTX * key_ctx = NULL; - size_t pub_key_datalen = 0; - size_t secret_len = 0; - struct - { - unsigned char pub_key[NCRYPT_X25519_KEYLEN]; - unsigned char uni_dist_shared_key[NCRYPT_X25519_KEYLEN]; - } local = {.pub_key = {}, .uni_dist_shared_key = {}}; - struct - { - EVP_PKEY * pub_key; - } remote = {.pub_key = NULL}; - - if (nc->libctx != NULL) - { - return -1; - } - nc->libctx = OSSL_LIB_CTX_new(); - if (nc->libctx == NULL) - { - return -2; - } - - nc->private_key = - EVP_PKEY_new_raw_private_key_ex(nc->libctx, "X25519", nc->propq, local_priv_key, NCRYPT_X25519_KEYLEN); - if (nc->private_key == NULL) - { - return -3; - } - - if (EVP_PKEY_get_octet_string_param( - nc->private_key, OSSL_PKEY_PARAM_PUB_KEY, local.pub_key, sizeof(local.pub_key), &pub_key_datalen) == 0) - { - rv = -4; - goto error; - } - if (pub_key_datalen != NCRYPT_X25519_KEYLEN) - { - rv = -5; - goto error; - } - - remote.pub_key = - EVP_PKEY_new_raw_public_key_ex(nc->libctx, "X25519", nc->propq, remote_pub_key, NCRYPT_X25519_KEYLEN); - if (remote.pub_key == NULL) - { - rv = -6; - goto error; - } - - key_ctx = EVP_PKEY_CTX_new_from_pkey(nc->libctx, nc->private_key, nc->propq); - if (key_ctx == NULL) - { - rv = -7; - goto error; - } - - if (EVP_PKEY_derive_init(key_ctx) == 0) - { - rv = -8; - goto error; - } - - if (EVP_PKEY_derive_set_peer(key_ctx, remote.pub_key) == 0) - { - rv = -9; - goto error; - } - - if (EVP_PKEY_derive(key_ctx, NULL, &secret_len) == 0) - { - rv = -10; - goto error; - } - if (secret_len != NCRYPT_X25519_KEYLEN) - { - rv = -11; - goto error; - } - - if (EVP_PKEY_derive(key_ctx, nc->shared_secret, &secret_len) == 0) - { - rv = -12; - OPENSSL_cleanse(nc->shared_secret, NCRYPT_X25519_KEYLEN); - goto error; - } - if (hkdf_x25519(nc->shared_secret, "ncrypt initial keygen", local.uni_dist_shared_key) != 0) - { - rv = -13; - OPENSSL_cleanse(nc->shared_secret, NCRYPT_X25519_KEYLEN); - goto error; - } - - memcpy(nc->shared_secret, local.uni_dist_shared_key, NCRYPT_X25519_KEYLEN); - OPENSSL_cleanse(local_priv_key, NCRYPT_X25519_KEYLEN); - OPENSSL_cleanse(remote_pub_key, NCRYPT_X25519_KEYLEN); - -error: - EVP_PKEY_CTX_free(key_ctx); - EVP_PKEY_free(remote.pub_key); - - return rv; -} - -int ncrypt_init_encrypt(struct ncrypt * const nc, struct aes * const aes) +int ncrypt_init(void) { - aes->ctx = EVP_CIPHER_CTX_new(); - if (aes->ctx == NULL) - { - return -3; - } - - if (EVP_EncryptInit_ex(aes->ctx, EVP_aes_256_gcm(), NULL, NULL, NULL) == 0) - { - return -4; - } + SSL_load_error_strings(); + OpenSSL_add_all_algorithms(); - if (EVP_CIPHER_CTX_ctrl(aes->ctx, EVP_CTRL_GCM_SET_IVLEN, NCRYPT_AES_IVLEN, NULL) == 0) - { - return -5; - } - - if (EVP_EncryptInit_ex(aes->ctx, NULL, NULL, nc->shared_secret, NULL) == 0) - { - return -6; - } - - return 0; -} - -int ncrypt_init_encrypt2(struct ncrypt * const nc, struct nDPIsrvd_address * const peer_address) -{ - struct peer * const peer = ncrypt_get_peer(nc, peer_address); - - if (peer == NULL) - { - return -1; - } - - if (init_iv(peer) != 0) - { - return -2; - } - - return ncrypt_init_encrypt(nc, &peer->aes); + return NCRYPT_SUCCESS; } -int ncrypt_init_decrypt(struct ncrypt * const nc, struct aes * const aes) +static int ncrypt_init_ctx(struct ncrypt_ctx * const ctx, SSL_METHOD const * const meth) { - aes->ctx = EVP_CIPHER_CTX_new(); - if (aes->ctx == NULL) + if (meth == NULL) { - return -2; + return NCRYPT_NULL_PTR; } - - if (EVP_DecryptInit_ex(aes->ctx, EVP_aes_256_gcm(), NULL, NULL, NULL) == 0) + if (ctx->ssl_ctx != NULL) { - return -3; + return NCRYPT_ALREADY_INITIALIZED; } - if (EVP_CIPHER_CTX_ctrl(aes->ctx, EVP_CTRL_GCM_SET_IVLEN, NCRYPT_AES_IVLEN, NULL) == 0) + ctx->ssl_ctx = SSL_CTX_new(meth); + if (ctx->ssl_ctx == NULL) { - return -4; + return NCRYPT_NOT_INITIALIZED; } - if (EVP_DecryptInit_ex(aes->ctx, NULL, NULL, nc->shared_secret, NULL) == 0) - { - return -5; - } + SSL_CTX_set_min_proto_version(ctx->ssl_ctx, TLS1_3_VERSION); + SSL_CTX_set_max_proto_version(ctx->ssl_ctx, TLS1_3_VERSION); + SSL_CTX_set_ciphersuites(ctx->ssl_ctx, "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256"); - return 0; + return NCRYPT_SUCCESS; } -int ncrypt_init_decrypt2(struct ncrypt * const nc, struct nDPIsrvd_address * const peer_address) +static int ncrypt_load_pems(struct ncrypt_ctx * const ctx, + char const * const ca_path, + char const * const privkey_pem_path, + char const * const pubkey_pem_path) { - struct peer * const peer = ncrypt_get_peer(nc, peer_address); - - if (peer == NULL) + if (SSL_CTX_use_certificate_file(ctx->ssl_ctx, pubkey_pem_path, SSL_FILETYPE_PEM) <= 0 || + SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, privkey_pem_path, SSL_FILETYPE_PEM) <= 0 || + SSL_CTX_load_verify_locations(ctx->ssl_ctx, ca_path, NULL) <= 0) { - return -1; + return NCRYPT_PEM_LOAD_FAILED; } - return ncrypt_init_decrypt(nc, &peer->aes); -} - -void ncrypt_free_aes(struct aes * const aes) -{ - EVP_CIPHER_CTX_free(aes->ctx); - aes->ctx = NULL; + SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); + SSL_CTX_set_verify_depth(ctx->ssl_ctx, 4); + return NCRYPT_SUCCESS; } -static void cleanup_peers(struct ncrypt * const nc) +int ncrypt_init_client(struct ncrypt_ctx * const ctx, + char const * const ca_path, + char const * const privkey_pem_path, + char const * const pubkey_pem_path) { - struct peer * current_peer; - struct peer * ctmp; - - if (nc->peers == NULL) + if (ca_path == NULL || privkey_pem_path == NULL || pubkey_pem_path == NULL) { - return; + return NCRYPT_NULL_PTR; } - HASH_ITER(hh, nc->peers, current_peer, ctmp) - { - ncrypt_free_aes(¤t_peer->aes); - HASH_DEL(nc->peers, current_peer); - free(current_peer); - } -} + int rv = ncrypt_init_ctx(ctx, TLS_client_method()); -void ncrypt_free(struct ncrypt * const nc) -{ - EVP_PKEY_free(nc->private_key); - nc->private_key = NULL; - OPENSSL_cleanse(nc->shared_secret, NCRYPT_X25519_KEYLEN); - - if (nc->libctx != NULL) + if (rv != NCRYPT_SUCCESS) { - OSSL_LIB_CTX_free(nc->libctx); - nc->libctx = NULL; + return rv; } - cleanup_peers(nc); + return ncrypt_load_pems(ctx, ca_path, privkey_pem_path, pubkey_pem_path); } -static int encrypt(struct aes * const aes, - char const * const plaintext, - size_t plaintext_size, - unsigned char const iv[NCRYPT_AES_IVLEN], - unsigned char encrypted[NCRYPT_BUFFER_SIZE], - unsigned char tag[NCRYPT_TAG_SIZE], - unsigned char const aad[NCRYPT_AAD_SIZE]) +int ncrypt_init_server(struct ncrypt_ctx * const ctx, + char const * const ca_path, + char const * const privkey_pem_path, + char const * const pubkey_pem_path) { - int encrypted_used; - int remaining; - - if (EVP_EncryptInit_ex(aes->ctx, NULL, NULL, NULL, iv) == 0) - { - return -2; - } - - if (EVP_EncryptUpdate(aes->ctx, NULL, &encrypted_used, aad, NCRYPT_AAD_SIZE) == 0) + if (ca_path == NULL || privkey_pem_path == NULL || pubkey_pem_path == NULL) { - return -3; + return NCRYPT_NULL_PTR; } - if (EVP_EncryptUpdate(aes->ctx, encrypted, &encrypted_used, (const unsigned char *)plaintext, plaintext_size) == 0) - { - return -4; - } + int rv = ncrypt_init_ctx(ctx, TLS_server_method()); - if (EVP_EncryptFinal_ex(aes->ctx, encrypted + encrypted_used, &remaining) == 0) + if (rv != NCRYPT_SUCCESS) { - return -5; + return rv; } - if (EVP_CIPHER_CTX_ctrl(aes->ctx, EVP_CTRL_GCM_GET_TAG, NCRYPT_TAG_SIZE, tag) == 0) - { - return -6; - } - - return encrypted_used + remaining; -} - -int ncrypt_encrypt(struct aes * const aes, - char const * const plaintext, - size_t plaintext_size, - unsigned char const iv[NCRYPT_AES_IVLEN], - unsigned char encrypted[NCRYPT_BUFFER_SIZE], - unsigned char tag[NCRYPT_TAG_SIZE]) -{ - unsigned char const aad[NCRYPT_AAD_SIZE] = {0x00, 0x00, 0x00}; // garbage - - if (plaintext_size > NCRYPT_BUFFER_SIZE) - { - return -1; - } - - return encrypt(aes, plaintext, plaintext_size, iv, encrypted, tag, aad); + return ncrypt_load_pems(ctx, ca_path, privkey_pem_path, pubkey_pem_path); } -static int decrypt(struct aes * const aes, - unsigned char const * const encrypted, - size_t encrypt_size, - unsigned char const iv[NCRYPT_AES_IVLEN], - unsigned char tag[NCRYPT_TAG_SIZE], - char plaintext[NCRYPT_BUFFER_SIZE], - unsigned char const aad[NCRYPT_AAD_SIZE]) +int ncrypt_on_connect(struct ncrypt_ctx * const ctx, int connect_fd, struct ncrypt_entity * const ent) { - int decrypted_used; - int remaining; - - if (EVP_DecryptInit_ex(aes->ctx, NULL, NULL, NULL, iv) == 0) - { - return -2; - } - - if (EVP_DecryptUpdate(aes->ctx, NULL, &decrypted_used, aad, NCRYPT_AAD_SIZE) == 0) + if (ent->ssl == NULL) { - return -3; - } - - if (EVP_DecryptUpdate(aes->ctx, (unsigned char *)plaintext, &decrypted_used, encrypted, encrypt_size) == 0) - { - return -4; + ent->ssl = SSL_new(ctx->ssl_ctx); + if (ent->ssl == NULL) + { + return NCRYPT_NOT_INITIALIZED; + } + SSL_set_fd(ent->ssl, connect_fd); + SSL_set_connect_state(ent->ssl); } - if (EVP_CIPHER_CTX_ctrl(aes->ctx, EVP_CTRL_GCM_SET_TAG, NCRYPT_TAG_SIZE, tag) == 0) + int rv = SSL_do_handshake(ent->ssl); + if (rv != 1) { - return -5; - } + int err = SSL_get_error(ent->ssl, rv); + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) + return NCRYPT_SUCCESS; - if (EVP_DecryptFinal_ex(aes->ctx, (unsigned char *)plaintext + decrypted_used, &remaining) == 0) - { - return -6; + return err; } - return decrypted_used + remaining; + return NCRYPT_SUCCESS; } -int ncrypt_decrypt(struct aes * const aes, - unsigned char const * const encrypted, - size_t encrypt_size, - unsigned char const iv[NCRYPT_AES_IVLEN], - unsigned char tag[NCRYPT_TAG_SIZE], - char plaintext[NCRYPT_BUFFER_SIZE]) +int ncrypt_on_accept(struct ncrypt_ctx * const ctx, int accept_fd, struct ncrypt_entity * const ent) { - unsigned char const aad[NCRYPT_AAD_SIZE] = {0x00, 0x00, 0x00}; // garbage - - if (encrypt_size > NCRYPT_BUFFER_SIZE) + if (ent->ssl == NULL) { - return -1; - } - - return decrypt(aes, encrypted, encrypt_size, iv, tag, plaintext, aad); -} - -static size_t keyex_packet() -{ - return 0; -} - -static size_t json_packet(struct peer * const current_peer, - union packet * const pkt, - char const * const plaintext, - size_t plaintext_size) -{ - pkt->aad.type = PACKET_TYPE_JSON; - pkt->aad.size = htons(NCRYPT_AES_IVLEN + NCRYPT_TAG_SIZE + plaintext_size); - - int encrypted_used = encrypt( - ¤t_peer->aes, plaintext, plaintext_size, current_peer->iv, pkt->json.data, pkt->json.tag, pkt->aad.raw); - if (encrypted_used < 0 || encrypted_used > (int)NCRYPT_BUFFER_SIZE) - { - current_peer->crypto_errors++; - return 0; - } - encrypted_used += PACKET_JSON_OVERHEAD; - - current_peer->cryptions++; - memcpy(pkt->json.iv, current_peer->iv, NCRYPT_AES_IVLEN); - next_iv(current_peer); - - return encrypted_used; -} - -int ncrypt_dgram_send(struct ncrypt * const nc, int fd, char const * const plaintext, size_t plaintext_size) -{ - if (plaintext_size > NCRYPT_BUFFER_SIZE) - { - return -1; + ent->ssl = SSL_new(ctx->ssl_ctx); + if (ent->ssl == NULL) + { + return NCRYPT_NOT_INITIALIZED; + } + SSL_set_fd(ent->ssl, accept_fd); + SSL_set_accept_state(ent->ssl); } - int retval = 0; - struct peer * current_peer; - struct peer * tmp_peer; - union packet encrypted; - HASH_ITER(hh, nc->peers, current_peer, tmp_peer) + int rv = SSL_accept(ent->ssl); + if (rv != 1) { - ssize_t used; + int err = SSL_get_error(ent->ssl, rv); + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) + return NCRYPT_SUCCESS; - if (current_peer->ephemeral.current_private_key != NULL) - { - used = keyex_packet(); - if (used == 0) - { - retval++; - continue; - } - } - else - { - used = json_packet(current_peer, &encrypted, plaintext, plaintext_size); - if (used == 0) - { - retval++; - continue; - } - } - ssize_t bytes_written = - sendto(fd, encrypted.raw, used, 0, ¤t_peer->address.raw, current_peer->address.size); - if (bytes_written < 0) - { - current_peer->send_errors++; - retval++; - continue; - } - if (bytes_written != used) - { - current_peer->partial_writes++; - retval++; - continue; - } + return err; } - return retval; + return NCRYPT_SUCCESS; } -static size_t check_packet_size(union packet const * const pkt, size_t bytes_read) +void ncrypt_free_entity(struct ncrypt_entity * const ent) { - size_t payload_size = 0; - - if (bytes_read < NCRYPT_AAD_SIZE) - { - return 0; - } - payload_size = ntohs(pkt->aad.size); - switch (pkt->aad.type) - { - case PACKET_TYPE_KEYEX: - if (payload_size != sizeof(pkt->keyex)) - { - return 0; - } - break; - case PACKET_TYPE_JSON: - if (payload_size < NCRYPT_AES_IVLEN + NCRYPT_TAG_SIZE + 1) - { - return 0; - } - break; - default: - return 0; - } - if (bytes_read != NCRYPT_AAD_SIZE + payload_size) - { - return 0; - } - - return payload_size; + SSL_free(ent->ssl); + ent->ssl = NULL; } -int ncrypt_dgram_recv(struct ncrypt * const nc, int fd, char * const plaintext, size_t plaintext_size) +void ncrypt_free_ctx(struct ncrypt_ctx * const ctx) { - if (plaintext_size > NCRYPT_BUFFER_SIZE) - { - return -1; - } - - struct nDPIsrvd_address remote = {.size = sizeof(remote.raw)}; - union packet encrypted; - ssize_t bytes_read = recvfrom(fd, encrypted.raw, sizeof(encrypted.raw), 0, &remote.raw, &remote.size); - - if (bytes_read < 0) - { - return -2; - } - size_t payload_size = check_packet_size(&encrypted, bytes_read); - if (payload_size == 0) - { - return -3; - } - if (plaintext_size < payload_size) - { - return -4; - } - - struct peer * peer = ncrypt_get_peer(nc, &remote); - if (peer == NULL) - { - if (ncrypt_add_peer(nc, &remote) != 0) - { - return -5; - } - peer = ncrypt_get_peer(nc, &remote); - if (peer == NULL) - { - return -6; - } - ncrypt_init_decrypt(nc, &peer->aes); - } - - if (memcmp(peer->iv, encrypted.json.iv, NCRYPT_AES_IVLEN) != 0) - { - peer->iv_mismatches++; - memcpy(peer->iv, encrypted.json.iv, NCRYPT_AES_IVLEN); - } - int decrypted_used = decrypt(&peer->aes, - encrypted.json.data, - payload_size - NCRYPT_AES_IVLEN - NCRYPT_TAG_SIZE, - peer->iv, - encrypted.json.tag, - plaintext, - encrypted.aad.raw); - next_iv(peer); - - if (decrypted_used < 0) - { - return -7; - } - peer->cryptions++; - - return 0; + SSL_CTX_free(ctx->ssl_ctx); + ctx->ssl_ctx = NULL; + EVP_cleanup(); } @@ -1,93 +1,56 @@ #ifndef NCRYPT_H #define NCRYPT_H 1 -#include <stdlib.h> - -#include "config.h" -#include "nDPIsrvd.h" - -#define NCRYPT_X25519_KEYLEN 32 -#define NCRYPT_AES_IVLEN 12 -#define NCRYPT_TAG_SIZE 16 -#define NCRYPT_AAD_SIZE 3 // packet type + packet size -#define NCRYPT_BUFFER_SIZE NETWORK_BUFFER_MAX_SIZE - -struct aes +#define ncrypt_ctx_init(x) \ + do \ + { \ + (x)->ssl_ctx = NULL; \ + } while (0); +#define ncrypt_entity_init(x) \ + do \ + { \ + (x)->ssl = NULL; \ + (x)->handshake_done = 0; \ + } while (0); + +enum { - void * ctx; + NCRYPT_SUCCESS = 0, + NCRYPT_NOT_INITIALIZED = -1, + NCRYPT_ALREADY_INITIALIZED = -2, + NCRYPT_NULL_PTR = -3, + NCRYPT_PEM_LOAD_FAILED = -4, }; -struct peer +struct ncrypt_ctx { - nDPIsrvd_hashkey hash_key; - struct nDPIsrvd_address address; - unsigned char iv[NCRYPT_AES_IVLEN]; - struct - { - void * last_private_key; - void * current_private_key; - } ephemeral; - size_t key_rotations; - size_t cryptions; - size_t crypto_errors; - size_t iv_mismatches; - size_t send_errors; - size_t partial_writes; - struct aes aes; - UT_hash_handle hh; + void * ssl_ctx; }; -struct ncrypt +struct ncrypt_entity { - void * libctx; - const char * propq; - void * private_key; - unsigned char shared_secret[NCRYPT_X25519_KEYLEN]; - struct peer * peers; + void * ssl; + int handshake_done; }; -int ncrypt_keygen(unsigned char priv_key[NCRYPT_X25519_KEYLEN], unsigned char pub_key[NCRYPT_X25519_KEYLEN]); - -int ncrypt_load_privkey(char const * const private_key_file, unsigned char priv_key[NCRYPT_X25519_KEYLEN]); - -int ncrypt_load_pubkey(char const * const public_key_file, unsigned char pub_key[NCRYPT_X25519_KEYLEN]); - -int ncrypt_init(struct ncrypt * const nc, - unsigned char local_priv_key[NCRYPT_X25519_KEYLEN], - unsigned char remote_pub_key[NCRYPT_X25519_KEYLEN]); - -int ncrypt_init_encrypt(struct ncrypt * const nc, struct aes * const aes); - -int ncrypt_init_encrypt2(struct ncrypt * const nc, struct nDPIsrvd_address * const peer_address); - -int ncrypt_init_decrypt(struct ncrypt * const nc, struct aes * const aes); - -int ncrypt_init_decrypt2(struct ncrypt * const nc, struct nDPIsrvd_address * const peer_address); - -void ncrypt_free_aes(struct aes * const aes); - -void ncrypt_free(struct ncrypt * const nc); +int ncrypt_init(void); -int ncrypt_add_peer(struct ncrypt * const nc, struct nDPIsrvd_address const * const peer_address); +int ncrypt_init_client(struct ncrypt_ctx * const ctx, + char const * const ca_path, + char const * const privkey_pem_path, + char const * const pubkey_pem_path); -struct peer * ncrypt_get_peer(struct ncrypt * const nc, struct nDPIsrvd_address const * const peer_address); +int ncrypt_init_server(struct ncrypt_ctx * const ctx, + char const * const ca_path, + char const * const privkey_pem_path, + char const * const pubkey_pem_path); -int ncrypt_encrypt(struct aes * const aes, - char const * const plaintext, - size_t plaintext_size, - unsigned char const iv[NCRYPT_AES_IVLEN], - unsigned char encrypted[NCRYPT_BUFFER_SIZE], - unsigned char tag[NCRYPT_TAG_SIZE]); +int ncrypt_on_connect(struct ncrypt_ctx * const ctx, int connect_fd, struct ncrypt_entity * const ent); -int ncrypt_decrypt(struct aes * const aes, - unsigned char const * const encrypted, - size_t encrypted_size, - unsigned char const iv[NCRYPT_AES_IVLEN], - unsigned char tag[NCRYPT_TAG_SIZE], - char plaintext[NCRYPT_BUFFER_SIZE]); +int ncrypt_on_accept(struct ncrypt_ctx * const ctx, int accept_fd, struct ncrypt_entity * const ent); -int ncrypt_dgram_send(struct ncrypt * const nc, int fd, char const * const plaintext, size_t plaintext_size); +void ncrypt_free_entity(struct ncrypt_entity * const ent); -int ncrypt_dgram_recv(struct ncrypt * const nc, int fd, char * const plaintext, size_t plaintext_size); +void ncrypt_free_ctx(struct ncrypt_ctx * const ctx); #endif diff --git a/scripts/gen-cacerts.sh b/scripts/gen-cacerts.sh new file mode 100755 index 000000000..1c00fe737 --- /dev/null +++ b/scripts/gen-cacerts.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash + +printf 'usage: %s [out-dir] [client-cname] [server-cname]\n' "${0}" + +if [ -z "${1}" ]; then + OUT_DIR="$(dirname ${0})/pki" +else + OUT_DIR="${1}" +fi + +if [ -z "${2}" ]; then + CLIENT_CN="unknown" +else + CLIENT_CN="${2}" +fi + +if [ -z "${3}" ]; then + SERVER_CN="unknown" +else + SERVER_CN="${3}" +fi + +printf 'PKI Directory: %s\n' "${OUT_DIR}" +printf 'Client CName.: %s\n' "${CLIENT_CN}" +printf 'Server CName.: %s\n' "${SERVER_CN}" + +set -e +set -x + +OLDPWD="$(pwd)" +mkdir -p "${OUT_DIR}" +cd "${OUT_DIR}" + +if [ ! -r ./ca.key -o ! -r ./ca.crt ]; then + printf '%s\n' '[*] Create CA...' + openssl genrsa -out ./ca.key 4096 + openssl req -x509 -new -nodes -key ./ca.key -sha256 -days 3650 -out ./ca.crt -subj "/CN=nDPId Root CA" +fi + +if [ ! -r ./server_${SERVER_CN}.key -o ! -r ./server_${SERVER_CN}.crt ]; then + printf '[*] Create Server Cert: %s\n' "${SERVER_CN}" + openssl genrsa -out ./server_${SERVER_CN}.key 2048 + openssl req -new -key ./server_${SERVER_CN}.key -out ./server_${SERVER_CN}.csr -subj "/CN=${SERVER_CN}" + openssl x509 -req -in ./server_${SERVER_CN}.csr -CA ./ca.crt -CAkey ./ca.key -CAcreateserial \ + -out ./server_${SERVER_CN}.crt -days 825 -sha256 +fi + +if [ ! -r ./client_${CLIENT_CN}.key -o ! -r ./client_${CLIENT_CN}.crt ]; then + printf '[*] Create Client Cert: %s\n' "${CLIENT_CN}" + openssl genrsa -out ./client_${CLIENT_CN}.key 2048 + openssl req -new -key ./client_${CLIENT_CN}.key -out ./client_${CLIENT_CN}.csr -subj "/CN=${CLIENT_CN}" + openssl x509 -req -in ./client_${CLIENT_CN}.csr -CA ./ca.crt -CAkey ./ca.key -CAcreateserial \ + -out ./client_${CLIENT_CN}.crt -days 825 -sha256 +fi + +printf '%s\n' '[*] Done' + +cd "${OLDPWD}" + +set +x + +printf '%s\n' 'To test the certs you may use OpenSSL and start a client/server with:' +printf 'openssl s_server -accept %s -cert %s -key %s -CAfile %s -Verify 1 -verify_return_error -tls1_3\n' \ + "7777" \ + "${OUT_DIR}/server_${SERVER_CN}.crt" "${OUT_DIR}/server_${SERVER_CN}.key" \ + "${OUT_DIR}/ca.crt" +printf 'openssl s_client -connect 127.0.0.1:%s -cert %s -key %s -CAfile %s -verify_return_error -tls1_3\n' \ + "7777" \ + "${OUT_DIR}/client_${CLIENT_CN}.crt" "${OUT_DIR}/client_${CLIENT_CN}.key" \ + "${OUT_DIR}/ca.crt" diff --git a/scripts/gen_keypair.sh b/scripts/gen_keypair.sh deleted file mode 100755 index b63c62f94..000000000 --- a/scripts/gen_keypair.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -printf 'usage: %s [out-pem-private-key-file] [out-pem-public-key-file]\n' "${0}" - -if [ -z "${1}" ]; then - PRIV_KEY="./nDPId-x25519-priv.pem" -else - PRIV_KEY="${1}" -fi - -if [ -z "${2}" ]; then - PUB_KEY="./nDPId-x25519-pub.pem" -else - PUB_KEY="${2}" -fi - -printf 'Private Key: %s\n' "${PRIV_KEY}" -printf 'Public Key.: %s\n' "${PUB_KEY}" - -openssl genpkey -algorithm x25519 -out "${PRIV_KEY}" -openssl pkey -in "${PRIV_KEY}" -outform PEM -pubout -out "${PUB_KEY}" |