From patchwork Wed Sep 22 11:12:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Selva Nair X-Patchwork-Id: 1964 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director7.mail.ord1d.rsapps.net ([172.31.255.6]) by backend30.mail.ord1d.rsapps.net with LMTP id KOPBGaecS2FVCQAAIUCqbw (envelope-from ) for ; Wed, 22 Sep 2021 17:14:15 -0400 Received: from proxy8.mail.iad3b.rsapps.net ([172.31.255.6]) by director7.mail.ord1d.rsapps.net with LMTP id sNuHGaecS2FCPAAAovjBpQ (envelope-from ) for ; Wed, 22 Sep 2021 17:14:15 -0400 Received: from smtp25.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy8.mail.iad3b.rsapps.net with LMTPS id 6GErEqecS2EMWwAAoCsc3g (envelope-from ) for ; Wed, 22 Sep 2021 17:14:15 -0400 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp25.gate.iad3b.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dkim=fail (signature verification failed) header.d=gmail.com; dmarc=fail (p=none; dis=none) header.from=gmail.com X-Suspicious-Flag: YES X-Classification-ID: 09aed5b0-1bea-11ec-b6e0-52540030a522-1-1 Received: from [216.105.38.7] ([216.105.38.7:50888] helo=lists.sourceforge.net) by smtp25.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id DE/8D-13837-6AC9B416; Wed, 22 Sep 2021 17:14:15 -0400 Received: from [127.0.0.1] (helo=sfs-ml-1.v29.lw.sourceforge.com) by sfs-ml-1.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1mT9YM-00079b-4X; Wed, 22 Sep 2021 21:13:18 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mT9YJ-00079D-B8 for openvpn-devel@lists.sourceforge.net; Wed, 22 Sep 2021 21:13:15 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=0mRKQv3SECsG9au41u7PEECNDP2cq6T+2/d/2vsNHyI=; b=DjUSQNGRsXGxaluxWOwJ2hUJx/ 4iPnGXEuDiW/q88pXsUrmOvOW4xwzVnAhYloHnc/BVg2FbOif8QjM7bCYSN/SUhwHJASgWbe1x0Yy QfAeYs3ZQX5i+iBVFfV532ezHfT4AKh2SsCCi2IMvZjunuJSMLRhoPup5bo1yHLxlLjs=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-Id: Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=0mRKQv3SECsG9au41u7PEECNDP2cq6T+2/d/2vsNHyI=; b=dQ1ceoo5CJ0vDKzotPXOnn6mWT GXeunKegz75OdD8b2anhP+joPxOa7izV8yxlqsQESFSRIhy1en2Oio28tMDENMnDjKskakyao9tl5 mnjrsm/CCYf1lec5mlPEPUEsWzZ3QOhUQijv44EGOrZppN7z4LJJ3rjlxqzUxTYnQ+eo=; Received: from mail-qt1-f171.google.com ([209.85.160.171]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.92.3) id 1mT9YE-0022yN-No for openvpn-devel@lists.sourceforge.net; Wed, 22 Sep 2021 21:13:15 +0000 Received: by mail-qt1-f171.google.com with SMTP id r16so4127093qtw.11 for ; Wed, 22 Sep 2021 14:13:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=0mRKQv3SECsG9au41u7PEECNDP2cq6T+2/d/2vsNHyI=; b=bhn5UJRqeprrAtX8Z+EXZSjXFm2b1kL5qM51n2+Mbd8cazrZIHKodMdRWB1QjoDqY4 mXfU/x0XO7twTcuJiGr51ujaabsA6GapyMbbGdfc/6e3fetgkb4RltNQcvJsd3tvP+2o 78TOT6LZ1d4WHAyUyn6THYctSE4vEggi8j9YUUuGf4NLd9VBCSV8OM82GF8XaldyNYWM aM1OgxI70NLvZ//pkzNPF8Jse+xGx6vwg/yCh9Wca+WiS4Hc9h6K/H2+i1JuW783nLkg epOC5+lGvfE1TTeyokGsJj4zXiSPsuS5J0Kd0MJMSx0FWSc9DGzxb/hmZ25rEYy7e8Kw MA+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=0mRKQv3SECsG9au41u7PEECNDP2cq6T+2/d/2vsNHyI=; b=jVyXUhU3Ydp4QXelUxfHPAEJvGUQXcIQZKt+Jxd7fnzzoQfgbOEI8NzKWDgIvqwGWc ZeVYY2b/m+O7KEVsVZxAsO0/EsKwtXFf0uw5O6bXJZQ3FKAAU1H2KNdrb8jDYX+Lz7RE mOvV8lNlB7MUFol+xzaKbDE4AapeQaSCxrvh4AyP6jbaRDMQqTgUeWODFBisYL+RZEoo R0r4S4W+JwiyLMrc06mmaElAkZj0bryytZtuoVCDSjy4vcCEti7XbUFcLOI6nE92qoSs e/uIWKwA5JKuHlOhk9BaPWgXhB9WfNOCJ8F/Zub0P1a3ldfCE32Rvw9PtFy/b5N9LnuK 9Rqw== X-Gm-Message-State: AOAM531h+KD97IYji1fmk54AOForEAVlrWSwr33DomTfS6c7KguCps1w jtHEcPffpsQm9oakTA2ewNnrd1DiF/w= X-Google-Smtp-Source: ABdhPJz0kx135UoDPHTeaCrgA8ilLH6cAjMZ5jVEDVKfCkywTKVPfLfROFNf+FggpvlcuLxOEnS2pw== X-Received: by 2002:a05:622a:4d4:: with SMTP id q20mr1458858qtx.271.1632345184709; Wed, 22 Sep 2021 14:13:04 -0700 (PDT) Received: from uranus.home.sansel.ca (bras-vprn-tnhlon4053w-lp130-02-70-51-223-227.dsl.bell.ca. [70.51.223.227]) by smtp.gmail.com with ESMTPSA id l7sm2185243qth.19.2021.09.22.14.13.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 22 Sep 2021 14:13:04 -0700 (PDT) From: selva.nair@gmail.com To: openvpn-devel@lists.sourceforge.net Date: Wed, 22 Sep 2021 17:12:48 -0400 Message-Id: <20210922211254.7570-4-selva.nair@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210922211254.7570-1-selva.nair@gmail.com> References: <20210922211254.7570-1-selva.nair@gmail.com> MIME-Version: 1.0 X-Spam-Report: Spam detection software, running on the system "util-spamd-1.v13.lw.sourceforge.com", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From: Selva Nair A minimal set of functions for keymgmt are implemented. No support for external key import as yet, only native keys. Support for native keys is required as all public key ops will get delegated to us [...] Content analysis details: (-0.2 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [selva.nair[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record -0.0 RCVD_IN_MSPIKE_H2 RBL: Average reputation (+2) [209.85.160.171 listed in wl.mailspike.net] -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [209.85.160.171 listed in list.dnswl.org] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid X-Headers-End: 1mT9YE-0022yN-No Subject: [Openvpn-devel] [PATCH 3/9] Implement keymgmt in the xkey provider X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox From: Selva Nair A minimal set of functions for keymgmt are implemented. No support for external key import as yet, only native keys. Support for native keys is required as all public key ops will get delegated to us once SSL_CTX is initialized in our context. This will include digest-verify using peer's public key. To test key import, use the normal --key operation, change use_xkey_provider() to return true. The key will import correctly but signing will fail as there is no signature interface in the provider yet. (use enable-debug for the dmsg() chatter). Sign-verify operations for native keys is in the next commit. Signed-off-by: Selva Nair --- src/openvpn/xkey_provider.c | 353 ++++++++++++++++++++++++++++++++++++ 1 file changed, 353 insertions(+) diff --git a/src/openvpn/xkey_provider.c b/src/openvpn/xkey_provider.c index 9d19d37d..4e5ed130 100644 --- a/src/openvpn/xkey_provider.c +++ b/src/openvpn/xkey_provider.c @@ -43,6 +43,9 @@ #include #include +/* propq set all on all ops we implement */ +static const char *const props = XKEY_PROV_PROPS; + /* A descriptive name */ static const char *provname = "OpenVPN External Key Provider"; @@ -53,6 +56,353 @@ typedef struct OSSL_LIB_CTX *libctx; /* libctx of the core context in which we are running */ } XKEY_PROVIDER_CTX; +typedef enum +{ + ORIGIN_NONAME = 0, + OPENSSL_NATIVE, /* native key imported in */ + EXTERNAL_KEY +} XKEY_ORIGIN; + +/* + * XKEY_KEYDATA: Our keydata encapsulation: + * --------------------------------------- + * We keep an opaque handle provided by the backend for the loaded + * key. It's passed back to the backend for any operation on private + * keys --- in practice, sign() op only. + * + * We also keep the public key in the form of a native OpenSSL EVP_PKEY. + * This allows us to do all public ops by calling ops in the default provider. + */ +typedef struct +{ + /* opaque handle dependent on KEY_ORIGIN -- could be NULL */ + void *handle; + /* associated public key as an openvpn native key */ + EVP_PKEY *pubkey; + /* origin of key -- native or external */ + XKEY_ORIGIN origin; + int refcount; /* reference count */ +} XKEY_KEYDATA; + +#define KEYTYPE(key) ((key)->pubkey ? EVP_PKEY_get_id((key)->pubkey) : 0) +#define KEYSIZE(key) ((key)->pubkey ? EVP_PKEY_get_size((key)->pubkey) : 0) + +/* keymgmt provider */ + +/* keymgmt callbacks we implement */ +static OSSL_FUNC_keymgmt_new_fn keymgmt_new; +static OSSL_FUNC_keymgmt_free_fn keymgmt_free; +static OSSL_FUNC_keymgmt_load_fn keymgmt_load; +static OSSL_FUNC_keymgmt_has_fn keymgmt_has; +static OSSL_FUNC_keymgmt_match_fn keymgmt_match; +static OSSL_FUNC_keymgmt_import_fn rsa_keymgmt_import; +static OSSL_FUNC_keymgmt_import_fn ec_keymgmt_import; +static OSSL_FUNC_keymgmt_import_types_fn keymgmt_types; +static OSSL_FUNC_keymgmt_get_params_fn keymgmt_get_params; +static OSSL_FUNC_keymgmt_gettable_params_fn keymgmt_gettable; +static OSSL_FUNC_keymgmt_query_operation_name_fn rsa_keymgmt_name; +static OSSL_FUNC_keymgmt_query_operation_name_fn ec_keymgmt_name; + +static XKEY_KEYDATA * +keydata_new() +{ + dmsg(D_LOW, "In keydata_new"); + + XKEY_KEYDATA *key = calloc(sizeof(*key), 1); + if (!key) + { + msg(M_NONFATAL, "xkey_keydata_new: out of memory"); + } + + return key; +} + +static void +keydata_free(XKEY_KEYDATA *key) +{ + dmsg(D_LOW, "In keydata_free"); + + if (!key || --key->refcount <= 0) /* free when refcount goes to zero */ + { + return; + } + if (key->pubkey) + { + EVP_PKEY_free(key->pubkey); + } + free(key); +} + +static void * +keymgmt_new(void *provctx) +{ + dmsg(D_LOW, "In keymgmt_new"); + + XKEY_KEYDATA *key = keydata_new(); + return key; +} + +static void * +keymgmt_load(const void *reference, size_t reference_sz) +{ + dmsg(D_LOW, "In keymgmt_load"); + + return NULL; +} + +/** + * Key import function + * When key operations like sign/verify are done in our context + * the key gets imported into us. + * + * For native keys we get called with standard OpenSSL params + * appropriate for the key. We just use it to create a native + * EVP_PKEY from params and assign to keydata->handle. + * + * Import of external keys -- to be implemented + */ +static int +keymgmt_import(void *keydata, int selection, const OSSL_PARAM params[], const char *name) +{ + dmsg(D_LOW, "In keymgmt_import"); + + XKEY_KEYDATA *key = keydata; + + /* Our private key is immutable -- we import only if keydata is empty */ + + if (key->handle || key->pubkey + || !(selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY)) + { + msg(M_WARN, "Error: keymgmt_import: keydata not empty or selection not allowed"); + return 0; + } + + /* create a native public key and assign it to key->pubkey */ + EVP_PKEY *pkey = NULL; + + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, name, NULL); + if (!ctx + || (EVP_PKEY_fromdata_init(ctx) != 1) + || (EVP_PKEY_fromdata(ctx, &pkey, selection, (OSSL_PARAM*) params) !=1)) + { + msg(M_WARN, "Error: keymgmt_import failed for key type <%s>", name); + if (pkey) + { + EVP_PKEY_free(pkey); + } + return 0; + } + + key->pubkey = pkey; + key->origin = OPENSSL_NATIVE; + if (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) + { + /* just use the same key as handle -- do not up-ref */ + key->handle = pkey; + } + return 1; +} + +static int +rsa_keymgmt_import(void *keydata, int selection, const OSSL_PARAM params[]) +{ + dmsg(D_LOW, "In rsa_keymgmt_import"); + return keymgmt_import(keydata, selection, params, "RSA"); +} + +static int +ec_keymgmt_import(void *keydata, int selection, const OSSL_PARAM params[]) +{ + dmsg(D_LOW, "In ec_keymgmt_import"); + return keymgmt_import(keydata, selection, params, "EC"); +} + +/* This function has to exist for key import to work + * though we do not support import of individual params + * like n or e. We simply return an empty list here for + * both rsa and ec, which works. + */ +static const OSSL_PARAM * +keymgmt_import_types(int selection) +{ + dmsg(D_LOW, "In keymgmt import types"); + + static const OSSL_PARAM key_types[] = { + OSSL_PARAM_END + }; + + if (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) + { + return key_types; + } + return NULL; +} + +/* We do not support any key export */ + +static void +keymgmt_free(void *keydata) +{ + dmsg(D_LOW, "In keymgmt_free"); + keydata_free(keydata); +} + +static int +keymgmt_has(const void *keydata, int selection) +{ + dmsg(D_LOW, "In keymgmt_has with selection = %d", selection); + + const XKEY_KEYDATA *key = keydata; + int ok = (key != NULL); + + if (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) + { + ok = ok && key->pubkey; + } + if (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) + { + ok = ok && key->handle; + } + + return ok; +} + +static int +keymgmt_match(const void *keydata1, const void *keydata2, int selection) +{ + const XKEY_KEYDATA *key1 = keydata1; + const XKEY_KEYDATA *key2 = keydata2; + + dmsg(D_LOW, "In keymgmt_match"); + int ret = 1; + + if (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY + && key1->pubkey && key2->pubkey) + { + ret = ret && EVP_PKEY_eq(key1->pubkey, key2->pubkey); + } + + if (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) + { + ret = ret && (key1->origin == key2->origin); /* origins must match */ + if (key1->origin == OPENSSL_NATIVE) + { + ret = ret && EVP_PKEY_eq(key1->pubkey, key2->pubkey); + } + /* private key is opaque. We can only check identity of the handle */ + else + { + ret = ret && (key1->handle == key2->handle); + } + } + + return ret; +} + +/* A minimal set of key params that we can return */ +static const OSSL_PARAM * +keymgmt_gettable_params(void *provctx) +{ + dmsg(D_LOW, "In keymgmt_gettable"); + static OSSL_PARAM gettable[] = { + OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL), + OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL), + OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL), + OSSL_PARAM_END + }; + return gettable; +} + +static int +keymgmt_get_params(void *keydata, OSSL_PARAM *params) +{ + dmsg(D_LOW, "In keymgmt_get_params"); + + XKEY_KEYDATA *key = keydata; + if (!key || !key->pubkey) + { + return 0; + } + + return EVP_PKEY_get_params(key->pubkey, params); +} + +/** + * If the key is an encapsulated native key, we just call + * EVP_PKEY_set_params in the default context. Only those params + * supported by the default provider would work in that case. + */ +static int +keymgmt_set_params(void *keydata, const OSSL_PARAM *params) +{ + XKEY_KEYDATA *key = keydata; + ASSERT(key); + + if (key->origin != OPENSSL_NATIVE) + { + return 0; /* to be implemented */ + } + else if (key->handle == NULL) /* once handle is set our key is immutable */ + { + /* pubkey is always native -- just delegate */ + return EVP_PKEY_set_params(key->pubkey, (OSSL_PARAM *)params); + } + else + { + msg(M_WARN, "xkey keymgmt_set_params: key is immutable"); + } + return 1; +} + +static const char * +rsa_keymgmt_name(int id) +{ + dmsg(D_LOW, "In rsa_keymgmt_name"); + return "RSA"; +} + +static const char * +ec_keymgmt_name(int id) +{ + dmsg(D_LOW, "In ec_keymgmt_name"); + return "EC"; +} + +static const OSSL_DISPATCH rsa_keymgmt_functions[] = { + {OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))keymgmt_new}, + {OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))keymgmt_free}, + {OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))keymgmt_load}, + {OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))keymgmt_has}, + {OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))keymgmt_match}, + {OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))rsa_keymgmt_import}, + {OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))keymgmt_import_types}, + {OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void)) keymgmt_gettable_params}, + {OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void)) keymgmt_get_params}, + {OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME, (void (*)(void))rsa_keymgmt_name}, + {0, NULL } +}; + +static const OSSL_DISPATCH ec_keymgmt_functions[] = { + {OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))keymgmt_new}, + {OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))keymgmt_free}, + {OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))keymgmt_load}, + {OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))keymgmt_has}, + {OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))keymgmt_match}, + {OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ec_keymgmt_import}, + {OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))keymgmt_import_types}, + {OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void)) keymgmt_gettable_params}, + {OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void)) keymgmt_get_params}, + {OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME, (void (*)(void))ec_keymgmt_name}, + {0, NULL } +}; + +const OSSL_ALGORITHM keymgmts[] = { + {"RSA:rsaEncryption", props, rsa_keymgmt_functions}, + {"RSA-PSS:RSASSA-PSS", props, rsa_keymgmt_functions}, + {"EC:id-ecPublicKey", props, ec_keymgmt_functions}, + {NULL, NULL, NULL} +}; + /* main provider interface */ /* provider callbacks we implement */ @@ -74,6 +424,9 @@ query_operation(void *provctx, int op, int *no_store) return NULL; case OSSL_OP_KEYMGMT: + return keymgmts; + + case OSSL_OP_STORE: return NULL; default: