diff options
Diffstat (limited to 'src/lib/crypt.c')
| -rw-r--r-- | src/lib/crypt.c | 1226 |
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, ¶ms); - 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 } |
