aboutsummaryrefslogtreecommitdiff
path: root/providers
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2019-06-27 12:36:30 +0100
committerMatt Caswell <matt@openssl.org>2019-07-16 10:16:32 +0100
commit89e291742f8db5920cc7938407d07c8f77c18293 (patch)
tree6e0498333ab0444b9ff7027d333fcc6f7e95fe95 /providers
parentff64702b3d83d4c77756e0fd7b624e2165dbbdf0 (diff)
downloadopenssl-89e291742f8db5920cc7938407d07c8f77c18293.zip
openssl-89e291742f8db5920cc7938407d07c8f77c18293.tar.gz
openssl-89e291742f8db5920cc7938407d07c8f77c18293.tar.bz2
Implement PKCS#3 DH Key Exchange in the default provider
We add the capability for the default provider to perform PKCS#3 Diffie-Hellman key exchange. At this point the implementation is not used because libcrypto still uses legacy handling for Diffie-Hellman. Note X9.42 DH is not touched by this commit. Reviewed-by: Paul Dale <paul.dale@oracle.com> (Merged from https://github.com/openssl/openssl/pull/9266)
Diffstat (limited to 'providers')
-rw-r--r--providers/common/build.info2
-rw-r--r--providers/common/exchange/build.info5
-rw-r--r--providers/common/exchange/dh.c173
-rw-r--r--providers/common/include/internal/provider_algs.h3
-rw-r--r--providers/default/defltprov.c7
5 files changed, 189 insertions, 1 deletions
diff --git a/providers/common/build.info b/providers/common/build.info
index 500ef64..c77606a 100644
--- a/providers/common/build.info
+++ b/providers/common/build.info
@@ -1,4 +1,4 @@
-SUBDIRS=digests ciphers
+SUBDIRS=digests ciphers exchange
SOURCE[../../libcrypto]=\
provider_err.c provlib.c
diff --git a/providers/common/exchange/build.info b/providers/common/exchange/build.info
new file mode 100644
index 0000000..1039075
--- /dev/null
+++ b/providers/common/exchange/build.info
@@ -0,0 +1,5 @@
+LIBS=../../../libcrypto
+SOURCE[../../../libcrypto]=\
+ dh.c
+
+
diff --git a/providers/common/exchange/dh.c b/providers/common/exchange/dh.c
new file mode 100644
index 0000000..f3d4925
--- /dev/null
+++ b/providers/common/exchange/dh.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2019 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/core_numbers.h>
+#include <openssl/core_names.h>
+#include <openssl/dh.h>
+#include <openssl/params.h>
+#include "internal/provider_algs.h"
+
+static OSSL_OP_keyexch_newctx_fn dh_newctx;
+static OSSL_OP_keyexch_init_fn dh_init;
+static OSSL_OP_keyexch_set_peer_fn dh_set_peer;
+static OSSL_OP_keyexch_derive_fn dh_derive;
+static OSSL_OP_keyexch_freectx_fn dh_freectx;
+static OSSL_OP_keyexch_dupctx_fn dh_dupctx;
+
+
+typedef struct {
+ DH *dh;
+ DH *dhpeer;
+} PROV_DH_CTX;
+
+static void *dh_newctx(void *provctx)
+{
+ return OPENSSL_zalloc(sizeof(PROV_DH_CTX));
+}
+
+static DH *param_to_dh(OSSL_PARAM params[], int priv)
+{
+ DH *dh = DH_new();
+ OSSL_PARAM *paramptr;
+ BIGNUM *p = NULL, *g = NULL, *pub_key = NULL, *priv_key = NULL;
+
+ if (dh == NULL)
+ return NULL;
+
+ paramptr = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DH_P);
+ if (paramptr == NULL
+ || !OSSL_PARAM_get_BN(paramptr, &p))
+ goto err;
+
+ paramptr = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DH_G);
+ if (paramptr == NULL || !OSSL_PARAM_get_BN(paramptr, &g))
+ goto err;
+
+ if (!DH_set0_pqg(dh, p, NULL, g))
+ goto err;
+ p = g = NULL;
+
+ paramptr = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DH_PUB_KEY);
+ if (paramptr == NULL || !OSSL_PARAM_get_BN(paramptr, &pub_key))
+ goto err;
+
+ /* Private key is optional */
+ if (priv) {
+ paramptr = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DH_PRIV_KEY);
+ if (paramptr == NULL
+ || (priv_key = BN_secure_new()) == NULL
+ || !OSSL_PARAM_get_BN(paramptr, &priv_key))
+ goto err;
+ }
+
+ if (!DH_set0_key(dh, pub_key, priv_key))
+ goto err;
+
+ return dh;
+
+ err:
+ BN_free(p);
+ BN_free(g);
+ BN_free(pub_key);
+ BN_free(priv_key);
+ DH_free(dh);
+ return NULL;
+}
+
+static int dh_init(void *vpdhctx, OSSL_PARAM params[])
+{
+ PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
+
+ DH_free(pdhctx->dh);
+ pdhctx->dh = param_to_dh(params, 1);
+
+ return pdhctx->dh != NULL;
+}
+
+static int dh_set_peer(void *vpdhctx, OSSL_PARAM params[])
+{
+ PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
+
+ DH_free(pdhctx->dhpeer);
+ pdhctx->dhpeer = param_to_dh(params, 0);
+
+ return pdhctx->dhpeer != NULL;
+}
+
+static int dh_derive(void *vpdhctx, unsigned char *key, size_t *keylen,
+ size_t outlen)
+{
+ PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
+ int ret;
+ size_t dhsize;
+ const BIGNUM *pub_key = NULL;
+
+ /* TODO(3.0): Add errors to stack */
+ if (pdhctx->dh == NULL || pdhctx->dhpeer == NULL)
+ return 0;
+
+ dhsize = (size_t)DH_size(pdhctx->dh);
+ if (key == NULL) {
+ *keylen = dhsize;
+ return 1;
+ }
+ if (outlen < dhsize)
+ return 0;
+
+ DH_get0_key(pdhctx->dhpeer, &pub_key, NULL);
+ ret = DH_compute_key(key, pub_key, pdhctx->dh);
+ if (ret <= 0)
+ return 0;
+
+ *keylen = ret;
+ return 1;
+}
+
+static void dh_freectx(void *vpdhctx)
+{
+ PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
+
+ DH_free(pdhctx->dh);
+ DH_free(pdhctx->dhpeer);
+
+ OPENSSL_free(pdhctx);
+}
+
+static void *dh_dupctx(void *vpdhctx)
+{
+ PROV_DH_CTX *srcctx = (PROV_DH_CTX *)vpdhctx;
+ PROV_DH_CTX *dstctx;
+
+ dstctx = OPENSSL_zalloc(sizeof(*srcctx));
+
+ *dstctx = *srcctx;
+ if (dstctx->dh != NULL && !DH_up_ref(dstctx->dh)) {
+ OPENSSL_free(dstctx);
+ return NULL;
+ }
+
+ if (dstctx->dhpeer != NULL && !DH_up_ref(dstctx->dhpeer)) {
+ DH_free(dstctx->dh);
+ OPENSSL_free(dstctx);
+ return NULL;
+ }
+
+ return dstctx;
+}
+
+const OSSL_DISPATCH dh_functions[] = {
+ { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))dh_newctx },
+ { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))dh_init },
+ { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))dh_derive },
+ { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))dh_set_peer },
+ { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))dh_freectx },
+ { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))dh_dupctx },
+ { 0, NULL }
+};
diff --git a/providers/common/include/internal/provider_algs.h b/providers/common/include/internal/provider_algs.h
index 0e26da0..dbc79a5 100644
--- a/providers/common/include/internal/provider_algs.h
+++ b/providers/common/include/internal/provider_algs.h
@@ -57,3 +57,6 @@ extern const OSSL_DISPATCH aes128cfb8_functions[];
extern const OSSL_DISPATCH aes256ctr_functions[];
extern const OSSL_DISPATCH aes192ctr_functions[];
extern const OSSL_DISPATCH aes128ctr_functions[];
+
+/* Key Exchange */
+extern const OSSL_DISPATCH dh_functions[];
diff --git a/providers/default/defltprov.c b/providers/default/defltprov.c
index 76ef2bc..6ac2bdb 100644
--- a/providers/default/defltprov.c
+++ b/providers/default/defltprov.c
@@ -114,6 +114,11 @@ static const OSSL_ALGORITHM deflt_ciphers[] = {
{ NULL, NULL, NULL }
};
+static const OSSL_ALGORITHM deflt_keyexch[] = {
+ { "dhKeyAgreement", "default=yes", dh_functions },
+ { NULL, NULL, NULL }
+};
+
static const OSSL_ALGORITHM *deflt_query(OSSL_PROVIDER *prov,
int operation_id,
int *no_cache)
@@ -124,6 +129,8 @@ static const OSSL_ALGORITHM *deflt_query(OSSL_PROVIDER *prov,
return deflt_digests;
case OSSL_OP_CIPHER:
return deflt_ciphers;
+ case OSSL_OP_KEYEXCH:
+ return deflt_keyexch;
}
return NULL;
}