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.c577
1 files changed, 263 insertions, 314 deletions
diff --git a/src/lib/crypt.c b/src/lib/crypt.c
index ad679501..756fcccc 100644
--- a/src/lib/crypt.c
+++ b/src/lib/crypt.c
@@ -1,8 +1,7 @@
/*
* Ouroboros - Copyright (C) 2016 - 2024
*
- * 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>
@@ -20,436 +19,386 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., http://www.fsf.org/about/contact/.
*/
+
#include <config.h>
#include <ouroboros/crypt.h>
#include <ouroboros/errno.h>
+#ifdef HAVE_OPENSSL
+ #include "crypt/openssl.h"
+#endif /* HAVE_OPENSSL */
#include <assert.h>
#include <string.h>
-#ifdef HAVE_OPENSSL
-
-#include <ouroboros/hash.h>
-#include <ouroboros/random.h>
-
-#include <openssl/evp.h>
-#include <openssl/ec.h>
-#include <openssl/pem.h>
-
-#include <openssl/bio.h>
+struct crypt_ctx {
+ uint16_t flags;
+ void * ctx;
+ uint8_t key[SYMMKEYSZ];
+};
-#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)
+int crypt_dh_pkp_create(void ** pkp,
+ uint8_t * pk)
{
- EVP_PKEY_CTX * ctx;
- int ret;
- uint8_t * secret;
- size_t secret_len;
-
- ctx = EVP_PKEY_CTX_new(kp, NULL);
- if (ctx == NULL)
- goto fail_new;
-
- ret = EVP_PKEY_derive_init(ctx);
- if (ret != 1)
- goto fail_ctx;
-
- ret = EVP_PKEY_derive_set_peer(ctx, pub);
- if (ret != 1)
- goto fail_ctx;
-
- ret = EVP_PKEY_derive(ctx, NULL, &secret_len);
- if (ret != 1)
- goto fail_ctx;
-
- if (secret_len < SYMMKEYSZ)
- goto fail_ctx;
-
- secret = OPENSSL_malloc(secret_len);
- if (secret == NULL)
- goto fail_ctx;
-
- ret = EVP_PKEY_derive(ctx, secret, &secret_len);
- if (ret != 1)
- goto fail_derive;
-
- /* Hash the secret for use as AES key. */
- mem_hash(HASH_SHA3_256, s, secret, secret_len);
+#ifdef HAVE_OPENSSL
+ assert(pkp != NULL);
+ *pkp = NULL;
+ return openssl_ecdh_pkp_create(pkp, pk);
+#else
+ (void) pkp;
+ (void) pk;
- OPENSSL_free(secret);
- EVP_PKEY_CTX_free(ctx);
+ *pkp = NULL;
return 0;
-
- 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)
+void crypt_dh_pkp_destroy(void * pkp)
{
- EVP_PKEY_CTX * ctx = NULL;
- EVP_PKEY_CTX * kctx = NULL;
- EVP_PKEY * params = NULL;
- int ret;
-
- ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
- if (ctx == NULL)
- goto fail_new_id;
-
- ret = EVP_PKEY_paramgen_init(ctx);
- if (ret != 1)
- goto fail_paramgen;
-
- ret = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, NID_X9_62_prime256v1);
- if (ret != 1)
- goto fail_paramgen;
-
- ret = EVP_PKEY_paramgen(ctx, &params);
- if (ret != 1)
- goto fail_paramgen;
-
- kctx = EVP_PKEY_CTX_new(params, NULL);
- if (kctx == NULL)
- goto fail_keygen_init;
-
- ret = EVP_PKEY_keygen_init(kctx);
- if (ret != 1)
- goto fail_keygen;
-
- ret = EVP_PKEY_keygen(kctx, (EVP_PKEY **) kp);
- if (ret != 1)
- goto fail_keygen;
+#ifdef HAVE_OPENSSL
+ openssl_ecdh_pkp_destroy(pkp);
+#else
+ (void) pkp;
+ return;
+#endif
+}
- EVP_PKEY_free(params);
- EVP_PKEY_CTX_free(kctx);
- EVP_PKEY_CTX_free(ctx);
+int crypt_dh_derive(void * pkp,
+ buffer_t pk,
+ uint8_t * s)
+{
+#ifdef HAVE_OPENSSL
+ return openssl_ecdh_derive(pkp, pk, s);
+#else
+ (void) pkp;
+ (void) pk;
- return 0;
+ memset(s, 0, SYMMKEYSZ);
- 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 crypt_encrypt(struct crypt_ctx * ctx,
+ buffer_t in,
+ buffer_t * out)
{
- uint8_t * pos;
- ssize_t len;
-
- assert(pkp != NULL);
- assert(*pkp == NULL);
- assert(pk != NULL);
-
- if (__openssl_ecdh_gen_key(pkp) < 0)
- return -ECRYPT;
-
- assert(*pkp != NULL);
-
- 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;
+ if (ctx->flags == 0) {
+ clrbuf(*out);
+ return 0;
}
- return len;
-}
+#ifdef HAVE_OPENSSL
+ return openssl_encrypt(ctx->ctx, ctx->key, in, out);
+#else
+ (void) in;
+ (void) out;
-static void openssl_ecdh_pkp_destroy(void * pkp)
-{
- EVP_PKEY_free((EVP_PKEY *) pkp);
+ return -ECRYPT;
+#endif
}
-static int openssl_ecdh_derive(void * pkp,
- buffer_t pk,
- uint8_t * s)
+int crypt_decrypt(struct crypt_ctx * ctx,
+ buffer_t in,
+ buffer_t * out)
{
- uint8_t * pos;
- EVP_PKEY * pub;
-
- pos = pk.data; /* d2i_PUBKEY increments the pointer, don't use key ptr! */
- pub = d2i_PUBKEY(NULL, (const uint8_t **) &pos, (long) pk.len);
- if (pub == NULL)
- return -ECRYPT;
-
- if (__openssl_ecdh_derive_secret(pkp, pub, s) < 0) {
- EVP_PKEY_free(pub);
- return -ECRYPT;
+ if (ctx->flags == 0) {
+ clrbuf(*out);
+ return 0;
}
- EVP_PKEY_free(pub);
+#ifdef HAVE_OPENSSL
+ return openssl_decrypt(ctx->ctx, ctx->key, in, out);
+#else
+ (void) in;
+ (void) out;
- return 0;
+ return -ECRYPT;
+#endif
}
-/*
- * 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.
- */
-
-static int openssl_encrypt(void * ctx,
- uint8_t * key,
- struct shm_du_buff * sdb)
+struct crypt_ctx * crypt_create_ctx(uint16_t flags,
+ const uint8_t * key)
{
- uint8_t * out;
- uint8_t * in;
- uint8_t * head;
- uint8_t iv[IVSZ];
- int in_sz;
- int out_sz;
- int tmp_sz;
- int ret;
-
- in = shm_du_buff_head(sdb);
- in_sz = shm_du_buff_tail(sdb) - in;
-
- assert(in_sz > 0);
-
- if (random_buffer(iv, IVSZ) < 0)
- goto fail_iv;
-
- out = malloc(in_sz + EVP_MAX_BLOCK_LENGTH);
- if (out == NULL)
- goto fail_iv;
+ struct crypt_ctx * crypt;
- EVP_CIPHER_CTX_reset(ctx);
+ crypt = malloc(sizeof(*crypt));
+ if (crypt == NULL)
+ goto fail_crypt;
- ret = EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv);
- if (ret != 1)
- goto fail_encrypt_init;
+ memset(crypt, 0, sizeof(*crypt));
- ret = EVP_EncryptUpdate(ctx, out, &tmp_sz, in, in_sz);
- if (ret != 1)
- goto fail_encrypt;
-
- out_sz = tmp_sz;
- ret = EVP_EncryptFinal_ex(ctx, out + tmp_sz, &tmp_sz);
- if (ret != 1)
- goto fail_encrypt;
-
- out_sz += tmp_sz;
-
- EVP_CIPHER_CTX_cleanup(ctx);
-
- assert(out_sz >= in_sz);
+ crypt->flags = flags;
+ if (key != NULL)
+ memcpy(crypt->key, key, SYMMKEYSZ);
+#ifdef HAVE_OPENSSL
+ crypt->ctx=openssl_crypt_create_ctx();
+ if (crypt->ctx == NULL)
+ goto fail_ctx;
+#endif
+ return crypt;
+#ifdef HAVE_OPENSSL
+ fail_ctx:
+ free(crypt);
+#endif
+ fail_crypt:
+ return NULL;
+}
- head = shm_du_buff_head_alloc(sdb, IVSZ);
- if (head == NULL)
- goto fail_encrypt;
+void crypt_destroy_ctx(struct crypt_ctx * crypt)
+{
+ if (crypt == NULL)
+ return;
- if (shm_du_buff_tail_alloc(sdb, out_sz - in_sz) == NULL)
- goto fail_tail_alloc;
+#ifdef HAVE_OPENSSL
+ assert(crypt->ctx != NULL);
+ openssl_crypt_destroy_ctx(crypt->ctx);
+#else
+ assert(crypt->ctx == NULL);
+#endif
+ free(crypt);
+}
- memcpy(head, iv, IVSZ);
- memcpy(in, out, out_sz);
+int crypt_load_privkey_file(const char * path,
+ void ** key)
+{
+ *key = NULL;
- free(out);
+#ifdef HAVE_OPENSSL
+ return openssl_load_privkey_file(path, key);
+#else
+ (void) path;
return 0;
-
- fail_tail_alloc:
- shm_du_buff_head_release(sdb, IVSZ);
- fail_encrypt:
- EVP_CIPHER_CTX_cleanup(ctx);
- fail_encrypt_init:
- free(out);
- fail_iv:
- return -ECRYPT;
+#endif
}
-static int openssl_decrypt(void * ctx,
- uint8_t * key,
- struct shm_du_buff * sdb)
+int crypt_load_privkey_str(const char * str,
+ void ** key)
{
- uint8_t * in;
- uint8_t * out;
- uint8_t iv[IVSZ];
- int ret;
- int out_sz;
- int in_sz;
- int tmp_sz;
+ *key = NULL;
- in_sz = shm_du_buff_len(sdb);
- if (in_sz < IVSZ)
- return -ECRYPT;
-
- in = shm_du_buff_head_release(sdb, IVSZ);
+#ifdef HAVE_OPENSSL
+ return openssl_load_privkey_str(str, key);
+#else
+ (void) str;
- memcpy(iv, in, IVSZ);
+ return 0;
+#endif
+}
- in = shm_du_buff_head(sdb);
- in_sz = shm_du_buff_tail(sdb) - in;
+int crypt_load_pubkey_str(const char * str,
+ void ** key)
+{
+ *key = NULL;
- out = malloc(in_sz);
- if (out == NULL)
- goto fail_malloc;
+#ifdef HAVE_OPENSSL
+ return openssl_load_pubkey_str(str, key);
+#else
+ (void) str;
- EVP_CIPHER_CTX_reset(ctx);
+ return 0;
+#endif
+}
- ret = EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv);
- if (ret != 1)
- goto fail_decrypt_init;
+int crypt_cmp_key(const void * key1,
+ const void * key2)
+{
+#ifdef HAVE_OPENSSL
+ return openssl_cmp_key(key1, key2);
+#else
+ (void) key1;
+ (void) key2;
- ret = EVP_DecryptUpdate(ctx, out, &tmp_sz, in, in_sz);
- if (ret != 1)
- goto fail_decrypt;
+ return 0;
+#endif
+}
- out_sz = tmp_sz;
+void crypt_free_key(void * key)
+{
+ if (key == NULL)
+ return;
- ret = EVP_DecryptFinal_ex(ctx, out + tmp_sz, &tmp_sz);
- if (ret != 1)
- goto fail_decrypt;
+#ifdef HAVE_OPENSSL
+ openssl_free_key(key);
+#endif
+}
- out_sz += tmp_sz;
+int crypt_load_crt_file(const char * path,
+ void ** crt)
+{
+ *crt = NULL;
- assert(out_sz <= in_sz);
+#ifdef HAVE_OPENSSL
+ return openssl_load_crt_file(path, crt);
+#else
+ (void) path;
- shm_du_buff_tail_release(sdb, in_sz - out_sz);
+ return 0;
+#endif
+}
- memcpy(in, out, out_sz);
+int crypt_load_crt_str(const char * str,
+ void ** crt)
+{
+ *crt = NULL;
- free(out);
+#ifdef HAVE_OPENSSL
+ return openssl_load_crt_str(str, crt);
+#else
+ (void) str;
return 0;
-
- fail_decrypt:
- EVP_CIPHER_CTX_cleanup(ctx);
- fail_decrypt_init:
- free(out);
- fail_malloc:
- return -ECRYPT;
-
+#endif
}
-static int openssl_crypt_init(void ** ctx)
+int crypt_get_pubkey_crt(void * crt,
+ void ** pk)
{
- *ctx = EVP_CIPHER_CTX_new();
- if (*ctx == NULL)
- return -ECRYPT;
+ assert(crt != NULL);
+ assert(pk != NULL);
+
+#ifdef HAVE_OPENSSL
+ return openssl_get_pubkey_crt(crt, pk);
+#else
+ (void) crt;
+
+ clrbuf(*pk);
return 0;
+#endif
}
-static void openssl_crypt_fini(void * ctx)
+void crypt_free_crt(void * crt)
{
- EVP_CIPHER_CTX_free(ctx);
+ if (crt == NULL)
+ return;
+#ifdef HAVE_OPENSSL
+ openssl_free_crt(crt);
+#endif
}
-#endif /* HAVE_OPENSSL */
-
-int crypt_dh_pkp_create(void ** pkp,
- uint8_t * pk)
+int crypt_crt_str(void * crt,
+ char * buf)
{
#ifdef HAVE_OPENSSL
- assert(pkp != NULL);
- *pkp = NULL;
- return openssl_ecdh_pkp_create(pkp, pk);
+ return openssl_crt_str(crt, buf);
#else
- (void) pkp;
- (void) pk;
-
- *pkp = NULL;
+ (void) crt;
+ (void) buf;
return 0;
#endif
}
-void crypt_dh_pkp_destroy(void * pkp)
+int crypt_check_crt_name(void * crt,
+ const char * name)
{
#ifdef HAVE_OPENSSL
- openssl_ecdh_pkp_destroy(pkp);
+ return openssl_check_crt_name(crt, name);
#else
- (void) pkp;
- return;
+ (void) crt;
+ (void) name;
+
+ return 0;
#endif
}
-int crypt_dh_derive(void * pkp,
- buffer_t pk,
- uint8_t * s)
+struct auth_ctx * auth_create_ctx(void)
{
-#ifdef HAVE_OPENSSL
- return openssl_ecdh_derive(pkp, pk, s);
-#else
- (void) pkp;
- (void) pk;
+ struct auth_ctx * ctx;
- memset(s, 0, SYMMKEYSZ);
+ ctx = malloc(sizeof(*ctx));
+ if (ctx == NULL)
+ goto fail_malloc;
- return -ECRYPT;
+ 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;
}
-int crypt_encrypt(struct crypt_info * info,
- struct shm_du_buff * sdb)
+void auth_destroy_ctx(struct auth_ctx * ctx)
{
- if (info->flags == 0)
- return 0;
+ 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);
+ assert(crt != NULL);
#ifdef HAVE_OPENSSL
- return openssl_encrypt(info->ctx, info->key, sdb);
+ return openssl_auth_add_crt_to_store(ctx->store, crt);
#else
- (void) sdb;
+ (void) ctx;
+ (void) crt;
- return 0;
+ return -1;
#endif
}
-int crypt_decrypt(struct crypt_info * info,
- struct shm_du_buff * sdb)
+int auth_verify_crt(struct auth_ctx * ctx,
+ void * crt)
{
- if (info->flags == 0)
- return 0;
-
#ifdef HAVE_OPENSSL
- return openssl_decrypt(info->ctx, info->key, sdb);
+ return openssl_verify_crt(ctx->store, crt);
#else
- (void) sdb;
+ (void) ctx;
+ (void) crt;
- return -ECRYPT;
+ return 0;
#endif
}
-int crypt_init(struct crypt_info * info)
+int auth_sign(void * pkp,
+ buffer_t msg,
+ buffer_t * sig)
{
#ifdef HAVE_OPENSSL
- return openssl_crypt_init(&info->ctx);
+ return openssl_sign(pkp, msg, sig);
#else
- info->ctx = NULL;
+ (void) pkp;
+ (void) msg;
+ (void) sig;
+
+ clrbuf(*sig);
+
return 0;
#endif
}
-void crypt_fini(struct crypt_info * info)
+int auth_verify_sig(void * pk,
+ buffer_t msg,
+ buffer_t sig)
{
#ifdef HAVE_OPENSSL
- openssl_crypt_fini(info->ctx);
+ return openssl_verify_sig(pk, msg, sig);
#else
- (void) info;
- assert(info->ctx == NULL);
+ (void) pk;
+ (void) msg;
+ (void) sig;
+
+ return 0;
#endif
}