summaryrefslogtreecommitdiff
path: root/src/lib/crypt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/crypt.c')
-rw-r--r--src/lib/crypt.c1226
1 files changed, 959 insertions, 267 deletions
diff --git a/src/lib/crypt.c b/src/lib/crypt.c
index 1fa12bb8..cd3421dd 100644
--- a/src/lib/crypt.c
+++ b/src/lib/crypt.c
@@ -1,8 +1,7 @@
/*
- * Ouroboros - Copyright (C) 2016 - 2020
+ * Ouroboros - Copyright (C) 2016 - 2026
*
- * Elliptic curve Diffie-Hellman key exchange and
- * AES encryption for flows using OpenSSL
+ * Cryptographic operations
*
* Dimitri Staessens <dimitri@ouroboros.rocks>
* Sander Vrijders <sander@ouroboros.rocks>
@@ -21,427 +20,1120 @@
* Foundation, Inc., http://www.fsf.org/about/contact/.
*/
-#ifdef HAVE_OPENSSL
+#if defined(__linux__) || defined(__CYGWIN__)
+#define _DEFAULT_SOURCE
+#endif
+
+#include <config.h>
+
+#include <ouroboros/errno.h>
+#include <ouroboros/random.h>
+#include <ouroboros/crypt.h>
+#ifdef HAVE_OPENSSL
#include <openssl/evp.h>
-#include <openssl/ec.h>
-#include <openssl/pem.h>
+#include "crypt/openssl.h"
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+struct nid_map {
+ uint16_t nid;
+ const char * name;
+};
+
+static const struct nid_map cipher_nid_map[] = {
+ {NID_aes_128_gcm, "aes-128-gcm"},
+ {NID_aes_192_gcm, "aes-192-gcm"},
+ {NID_aes_256_gcm, "aes-256-gcm"},
+ {NID_chacha20_poly1305, "chacha20-poly1305"},
+ {NID_aes_128_ctr, "aes-128-ctr"},
+ {NID_aes_192_ctr, "aes-192-ctr"},
+ {NID_aes_256_ctr, "aes-256-ctr"},
+ {NID_undef, NULL}
+};
+
+/* Ordered in strength preference, lowest first */
+const uint16_t crypt_supported_nids[] = {
+#ifdef HAVE_OPENSSL
+ NID_aes_128_ctr,
+ NID_aes_192_ctr,
+ NID_aes_256_ctr,
+ NID_aes_128_gcm,
+ NID_aes_192_gcm,
+ NID_aes_256_gcm,
+ NID_chacha20_poly1305,
+#endif
+ NID_undef
+};
+
+static const struct nid_map kex_nid_map[] = {
+ {NID_X9_62_prime256v1, "prime256v1"},
+ {NID_secp384r1, "secp384r1"},
+ {NID_secp521r1, "secp521r1"},
+ {NID_X25519, "X25519"},
+ {NID_X448, "X448"},
+ {NID_ffdhe2048, "ffdhe2048"},
+ {NID_ffdhe3072, "ffdhe3072"},
+ {NID_ffdhe4096, "ffdhe4096"},
+ {NID_MLKEM512, "ML-KEM-512"},
+ {NID_MLKEM768, "ML-KEM-768"},
+ {NID_MLKEM1024, "ML-KEM-1024"},
+ {NID_X25519MLKEM768, "X25519MLKEM768"},
+ {NID_X448MLKEM1024, "X448MLKEM1024"},
+ {NID_undef, NULL}
+};
+
+/* Ordered in strength preference, lowest first */
+const uint16_t kex_supported_nids[] = {
+#ifdef HAVE_OPENSSL
+ NID_ffdhe2048,
+ NID_X9_62_prime256v1,
+ NID_X25519,
+ NID_ffdhe3072,
+ NID_secp384r1,
+ NID_ffdhe4096,
+ NID_X448,
+ NID_secp521r1,
+#ifdef HAVE_OPENSSL_ML_KEM
+ NID_MLKEM512,
+ NID_MLKEM768,
+ NID_MLKEM1024,
+ NID_X25519MLKEM768,
+ NID_X448MLKEM1024,
+#endif
+#endif
+ NID_undef
+};
+
+static const struct nid_map md_nid_map[] = {
+ {NID_sha256, "sha256"},
+ {NID_sha384, "sha384"},
+ {NID_sha512, "sha512"},
+ {NID_sha3_256, "sha3-256"},
+ {NID_sha3_384, "sha3-384"},
+ {NID_sha3_512, "sha3-512"},
+ {NID_blake2b512, "blake2b512"},
+ {NID_blake2s256, "blake2s256"},
+ {NID_undef, NULL}
+};
+
+/* Ordered in strength preference, lowest first */
+const uint16_t md_supported_nids[] = {
+#ifdef HAVE_OPENSSL
+ NID_blake2s256,
+ NID_sha256,
+ NID_sha3_256,
+ NID_sha384,
+ NID_sha3_384,
+ NID_blake2b512,
+ NID_sha512,
+ NID_sha3_512,
+#endif
+ NID_undef
+};
-#include <openssl/bio.h>
+struct crypt_ctx {
+ void * ctx; /* Encryption context */
+};
-#define IVSZ 16
-/* SYMMKEYSZ defined in dev.c */
+struct auth_ctx {
+ void * store;
+};
-/*
- * Derive the common secret from
- * your public key pair (kp)
- * the remote public key (pub).
- * Store it in a preallocated buffer (s).
- */
-static int __openssl_ecdh_derive_secret(EVP_PKEY * kp,
- EVP_PKEY * pub,
- uint8_t * s)
+static int parse_kex_value(const char * value,
+ struct sec_config * cfg)
{
- EVP_PKEY_CTX * ctx;
- int ret;
- uint8_t * secret;
- size_t secret_len;
+ SET_KEX_ALGO(cfg, value);
+ if (cfg->x.nid == NID_undef)
+ return -ENOTSUP;
- ctx = EVP_PKEY_CTX_new(kp, NULL);
- if (ctx == NULL)
- goto fail_new;
+ return 0;
+}
- ret = EVP_PKEY_derive_init(ctx);
- if (ret != 1)
- goto fail_ctx;
+/* not in header, but non-static for unit testing */
+int parse_sec_config(struct sec_config * cfg,
+ FILE * fp)
+{
+ char line[256];
+ char * equals;
+ char * key;
+ char * value;
+
+ assert(cfg != NULL);
+ assert(fp != NULL);
+
+ /* Set defaults */
+ SET_KEX_ALGO_NID(cfg, NID_X9_62_prime256v1);
+ cfg->x.mode = KEM_MODE_SERVER_ENCAP;
+ SET_KEX_KDF_NID(cfg, NID_sha256);
+ SET_KEX_CIPHER_NID(cfg, NID_aes_256_gcm);
+ SET_KEX_DIGEST_NID(cfg, NID_sha256);
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ char * trimmed;
+
+ /* Skip comments and empty lines */
+ if (line[0] == '#' || line[0] == '\n')
+ continue;
+
+ /* Check for 'none' keyword */
+ trimmed = trim_whitespace(line);
+ if (strcmp(trimmed, "none") == 0) {
+ memset(cfg, 0, sizeof(*cfg));
+ return 0;
+ }
+
+ /* Find the = separator */
+ equals = strchr(line, '=');
+ if (equals == NULL)
+ continue;
+
+ /* Split into key and value */
+ *equals = '\0';
+ key = trim_whitespace(line);
+ value = trim_whitespace(equals + 1);
+
+ /* Parse key exchange field */
+ if (strcmp(key, "kex") == 0) {
+ if (parse_kex_value(value, cfg) < 0)
+ return -EINVAL;
+ } else if (strcmp(key, "cipher") == 0) {
+ SET_KEX_CIPHER(cfg, value);
+ if (cfg->c.nid == NID_undef)
+ return -EINVAL;
+ } else if (strcmp(key, "kdf") == 0) {
+ SET_KEX_KDF(cfg, value);
+ if (cfg->k.nid == NID_undef)
+ return -EINVAL;
+ } else if (strcmp(key, "digest") == 0) {
+ SET_KEX_DIGEST(cfg, value);
+ if (cfg->d.nid == NID_undef)
+ return -EINVAL;
+ } else if (strcmp(key, "kem_mode") == 0) {
+ if (strcmp(value, "server") == 0) {
+ cfg->x.mode = KEM_MODE_SERVER_ENCAP;
+ } else if (strcmp(value, "client") == 0) {
+ cfg->x.mode = KEM_MODE_CLIENT_ENCAP;
+ } else {
+ return -EINVAL;
+ }
+ }
+ }
- ret = EVP_PKEY_derive_set_peer(ctx, pub);
- if (ret != 1)
- goto fail_ctx;
+ return 0;
+}
- ret = EVP_PKEY_derive(ctx, NULL, &secret_len);
- if (ret != 1)
- goto fail_ctx;
+/* Parse key exchange config from file */
+int load_sec_config_file(struct sec_config * cfg,
+ const char * path)
+{
+ FILE * fp;
+ int ret;
- if (secret_len < SYMMKEYSZ)
- goto fail_ctx;
+ assert(cfg != NULL);
+ assert(path != NULL);
- secret = OPENSSL_malloc(secret_len);
- if (secret == NULL)
- goto fail_ctx;
+ fp = fopen(path, "r");
+ if (fp == NULL) {
+ /* File doesn't exist - disable encryption */
+ CLEAR_KEX_ALGO(cfg);
+ return 0;
+ }
- ret = EVP_PKEY_derive(ctx, secret, &secret_len);
- if (ret != 1)
- goto fail_derive;
+ ret = parse_sec_config(cfg, fp);
- /* Hash the secret for use as AES key. */
- mem_hash(HASH_SHA3_256, s, secret, secret_len);
+ fclose(fp);
- OPENSSL_free(secret);
- EVP_PKEY_CTX_free(ctx);
+ return ret;
+}
+
+int kex_pkp_create(struct sec_config * cfg,
+ void ** pkp,
+ uint8_t * pk)
+{
+#ifdef HAVE_OPENSSL
+ assert(cfg != NULL);
+ assert(pkp != NULL);
+
+ *pkp = NULL;
+
+ if (cfg->x.str == NULL || kex_validate_nid(cfg->x.nid) < 0)
+ return -ENOTSUP;
+
+ return openssl_pkp_create(cfg->x.str, (EVP_PKEY **) pkp, pk);
+#else
+ (void) cfg;
+ (void) pkp;
+ (void) pk;
+
+ *pkp = NULL;
return 0;
+#endif
+}
+
+void kex_pkp_destroy(void * pkp)
+{
+ if (pkp == NULL)
+ return;
+#ifdef HAVE_OPENSSL
+ openssl_pkp_destroy((EVP_PKEY *) pkp);
+#else
+ (void) pkp;
+
+ return;
+#endif
+}
+
+int kex_dhe_derive(struct sec_config * cfg,
+ void * pkp,
+ buffer_t pk,
+ uint8_t * s)
+{
+ assert(cfg != NULL);
+
+ if (kex_validate_nid(cfg->x.nid) < 0)
+ return -ENOTSUP;
+
+#ifdef HAVE_OPENSSL
+ return openssl_dhe_derive((EVP_PKEY *) pkp, pk, cfg->k.nid, s);
+#else
+ (void) pkp;
+ (void) pk;
+
+ memset(s, 0, SYMMKEYSZ);
- fail_derive:
- OPENSSL_free(secret);
- fail_ctx:
- EVP_PKEY_CTX_free(ctx);
- fail_new:
return -ECRYPT;
+#endif
}
-static int __openssl_ecdh_gen_key(void ** kp)
+ssize_t kex_kem_encap(buffer_t pk,
+ uint8_t * ct,
+ int kdf,
+ uint8_t * s)
{
- EVP_PKEY_CTX * ctx = NULL;
- EVP_PKEY_CTX * kctx = NULL;
- EVP_PKEY * params = NULL;
- int ret;
+#ifdef HAVE_OPENSSL
+ return openssl_kem_encap(pk, ct, kdf, s);
+#else
+ (void) pk;
+ (void) ct;
+ (void) kdf;
- ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
- if (ctx == NULL)
- goto fail_new_id;
+ memset(s, 0, SYMMKEYSZ);
- ret = EVP_PKEY_paramgen_init(ctx);
- if (ret != 1)
- goto fail_paramgen;
+ return -ECRYPT;
+#endif
+}
- ret = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, NID_X9_62_prime256v1);
- if (ret != 1)
- goto fail_paramgen;
+ssize_t kex_kem_encap_raw(buffer_t pk,
+ uint8_t * ct,
+ int kdf,
+ uint8_t * s)
+{
+#ifdef HAVE_OPENSSL
+ return openssl_kem_encap_raw(pk, ct, kdf, s);
+#else
+ (void) pk;
+ (void) ct;
+ (void) kdf;
- ret = EVP_PKEY_paramgen(ctx, &params);
- if (ret != 1)
- goto fail_paramgen;
+ memset(s, 0, SYMMKEYSZ);
- kctx = EVP_PKEY_CTX_new(params, NULL);
- if (kctx == NULL)
- goto fail_keygen_init;
+ return -ECRYPT;
+#endif
+}
- ret = EVP_PKEY_keygen_init(kctx);
- if (ret != 1)
- goto fail_keygen;
+int kex_kem_decap(void * pkp,
+ buffer_t ct,
+ int kdf,
+ uint8_t * s)
+{
+#ifdef HAVE_OPENSSL
+ return openssl_kem_decap((EVP_PKEY *) pkp, ct, kdf, s);
+#else
+ (void) pkp;
+ (void) ct;
+ (void) kdf;
- ret = EVP_PKEY_keygen(kctx, (EVP_PKEY **) kp);
- if (ret != 1)
- goto fail_keygen;
+ memset(s, 0, SYMMKEYSZ);
- EVP_PKEY_free(params);
- EVP_PKEY_CTX_free(kctx);
- EVP_PKEY_CTX_free(ctx);
+ return -ECRYPT;
+#endif
+}
- return 0;
+int kex_get_algo_from_pk_der(buffer_t pk,
+ char * algo)
+{
+#ifdef HAVE_OPENSSL
+ return openssl_get_algo_from_pk_der(pk, algo);
+#else
+ (void) pk;
+ algo[0] = '\0';
- fail_keygen:
- EVP_PKEY_CTX_free(kctx);
- fail_keygen_init:
- EVP_PKEY_free(params);
- fail_paramgen:
- EVP_PKEY_CTX_free(ctx);
- fail_new_id:
return -ECRYPT;
+#endif
}
-static ssize_t openssl_ecdh_pkp_create(void ** pkp,
- uint8_t * pk)
+int kex_get_algo_from_pk_raw(buffer_t pk,
+ char * algo)
{
- uint8_t * pos;
- ssize_t len;
+#ifdef HAVE_OPENSSL
+ return openssl_get_algo_from_pk_raw(pk, algo);
+#else
+ (void) pk;
+ algo[0] = '\0';
- assert(pkp != NULL);
- assert(*pkp == NULL);
- assert(pk != NULL);
+ return -ECRYPT;
+#endif
+}
+
+int kex_validate_algo(const char * algo)
+{
+ if (algo == NULL)
+ return -EINVAL;
- if (__openssl_ecdh_gen_key(pkp) < 0)
- return -ECRYPT;
+ /* Use NID validation instead of string array */
+ return kex_validate_nid(kex_str_to_nid(algo));
+}
+
+int crypt_validate_nid(int nid)
+{
+ const struct nid_map * p;
- assert(*pkp != NULL);
+ if (nid == NID_undef)
+ return -EINVAL;
- pos = pk; /* i2d_PUBKEY increments the pointer, don't use buf! */
- len = i2d_PUBKEY(*pkp, &pos);
- if (len < 0) {
- EVP_PKEY_free(*pkp);
- return -ECRYPT;
+ for (p = cipher_nid_map; p->name != NULL; p++) {
+ if (p->nid == nid)
+ return 0;
}
- return len;
+ return -ENOTSUP;
}
-static void openssl_ecdh_pkp_destroy(void * pkp)
+
+const char * crypt_nid_to_str(uint16_t nid)
{
- EVP_PKEY_free((EVP_PKEY *) pkp);
+ const struct nid_map * p;
+
+ for (p = cipher_nid_map; p->name != NULL; p++) {
+ if (p->nid == nid)
+ return p->name;
+ }
+
+ return NULL;
}
-static int openssl_ecdh_derive(void * pkp,
- uint8_t * pk,
- size_t len,
- uint8_t * s)
+uint16_t crypt_str_to_nid(const char * cipher)
{
- uint8_t * pos;
- EVP_PKEY * pub;
+ const struct nid_map * p;
- pos = pk; /* d2i_PUBKEY increments the pointer, don't use key ptr! */
- pub = d2i_PUBKEY(NULL, (const uint8_t **) &pos, (long) len);
- if (pub == NULL)
- return -ECRYPT;
+ if (cipher == NULL)
+ return NID_undef;
- if (__openssl_ecdh_derive_secret(pkp, pub, s) < 0) {
- EVP_PKEY_free(pub);
- return -ECRYPT;
+ /* fast, check if cipher pointer is in the map */
+ for (p = cipher_nid_map; p->name != NULL; p++) {
+ if (cipher == p->name)
+ return p->nid;
}
- EVP_PKEY_free(pub);
+ for (p = cipher_nid_map; p->name != NULL; p++) {
+ if (strcmp(p->name, cipher) == 0)
+ return p->nid;
+ }
- return 0;
+ return NID_undef;
}
-/*
- * AES encryption calls. If FRCT is disabled, we should generate a
- * 128-bit random IV and append it to the packet. If the flow is
- * reliable, we could initialize the context once, and consider the
- * stream a single encrypted message to avoid initializing the
- * encryption context for each packet.
- */
+const char * kex_nid_to_str(uint16_t nid)
+{
+ const struct nid_map * p;
+
+ for (p = kex_nid_map; p->name != NULL; p++) {
+ if (p->nid == nid)
+ return p->name;
+ }
+
+ return NULL;
+}
-static int openssl_encrypt(struct flow * f,
- struct shm_du_buff * sdb)
+uint16_t kex_str_to_nid(const char * algo)
{
- uint8_t * out;
- uint8_t * in;
- uint8_t * head;
- uint8_t iv[IVSZ];
- int in_sz;
- int out_sz;
- int tmp_sz;
- int ret;
+ const struct nid_map * p;
- in = shm_du_buff_head(sdb);
- in_sz = shm_du_buff_tail(sdb) - in;
+ if (algo == NULL)
+ return NID_undef;
- if (random_buffer(iv, IVSZ) < 0)
- goto fail_iv;
+ /* Fast path: check if algo pointer is in the map */
+ for (p = kex_nid_map; p->name != NULL; p++) {
+ if (algo == p->name)
+ return p->nid;
+ }
- out = malloc(in_sz + EVP_MAX_BLOCK_LENGTH);
- if (out == NULL)
- goto fail_iv;
+ /* Slow path: string comparison */
+ for (p = kex_nid_map; p->name != NULL; p++) {
+ if (strcmp(p->name, algo) == 0)
+ return p->nid;
+ }
- EVP_CIPHER_CTX_reset(f->ctx);
+ return NID_undef;
+}
- ret = EVP_EncryptInit_ex(f->ctx,
- EVP_aes_256_cbc(),
- NULL,
- f->key,
- iv);
- if (ret != 1)
- goto fail_encrypt_init;
+int kex_validate_nid(int nid)
+{
+ const struct nid_map * p;
- ret = EVP_EncryptUpdate(f->ctx, out, &tmp_sz, in, in_sz);
- if (ret != 1)
- goto fail_encrypt;
+ if (nid == NID_undef)
+ return -EINVAL;
- out_sz = tmp_sz;
- ret = EVP_EncryptFinal_ex(f->ctx, out + tmp_sz, &tmp_sz);
- if (ret != 1)
- goto fail_encrypt;
+ for (p = kex_nid_map; p->name != NULL; p++) {
+ if (p->nid == nid)
+ return 0;
+ }
- out_sz += tmp_sz;
+ return -ENOTSUP;
+}
- EVP_CIPHER_CTX_cleanup(f->ctx);
+const char * md_nid_to_str(uint16_t nid)
+{
+ const struct nid_map * p;
- assert(out_sz >= in_sz);
+ for (p = md_nid_map; p->name != NULL; p++) {
+ if (p->nid == nid)
+ return p->name;
+ }
- head = shm_du_buff_head_alloc(sdb, IVSZ);
- if (head == NULL)
- goto fail_encrypt;
+ return NULL;
+}
- if (shm_du_buff_tail_alloc(sdb, out_sz - in_sz) == NULL)
- goto fail_tail_alloc;
+uint16_t md_str_to_nid(const char * kdf)
+{
+ const struct nid_map * p;
- memcpy(head, iv, IVSZ);
- memcpy(in, out, out_sz);
+ if (kdf == NULL)
+ return NID_undef;
- free(out);
+ /* Fast path: check if kdf pointer is in the map */
+ for (p = md_nid_map; p->name != NULL; p++) {
+ if (kdf == p->name)
+ return p->nid;
+ }
- return 0;
+ /* Slow path: string comparison */
+ for (p = md_nid_map; p->name != NULL; p++) {
+ if (strcmp(p->name, kdf) == 0)
+ return p->nid;
+ }
+
+ return NID_undef;
+}
+
+int md_validate_nid(int nid)
+{
+ const struct nid_map * p;
+
+ if (nid == NID_undef)
+ return -EINVAL;
+
+ for (p = md_nid_map; p->name != NULL; p++) {
+ if (p->nid == nid)
+ return 0;
+ }
+
+ return -ENOTSUP;
+}
+
+int crypt_cipher_rank(int nid)
+{
+ int i;
+
+ if (nid == NID_undef)
+ return 0;
+
+ for (i = 0; crypt_supported_nids[i] != NID_undef; i++) {
+ if ((int) crypt_supported_nids[i] == nid)
+ return i + 1;
+ }
+
+ return -1;
+}
+
+int crypt_kdf_rank(int nid)
+{
+ int i;
+
+ if (nid == NID_undef)
+ return 0;
+
+ for (i = 0; md_supported_nids[i] != NID_undef; i++) {
+ if ((int) md_supported_nids[i] == nid)
+ return i + 1;
+ }
+
+ return -1;
+}
+
+int crypt_kex_rank(int nid)
+{
+ int i;
+
+ if (nid == NID_undef)
+ return 0;
+
+ for (i = 0; kex_supported_nids[i] != NID_undef; i++) {
+ if ((int) kex_supported_nids[i] == nid)
+ return i + 1;
+ }
+
+ return -1;
+}
+
+/* Hash length now returned by md_digest() */
+
+int crypt_encrypt(struct crypt_ctx * ctx,
+ buffer_t in,
+ buffer_t * out)
+{
+ assert(ctx != NULL);
+ assert(ctx->ctx != NULL);
+
+#ifdef HAVE_OPENSSL
+ return openssl_encrypt(ctx->ctx, in, out);
+#else
+ (void) ctx;
+ (void) in;
+ (void) out;
- fail_tail_alloc:
- shm_du_buff_head_release(sdb, IVSZ);
- fail_encrypt:
- EVP_CIPHER_CTX_cleanup(f->ctx);
- fail_encrypt_init:
- free(out);
- fail_iv:
return -ECRYPT;
+#endif
}
-static int openssl_decrypt(struct flow * f,
- struct shm_du_buff * sdb)
+int crypt_decrypt(struct crypt_ctx * ctx,
+ buffer_t in,
+ buffer_t * out)
{
- uint8_t * in;
- uint8_t * out;
- uint8_t iv[IVSZ];
- int ret;
- int out_sz;
- int in_sz;
- int tmp_sz;
+ assert(ctx != NULL);
+ assert(ctx->ctx != NULL);
- in = shm_du_buff_head_release(sdb, IVSZ);
+#ifdef HAVE_OPENSSL
+ return openssl_decrypt(ctx->ctx, in, out);
+#else
+ (void) ctx;
+ (void) in;
+ (void) out;
- memcpy(iv, in, IVSZ);
+ return -ECRYPT;
+#endif
+}
- in = shm_du_buff_head(sdb);
+struct crypt_ctx * crypt_create_ctx(struct crypt_sk * sk)
+{
+ struct crypt_ctx * crypt;
- in_sz = shm_du_buff_tail(sdb) - shm_du_buff_head(sdb);
+ if (crypt_validate_nid(sk->nid) != 0)
+ return NULL;
- out = malloc(in_sz);
- if (out == NULL)
- goto fail_malloc;
+ crypt = malloc(sizeof(*crypt));
+ if (crypt == NULL)
+ goto fail_crypt;
+
+ memset(crypt, 0, sizeof(*crypt));
+
+#ifdef HAVE_OPENSSL
+ crypt->ctx = openssl_crypt_create_ctx(sk);
+ if (crypt->ctx == NULL)
+ goto fail_ctx;
+#endif
+ return crypt;
+#ifdef HAVE_OPENSSL
+ fail_ctx:
+ free(crypt);
+#endif
+ fail_crypt:
+ return NULL;
+}
+
+void crypt_destroy_ctx(struct crypt_ctx * crypt)
+{
+ if (crypt == NULL)
+ return;
+
+#ifdef HAVE_OPENSSL
+ assert(crypt->ctx != NULL);
+ openssl_crypt_destroy_ctx(crypt->ctx);
+#else
+ assert(crypt->ctx == NULL);
+#endif
+ free(crypt);
+}
+
+int crypt_get_ivsz(struct crypt_ctx * ctx)
+{
+ if (ctx == NULL)
+ return -EINVAL;
+
+#ifdef HAVE_OPENSSL
+ assert(ctx->ctx != NULL);
+ return openssl_crypt_get_ivsz(ctx->ctx);
+#else
+ assert(ctx->ctx == NULL);
+ return -ENOTSUP;
+#endif
+}
- EVP_CIPHER_CTX_reset(f->ctx);
+int crypt_get_tagsz(struct crypt_ctx * ctx)
+{
+ if (ctx == NULL)
+ return -EINVAL;
- ret = EVP_DecryptInit_ex(f->ctx,
- EVP_aes_256_cbc(),
- NULL,
- f->key,
- iv);
- if (ret != 1)
- goto fail_decrypt_init;
+#ifdef HAVE_OPENSSL
+ assert(ctx->ctx != NULL);
+ return openssl_crypt_get_tagsz(ctx->ctx);
+#else
+ assert(ctx->ctx == NULL);
+ return -ENOTSUP;
+#endif
+}
- ret = EVP_DecryptUpdate(f->ctx, out, &tmp_sz, in, in_sz);
- if (ret != 1)
- goto fail_decrypt;
+int crypt_load_privkey_file(const char * path,
+ void ** key)
+{
+ *key = NULL;
- out_sz = tmp_sz;
+#ifdef HAVE_OPENSSL
+ return openssl_load_privkey_file(path, key);
+#else
+ (void) path;
- ret = EVP_DecryptFinal_ex(f->ctx, out + tmp_sz, &tmp_sz);
- if (ret != 1)
- goto fail_decrypt;
+ return 0;
+#endif
+}
- out_sz += tmp_sz;
+int crypt_load_privkey_str(const char * str,
+ void ** key)
+{
+ *key = NULL;
- assert(out_sz <= in_sz);
+#ifdef HAVE_OPENSSL
+ return openssl_load_privkey_str(str, key);
+#else
+ (void) str;
- shm_du_buff_tail_release(sdb, in_sz - out_sz);
+ return 0;
+#endif
+}
- memcpy(in, out, out_sz);
+int crypt_load_pubkey_str(const char * str,
+ void ** key)
+{
+ *key = NULL;
- free(out);
+#ifdef HAVE_OPENSSL
+ return openssl_load_pubkey_str(str, key);
+#else
+ (void) str;
return 0;
+#endif
+}
- fail_decrypt:
- EVP_CIPHER_CTX_cleanup(f->ctx);
- fail_decrypt_init:
- free(out);
- fail_malloc:
- return -ECRYPT;
+int crypt_load_pubkey_file(const char * path,
+ void ** key)
+{
+ *key = NULL;
+#ifdef HAVE_OPENSSL
+ return openssl_load_pubkey_file(path, key);
+#else
+ (void) path;
+
+ return 0;
+#endif
+}
+
+int crypt_load_pubkey_file_to_der(const char * path,
+ buffer_t * buf)
+{
+ assert(buf != NULL);
+
+#ifdef HAVE_OPENSSL
+ return openssl_load_pubkey_file_to_der(path, buf);
+#else
+ (void) path;
+
+ buf->data = NULL;
+ buf->len = 0;
+ return 0;
+#endif
+}
+
+int crypt_load_pubkey_raw_file(const char * path,
+ buffer_t * buf)
+{
+ assert(buf != NULL);
+
+#ifdef HAVE_OPENSSL
+ return openssl_load_pubkey_raw_file(path, buf);
+#else
+ (void) path;
+
+ buf->data = NULL;
+ buf->len = 0;
+ return 0;
+#endif
}
-static int openssl_crypt_init(void ** ctx)
+int crypt_load_privkey_raw_file(const char * path,
+ void ** key)
{
- *ctx = EVP_CIPHER_CTX_new();
- if (*ctx == NULL)
- return -ECRYPT;
+ *key = NULL;
+
+#ifdef HAVE_OPENSSL
+ return openssl_load_privkey_raw_file(path, key);
+#else
+ (void) path;
return 0;
+#endif
}
-static void openssl_crypt_fini(void * ctx)
+int crypt_cmp_key(const void * key1,
+ const void * key2)
{
- EVP_CIPHER_CTX_free(ctx);
+#ifdef HAVE_OPENSSL
+ return openssl_cmp_key((const EVP_PKEY *) key1,
+ (const EVP_PKEY *) key2);
+#else
+ (void) key1;
+ (void) key2;
+
+ return 0;
+#endif
}
-#endif /* HAVE_OPENSSL */
+void crypt_free_key(void * key)
+{
+ if (key == NULL)
+ return;
+
+#ifdef HAVE_OPENSSL
+ openssl_free_key((EVP_PKEY *) key);
+#endif
+}
-static int crypt_dh_pkp_create(void ** pkp,
- uint8_t * pk)
+int crypt_load_crt_file(const char * path,
+ void ** crt)
{
+ assert(crt != NULL);
+
+ *crt = NULL;
+
#ifdef HAVE_OPENSSL
- assert(pkp != NULL);
- *pkp = NULL;
- return openssl_ecdh_pkp_create(pkp, pk);
+ return openssl_load_crt_file(path, crt);
#else
- (void) pkp;
- (void) pk;
+ (void) path;
- memset(pk, 0, MSGBUFSZ);
+ return 0;
+#endif
+}
- return -ECRYPT;
+int crypt_load_crt_str(const char * str,
+ void ** crt)
+{
+ assert(crt != NULL);
+
+ *crt = NULL;
+
+#ifdef HAVE_OPENSSL
+ return openssl_load_crt_str(str, crt);
+#else
+ (void) str;
+
+ return 0;
#endif
}
-static void crypt_dh_pkp_destroy(void * pkp)
+int crypt_load_crt_der(const buffer_t buf,
+ void ** crt)
{
+ assert(crt != NULL);
#ifdef HAVE_OPENSSL
- openssl_ecdh_pkp_destroy(pkp);
+ return openssl_load_crt_der(buf, crt);
#else
- (void) pkp;
+ *crt = NULL;
+
+ (void) buf;
+
return 0;
#endif
}
-static int crypt_dh_derive(void * pkp,
- uint8_t * pk,
- size_t len,
- uint8_t * s)
+int crypt_get_pubkey_crt(void * crt,
+ void ** pk)
{
+ assert(crt != NULL);
+ assert(pk != NULL);
+
#ifdef HAVE_OPENSSL
- return openssl_ecdh_derive(pkp, pk, len, s);
+ return openssl_get_pubkey_crt(crt, pk);
#else
- (void) pkp;
- (void) pk;
- (void) len;
+ (void) crt;
- memset(s, 0, SYMMKEYSZ);
+ clrbuf(*pk);
- return -ECRYPT;
+ return 0;
+#endif
+}
+
+void crypt_free_crt(void * crt)
+{
+ if (crt == NULL)
+ return;
+#ifdef HAVE_OPENSSL
+ openssl_free_crt(crt);
#endif
}
-static int crypt_encrypt(struct flow * f,
- struct shm_du_buff * sdb)
+int crypt_crt_str(const void * crt,
+ char * buf)
{
#ifdef HAVE_OPENSSL
- return openssl_encrypt(f, sdb);
+ return openssl_crt_str(crt, buf);
#else
- (void) f;
- (void) sdb;
+ (void) crt;
+ (void) buf;
return 0;
#endif
}
-static int crypt_decrypt(struct flow * f,
- struct shm_du_buff * sdb)
+int crypt_crt_der(const void * crt,
+ buffer_t * buf)
{
+ assert(crt != NULL);
+ assert(buf != NULL);
+
#ifdef HAVE_OPENSSL
- return openssl_decrypt(f, sdb);
+ return openssl_crt_der(crt, buf);
#else
- (void) f;
- (void) sdb;
+ (void) crt;
- return -ECRYPT;
+ clrbuf(*buf);
+
+ return 0;
#endif
}
-static int crypt_init(void ** ctx)
+int crypt_check_crt_name(void * crt,
+ const char * name)
{
#ifdef HAVE_OPENSSL
- return openssl_crypt_init(ctx);
+ return openssl_check_crt_name(crt, name);
#else
+ (void) crt;
+ (void) name;
+
+ return 0;
+#endif
+}
+
+int crypt_get_crt_name(void * crt,
+ char * name)
+{
+#ifdef HAVE_OPENSSL
+ return openssl_get_crt_name(crt, name);
+#else
+ (void) crt;
+ (void) name;
+
+ return 0;
+#endif
+}
+
+struct auth_ctx * auth_create_ctx(void)
+{
+ struct auth_ctx * ctx;
+
+ ctx = malloc(sizeof(*ctx));
+ if (ctx == NULL)
+ goto fail_malloc;
+
+ memset(ctx, 0, sizeof(*ctx));
+#ifdef HAVE_OPENSSL
+ ctx->store = openssl_auth_create_store();
+ if (ctx->store == NULL)
+ goto fail_store;
+#endif
+ return ctx;
+#ifdef HAVE_OPENSSL
+ fail_store:
+ free(ctx);
+#endif
+ fail_malloc:
+ return NULL;
+}
+
+void auth_destroy_ctx(struct auth_ctx * ctx)
+{
+ if (ctx == NULL)
+ return;
+#ifdef HAVE_OPENSSL
+ openssl_auth_destroy_store(ctx->store);
+#endif
+ free(ctx);
+}
+
+int auth_add_crt_to_store(struct auth_ctx * ctx,
+ void * crt)
+{
assert(ctx != NULL);
- *ctx = NULL;
+ assert(crt != NULL);
+
+#ifdef HAVE_OPENSSL
+ return openssl_auth_add_crt_to_store(ctx->store, crt);
+#else
+ (void) ctx;
+ (void) crt;
return 0;
#endif
}
-static void crypt_fini(void * ctx)
+int auth_verify_crt(struct auth_ctx * ctx,
+ void * crt)
{
#ifdef HAVE_OPENSSL
- openssl_crypt_fini(ctx);
+ return openssl_verify_crt(ctx->store, crt);
#else
- assert(ctx == NULL);
(void) ctx;
+ (void) crt;
+
+ return 0;
+#endif
+}
+
+int auth_sign(void * pkp,
+ int md_nid,
+ buffer_t msg,
+ buffer_t * sig)
+{
+#ifdef HAVE_OPENSSL
+ return openssl_sign((EVP_PKEY *) pkp, md_nid, msg, sig);
+#else
+ (void) pkp;
+ (void) md_nid;
+ (void) msg;
+ (void) sig;
+
+ clrbuf(*sig);
+
+ return 0;
+#endif
+}
+
+int auth_verify_sig(void * pk,
+ int md_nid,
+ buffer_t msg,
+ buffer_t sig)
+{
+#ifdef HAVE_OPENSSL
+ return openssl_verify_sig((EVP_PKEY *) pk, md_nid, msg, sig);
+#else
+ (void) pk;
+ (void) md_nid;
+ (void) msg;
+ (void) sig;
+
+ return 0;
+#endif
+}
+
+ssize_t md_digest(int md_nid,
+ buffer_t in,
+ uint8_t * out)
+{
+#ifdef HAVE_OPENSSL
+ return openssl_md_digest(md_nid, in, out);
+#else
+ (void) md_nid;
+ (void) in;
+ (void) out;
+
+ return -1;
+#endif
+}
+
+ssize_t md_len(int md_nid)
+{
+#ifdef HAVE_OPENSSL
+ return openssl_md_len(md_nid);
+#else
+ (void) md_nid;
+ return -1;
+#endif
+}
+
+int crypt_secure_malloc_init(size_t max)
+{
+#ifdef HAVE_OPENSSL
+ return openssl_secure_malloc_init(max, SECMEM_GUARD);
+#else
+ (void) max;
+ return 0;
+#endif
+}
+
+void crypt_secure_malloc_fini(void)
+{
+#ifdef HAVE_OPENSSL
+ openssl_secure_malloc_fini();
+#endif
+}
+
+void * crypt_secure_malloc(size_t size)
+{
+#ifdef HAVE_OPENSSL
+ return openssl_secure_malloc(size);
+#else
+ return malloc(size);
+#endif
+}
+
+void crypt_secure_free(void * ptr,
+ size_t size)
+{
+ if (ptr == NULL)
+ return;
+
+#ifdef HAVE_OPENSSL
+ openssl_secure_free(ptr, size);
+#else
+ memset(ptr, 0, size);
+ free(ptr);
+#endif
+}
+
+void crypt_secure_clear(void * ptr,
+ size_t size)
+{
+ volatile uint8_t * p;
+
+ if (ptr == NULL)
+ return;
+
+#ifdef HAVE_OPENSSL
+ (void) p;
+ openssl_secure_clear(ptr, size);
+#elif defined(HAVE_EXPLICIT_BZERO)
+ (void) p;
+ explicit_bzero(ptr, size);
+#else /* best effort to avoid optimizing out */
+ p = ptr;
+ while (size-- > 0)
+ *p++ = 0;
#endif
}