summaryrefslogtreecommitdiffstats
path: root/providers
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2020-07-03 16:18:03 +0100
committerMatt Caswell <matt@openssl.org>2020-08-10 14:51:57 +0100
commitac2d58c72b4dc4a8c74eef893000306bf78a30fd (patch)
tree105bc32568afcb7dd145a2560bc865ff8de3a20f /providers
parent23f04372f45f8c9e3865c3bcfee3f77a9cc10673 (diff)
Implement a EVP_PKEY KDF to KDF provider bridge
Some KDF implementations were available before the current EVP_KDF API. They were used via EVP_PKEY_derive. There exists a bridge between the old API and the EVP_KDF API however this bridge itself uses a legacy EVP_PKEY_METHOD. This commit implements a provider side bridge without having to use any legacy code. Reviewed-by: Paul Dale <paul.dale@oracle.com> (Merged from https://github.com/openssl/openssl/pull/12573)
Diffstat (limited to 'providers')
-rw-r--r--providers/defltprov.c2
-rw-r--r--providers/implementations/exchange/build.info3
-rw-r--r--providers/implementations/exchange/kdf_exch.c148
-rw-r--r--providers/implementations/include/prov/implementations.h2
-rw-r--r--providers/implementations/include/prov/kdfexchange.h24
-rw-r--r--providers/implementations/kdfs/tls1_prf.c3
-rw-r--r--providers/implementations/keymgmt/build.info3
-rw-r--r--providers/implementations/keymgmt/kdf_legacy_kmgmt.c90
8 files changed, 272 insertions, 3 deletions
diff --git a/providers/defltprov.c b/providers/defltprov.c
index 4ab39e6531..5b6d6a677e 100644
--- a/providers/defltprov.c
+++ b/providers/defltprov.c
@@ -339,6 +339,7 @@ static const OSSL_ALGORITHM deflt_keyexch[] = {
{ "X25519", "provider=default", x25519_keyexch_functions },
{ "X448", "provider=default", x448_keyexch_functions },
#endif
+ { "TLS1-PRF", "provider=default", kdf_keyexch_functions },
{ NULL, NULL, NULL }
};
@@ -384,6 +385,7 @@ static const OSSL_ALGORITHM deflt_keymgmt[] = {
{ "ED25519", "provider=default", ed25519_keymgmt_functions },
{ "ED448", "provider=default", ed448_keymgmt_functions },
#endif
+ { "TLS1-PRF", "provider=default", kdf_keymgmt_functions },
{ NULL, NULL, NULL }
};
diff --git a/providers/implementations/exchange/build.info b/providers/implementations/exchange/build.info
index 3127f9a3e7..92932b9d28 100644
--- a/providers/implementations/exchange/build.info
+++ b/providers/implementations/exchange/build.info
@@ -4,6 +4,7 @@
$DH_GOAL=../../libimplementations.a
$ECX_GOAL=../../libimplementations.a
$ECDH_GOAL=../../libimplementations.a
+$KDF_GOAL=../../libimplementations.a
IF[{- !$disabled{dh} -}]
SOURCE[$DH_GOAL]=dh_exch.c
@@ -25,3 +26,5 @@ IF[{- !$disabled{ec} -}]
SOURCE[../../libfips.a]=ecdh_exch.c
SOURCE[../../libnonfips.a]=ecdh_exch.c
ENDIF
+
+SOURCE[$KDF_GOAL]=kdf_exch.c
diff --git a/providers/implementations/exchange/kdf_exch.c b/providers/implementations/exchange/kdf_exch.c
new file mode 100644
index 0000000000..41278e6389
--- /dev/null
+++ b/providers/implementations/exchange/kdf_exch.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/kdf.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include "prov/implementations.h"
+#include "prov/provider_ctx.h"
+#include "prov/kdfexchange.h"
+
+static OSSL_FUNC_keyexch_newctx_fn kdf_newctx;
+static OSSL_FUNC_keyexch_init_fn kdf_init;
+static OSSL_FUNC_keyexch_derive_fn kdf_derive;
+static OSSL_FUNC_keyexch_freectx_fn kdf_freectx;
+static OSSL_FUNC_keyexch_dupctx_fn kdf_dupctx;
+static OSSL_FUNC_keyexch_set_ctx_params_fn kdf_set_ctx_params;
+static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_settable_ctx_params;
+
+typedef struct {
+ void *provctx;
+ EVP_KDF_CTX *kdfctx;
+ KDF_DATA *kdfdata;
+} PROV_KDF_CTX;
+
+static void *kdf_newctx(void *provctx)
+{
+ PROV_KDF_CTX *kdfctx = OPENSSL_zalloc(sizeof(PROV_KDF_CTX));
+ EVP_KDF *kdf = NULL;
+
+ if (kdfctx == NULL)
+ return NULL;
+
+ kdfctx->provctx = provctx;
+
+ kdf = EVP_KDF_fetch(PROV_LIBRARY_CONTEXT_OF(provctx), "TLS1-PRF", NULL);
+ if (kdf == NULL)
+ goto err;
+ kdfctx->kdfctx = EVP_KDF_new_ctx(kdf);
+ EVP_KDF_free(kdf);
+
+ if (kdfctx->kdfctx == NULL)
+ goto err;
+
+ return kdfctx;
+ err:
+ OPENSSL_free(kdfctx);
+ return NULL;
+}
+
+static int kdf_init(void *vpkdfctx, void *vkdf)
+{
+ PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
+
+ if (pkdfctx == NULL || vkdf == NULL || !kdf_data_up_ref(vkdf))
+ return 0;
+ pkdfctx->kdfdata = vkdf;
+
+ return 1;
+}
+
+static int kdf_derive(void *vpkdfctx, unsigned char *secret, size_t *secretlen,
+ size_t outlen)
+{
+ PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
+
+ return EVP_KDF_derive(pkdfctx->kdfctx, secret, *secretlen);
+}
+
+static void kdf_freectx(void *vpkdfctx)
+{
+ PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
+
+ EVP_KDF_CTX_free(pkdfctx->kdfctx);
+ kdf_data_free(pkdfctx->kdfdata);
+
+ OPENSSL_free(pkdfctx);
+}
+
+static void *kdf_dupctx(void *vpkdfctx)
+{
+ PROV_KDF_CTX *srcctx = (PROV_KDF_CTX *)vpkdfctx;
+ PROV_KDF_CTX *dstctx;
+
+ dstctx = OPENSSL_zalloc(sizeof(*srcctx));
+ if (dstctx == NULL)
+ return NULL;
+
+ *dstctx = *srcctx;
+
+ dstctx->kdfctx = EVP_KDF_dup_ctx(srcctx->kdfctx);
+ if (dstctx->kdfctx == NULL) {
+ OPENSSL_free(dstctx);
+ return NULL;
+ }
+ if (!kdf_data_up_ref(dstctx->kdfdata)) {
+ EVP_KDF_CTX_free(dstctx->kdfctx);
+ OPENSSL_free(dstctx);
+ return NULL;
+ }
+
+ return dstctx;
+}
+
+static int kdf_set_ctx_params(void *vpkdfctx, const OSSL_PARAM params[])
+{
+ PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
+
+ return EVP_KDF_set_ctx_params(pkdfctx->kdfctx, params);
+}
+
+
+static const OSSL_PARAM *kdf_settable_ctx_params(void)
+{
+ /*
+ * TODO(3.0): FIXME FIXME!! These settable_ctx_params functions should
+ * should have a provctx argument so we can get hold of the libctx.
+ */
+ EVP_KDF *kdf = EVP_KDF_fetch(NULL, "TLS1-PRF", NULL);
+ const OSSL_PARAM *params;
+
+ if (kdf == NULL)
+ return NULL;
+
+ params = EVP_KDF_settable_ctx_params(kdf);
+ EVP_KDF_free(kdf);
+
+ return params;
+}
+
+const OSSL_DISPATCH kdf_keyexch_functions[] = {
+ { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))kdf_newctx },
+ { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))kdf_init },
+ { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))kdf_derive },
+ { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))kdf_freectx },
+ { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))kdf_dupctx },
+ { OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))kdf_set_ctx_params },
+ { OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS,
+ (void (*)(void))kdf_settable_ctx_params },
+ { 0, NULL }
+};
diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h
index 7e470044cd..e862e3f8e8 100644
--- a/providers/implementations/include/prov/implementations.h
+++ b/providers/implementations/include/prov/implementations.h
@@ -275,12 +275,14 @@ extern const OSSL_DISPATCH x448_keymgmt_functions[];
extern const OSSL_DISPATCH ed25519_keymgmt_functions[];
extern const OSSL_DISPATCH ed448_keymgmt_functions[];
extern const OSSL_DISPATCH ec_keymgmt_functions[];
+extern const OSSL_DISPATCH kdf_keymgmt_functions[];
/* Key Exchange */
extern const OSSL_DISPATCH dh_keyexch_functions[];
extern const OSSL_DISPATCH x25519_keyexch_functions[];
extern const OSSL_DISPATCH x448_keyexch_functions[];
extern const OSSL_DISPATCH ecdh_keyexch_functions[];
+extern const OSSL_DISPATCH kdf_keyexch_functions[];
/* Signature */
extern const OSSL_DISPATCH dsa_signature_functions[];
diff --git a/providers/implementations/include/prov/kdfexchange.h b/providers/implementations/include/prov/kdfexchange.h
new file mode 100644
index 0000000000..5c817bb929
--- /dev/null
+++ b/providers/implementations/include/prov/kdfexchange.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdlib.h>
+#include <openssl/crypto.h>
+#include "internal/refcount.h"
+
+struct kdf_data_st {
+ OPENSSL_CTX *libctx;
+ CRYPTO_REF_COUNT refcnt;
+ CRYPTO_RWLOCK *lock;
+};
+
+typedef struct kdf_data_st KDF_DATA;
+
+KDF_DATA *kdf_data_new(void *provctx);
+void kdf_data_free(KDF_DATA *kdfdata);
+int kdf_data_up_ref(KDF_DATA *kdfdata);
diff --git a/providers/implementations/kdfs/tls1_prf.c b/providers/implementations/kdfs/tls1_prf.c
index bc7d7fd721..46a1253ee8 100644
--- a/providers/implementations/kdfs/tls1_prf.c
+++ b/providers/implementations/kdfs/tls1_prf.c
@@ -183,9 +183,6 @@ static int kdf_tls1_prf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
}
/* The seed fields concatenate, so process them all */
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SEED)) != NULL) {
- OPENSSL_cleanse(ctx->seed, ctx->seedlen);
- ctx->seedlen = 0;
-
for (; p != NULL; p = OSSL_PARAM_locate_const(p + 1,
OSSL_KDF_PARAM_SEED)) {
const void *q = ctx->seed + ctx->seedlen;
diff --git a/providers/implementations/keymgmt/build.info b/providers/implementations/keymgmt/build.info
index 73597c7cea..53c84ac3d4 100644
--- a/providers/implementations/keymgmt/build.info
+++ b/providers/implementations/keymgmt/build.info
@@ -5,6 +5,7 @@ $DH_GOAL=../../libimplementations.a
$DSA_GOAL=../../libimplementations.a
$EC_GOAL=../../libimplementations.a
$ECX_GOAL=../../libimplementations.a
+$KDF_GOAL=../../libimplementations.a
IF[{- !$disabled{dh} -}]
SOURCE[$DH_GOAL]=dh_kmgmt.c
@@ -33,3 +34,5 @@ ENDIF
SOURCE[../../libfips.a]=rsa_kmgmt.c
SOURCE[../../libnonfips.a]=rsa_kmgmt.c
+
+SOURCE[$KDF_GOAL]=kdf_legacy_kmgmt.c
diff --git a/providers/implementations/keymgmt/kdf_legacy_kmgmt.c b/providers/implementations/keymgmt/kdf_legacy_kmgmt.c
new file mode 100644
index 0000000000..33cf87e350
--- /dev/null
+++ b/providers/implementations/keymgmt/kdf_legacy_kmgmt.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This implemments a dummy key manager for legacy KDFs that still support the
+ * old way of performing a KDF via EVP_PKEY_derive(). New KDFs should not be
+ * implemented this way. In reality there is no key data for such KDFs, so this
+ * key manager does very little.
+ */
+
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/err.h>
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+#include "prov/provider_ctx.h"
+#include "prov/kdfexchange.h"
+
+static OSSL_FUNC_keymgmt_new_fn kdf_newdata;
+static OSSL_FUNC_keymgmt_free_fn kdf_freedata;
+static OSSL_FUNC_keymgmt_has_fn kdf_has;
+
+KDF_DATA *kdf_data_new(void *provctx)
+{
+ KDF_DATA *kdfdata = OPENSSL_zalloc(sizeof(*kdfdata));
+
+ if (kdfdata == NULL)
+ return NULL;
+
+ kdfdata->lock = CRYPTO_THREAD_lock_new();
+ if (kdfdata->lock == NULL) {
+ OPENSSL_free(kdfdata);
+ return NULL;
+ }
+ kdfdata->libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
+ kdfdata->refcnt = 1;
+
+ return kdfdata;
+}
+
+void kdf_data_free(KDF_DATA *kdfdata)
+{
+ int ref = 0;
+
+ if (kdfdata == NULL)
+ return;
+
+ CRYPTO_DOWN_REF(&kdfdata->refcnt, &ref, kdfdata->lock);
+ if (ref > 0)
+ return;
+
+ CRYPTO_THREAD_lock_free(kdfdata->lock);
+ OPENSSL_free(kdfdata);
+}
+
+int kdf_data_up_ref(KDF_DATA *kdfdata)
+{
+ int ref = 0;
+
+ CRYPTO_UP_REF(&kdfdata->refcnt, &ref, kdfdata->lock);
+ return 1;
+}
+
+static void *kdf_newdata(void *provctx)
+{
+ return kdf_data_new(provctx);
+}
+
+static void kdf_freedata(void *kdfdata)
+{
+ kdf_data_free(kdfdata);
+}
+
+static int kdf_has(void *keydata, int selection)
+{
+ return 0;
+}
+
+const OSSL_DISPATCH kdf_keymgmt_functions[] = {
+ { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))kdf_newdata },
+ { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))kdf_freedata },
+ { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))kdf_has },
+ { 0, NULL }
+};