@@ -128,6 +128,7 @@ openvpn_SOURCES = \
tls_crypt.c tls_crypt.h \
tun.c tun.h \
vlan.c vlan.h \
+ xkey_provider.c xkey_common.h \
win32.h win32.c \
win32-util.h win32-util.c \
cryptoapi.h cryptoapi.c
new file mode 100644
@@ -0,0 +1,45 @@
+/*
+ * OpenVPN -- An application to securely tunnel IP networks
+ * over a single TCP/UDP port, with support for SSL/TLS-based
+ * session authentication and key exchange,
+ * packet encryption, packet authentication, and
+ * packet compression.
+ *
+ * Copyright (C) 2021 Selva Nair <selva.nair@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef XKEY_COMMON_H_
+#define XKEY_COMMON_H_
+
+#include <openssl/opensslv.h>
+#if OPENSSL_VERSION_NUMBER >= 0x30000010L && !defined(DISABLE_XKEY_PROVIDER)
+#define HAVE_XKEY_PROVIDER 1
+
+#include <openssl/provider.h>
+#include <openssl/core_dispatch.h>
+
+/**
+ * Initialization function for OpenVPN external key provider for OpenSSL
+ * Follows the function signature of OSSL_PROVIDER init()
+ */
+OSSL_provider_init_fn xkey_provider_init;
+
+#define XKEY_PROV_PROPS "provider=ovpn.xkey"
+
+#endif /* HAVE_XKEY_PROVIDER */
+
+#endif /* XKEY_COMMON_H_ */
new file mode 100644
@@ -0,0 +1,169 @@
+/*
+ * OpenVPN -- An application to securely tunnel IP networks
+ * over a single TCP/UDP port, with support for SSL/TLS-based
+ * session authentication and key exchange,
+ * packet encryption, packet authentication, and
+ * packet compression.
+ *
+ * Copyright (C) 2021 Selva Nair <selva.nair@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#elif defined(_MSC_VER)
+#include "config-msvc.h"
+#endif
+
+#include "syshead.h"
+#include "error.h"
+#include "buffer.h"
+#include "xkey_common.h"
+
+#ifdef HAVE_XKEY_PROVIDER
+
+#include <openssl/provider.h>
+#include <openssl/params.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_object.h>
+#include <openssl/core_names.h>
+#include <openssl/store.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+
+/* A descriptive name */
+static const char *provname = "OpenVPN External Key Provider";
+
+typedef struct
+{
+ OSSL_LIB_CTX *libctx; /**< a child libctx for our own use */
+} XKEY_PROVIDER_CTX;
+
+/* helper to print debug messages */
+#define xkey_dmsg(f, ...) \
+ do { \
+ dmsg(f|M_NOLF, "xkey_provider: In %s: ", __func__); \
+ dmsg(f|M_NOPREFIX, __VA_ARGS__); \
+ } while(0)
+
+/* main provider interface */
+
+/* provider callbacks we implement */
+static OSSL_FUNC_provider_query_operation_fn query_operation;
+static OSSL_FUNC_provider_gettable_params_fn gettable_params;
+static OSSL_FUNC_provider_get_params_fn get_params;
+static OSSL_FUNC_provider_teardown_fn teardown;
+
+static const OSSL_ALGORITHM *
+query_operation(void *provctx, int op, int *no_store)
+{
+ xkey_dmsg(D_LOW, "op = %d", op);
+
+ *no_store = 0;
+
+ switch (op)
+ {
+ case OSSL_OP_SIGNATURE:
+ return NULL;
+
+ case OSSL_OP_KEYMGMT:
+ return NULL;
+
+ default:
+ xkey_dmsg(D_LOW, "op not supported");
+ break;
+ }
+ return NULL;
+}
+
+static const OSSL_PARAM *
+gettable_params(void *provctx)
+{
+ xkey_dmsg(D_LOW, "entry");
+
+ static const OSSL_PARAM param_types[] = {
+ OSSL_PARAM_DEFN(OSSL_PROV_PARAM_NAME, OSSL_PARAM_UTF8_PTR, NULL, 0),
+ OSSL_PARAM_END
+ };
+
+ return param_types;
+}
+static int
+get_params(void *provctx, OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ xkey_dmsg(D_LOW, "entry");
+
+ p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_NAME);
+ if (p)
+ {
+ return (OSSL_PARAM_set_utf8_ptr(p, provname) != 0);
+ }
+
+ return 0;
+}
+
+static void
+teardown(void *provctx)
+{
+ xkey_dmsg(D_LOW, "entry");
+
+ XKEY_PROVIDER_CTX *prov = provctx;
+ if (prov && prov->libctx)
+ {
+ OSSL_LIB_CTX_free(prov->libctx);
+ }
+ OPENSSL_free(prov);
+}
+
+static const OSSL_DISPATCH dispatch_table[] = {
+ {OSSL_FUNC_PROVIDER_GETTABLE_PARAMS, (void (*)(void)) gettable_params},
+ {OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void)) get_params},
+ {OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void)) query_operation},
+ {OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void)) teardown},
+ {0, NULL}
+};
+
+int
+xkey_provider_init(const OSSL_CORE_HANDLE *handle, const OSSL_DISPATCH *in,
+ const OSSL_DISPATCH **out, void **provctx)
+{
+ XKEY_PROVIDER_CTX *prov;
+
+ xkey_dmsg(D_LOW, "entry");
+
+ prov = OPENSSL_zalloc(sizeof(*prov));
+ if (!prov)
+ {
+ msg(M_NONFATAL, "xkey_provider_init: out of memory");
+ return 0;
+ }
+
+ /* Make a child libctx for our use and set default prop query
+ * on it to ensure calls we delegate won't loop back to us.
+ */
+ prov->libctx = OSSL_LIB_CTX_new_child(handle, in);
+
+ EVP_set_default_properties(prov->libctx, "provider!=ovpn.xkey");
+
+ *out = dispatch_table;
+ *provctx = prov;
+
+ return 1;
+}
+
+#endif /* HAVE_XKEY_PROVIDER */