aec30dcfcb
Resolves: #1955873
269 lines
8.3 KiB
Diff
269 lines
8.3 KiB
Diff
From ea62d96f5b1e47818ab9f33ad143c4ffb460b3af Mon Sep 17 00:00:00 2001
|
|
From: Robbie Harwood <rharwood@redhat.com>
|
|
Date: Sat, 15 May 2021 21:18:06 -0400
|
|
Subject: [PATCH] Handle OpenSSL 3's providers
|
|
|
|
OpenSSL 3 compartmentalizes what algorithms it uses, which for us means
|
|
another hoop to jump through to use dubious cryptography. Right now, we
|
|
need to load "legacy" in order to access MD4 and RC4.
|
|
|
|
(cherry picked from commit faac961a0d02c7818aad87c765eb344b87e668fa)
|
|
[rharwood@redhat.com: des3 removal, rc4 FIPSification]
|
|
---
|
|
src/configure.ac | 1 +
|
|
src/lib/crypto/openssl/enc_provider/aes.c | 16 +++++++
|
|
.../crypto/openssl/enc_provider/camellia.c | 16 +++++++
|
|
src/lib/crypto/openssl/enc_provider/rc4.c | 4 ++
|
|
.../crypto/openssl/hash_provider/hash_evp.c | 5 ++
|
|
src/lib/crypto/openssl/init.c | 47 +++++++++++++++++++
|
|
.../preauth/pkinit/pkinit_crypto_openssl.c | 25 ++++++++--
|
|
7 files changed, 111 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/src/configure.ac b/src/configure.ac
|
|
index 9c2e816fe..20066918b 100644
|
|
--- a/src/configure.ac
|
|
+++ b/src/configure.ac
|
|
@@ -284,6 +284,7 @@ AC_SUBST(CRYPTO_IMPL_LIBS)
|
|
|
|
if test "$CRYPTO_IMPL" = openssl; then
|
|
AC_CHECK_FUNCS(EVP_KDF_fetch)
|
|
+ AC_CHECK_FUNCS(OSSL_PROVIDER_load)
|
|
fi
|
|
|
|
AC_ARG_WITH([prng-alg],
|
|
diff --git a/src/lib/crypto/openssl/enc_provider/aes.c b/src/lib/crypto/openssl/enc_provider/aes.c
|
|
index 6b4622fe9..31c90a69d 100644
|
|
--- a/src/lib/crypto/openssl/enc_provider/aes.c
|
|
+++ b/src/lib/crypto/openssl/enc_provider/aes.c
|
|
@@ -68,6 +68,10 @@ cbc_enc(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
|
|
EVP_CIPHER_CTX *ctx;
|
|
struct iov_cursor cursor;
|
|
|
|
+ ret = krb5int_crypto_init();
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
ctx = EVP_CIPHER_CTX_new();
|
|
if (ctx == NULL)
|
|
return ENOMEM;
|
|
@@ -102,6 +106,10 @@ cbc_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
|
|
EVP_CIPHER_CTX *ctx;
|
|
struct iov_cursor cursor;
|
|
|
|
+ ret = krb5int_crypto_init();
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
ctx = EVP_CIPHER_CTX_new();
|
|
if (ctx == NULL)
|
|
return ENOMEM;
|
|
@@ -137,6 +145,10 @@ cts_encr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
|
|
struct iov_cursor cursor;
|
|
AES_KEY enck;
|
|
|
|
+ ret = krb5int_crypto_init();
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
memset(iv_cts,0,sizeof(iv_cts));
|
|
if (ivec && ivec->data){
|
|
if (ivec->length != sizeof(iv_cts))
|
|
@@ -190,6 +202,10 @@ cts_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
|
|
struct iov_cursor cursor;
|
|
AES_KEY deck;
|
|
|
|
+ ret = krb5int_crypto_init();
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
memset(iv_cts,0,sizeof(iv_cts));
|
|
if (ivec && ivec->data){
|
|
if (ivec->length != sizeof(iv_cts))
|
|
diff --git a/src/lib/crypto/openssl/enc_provider/camellia.c b/src/lib/crypto/openssl/enc_provider/camellia.c
|
|
index f79679a0b..7cc7fc6fb 100644
|
|
--- a/src/lib/crypto/openssl/enc_provider/camellia.c
|
|
+++ b/src/lib/crypto/openssl/enc_provider/camellia.c
|
|
@@ -92,6 +92,10 @@ cbc_enc(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
|
|
EVP_CIPHER_CTX *ctx;
|
|
struct iov_cursor cursor;
|
|
|
|
+ ret = krb5int_crypto_init();
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
ctx = EVP_CIPHER_CTX_new();
|
|
if (ctx == NULL)
|
|
return ENOMEM;
|
|
@@ -126,6 +130,10 @@ cbc_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
|
|
EVP_CIPHER_CTX *ctx;
|
|
struct iov_cursor cursor;
|
|
|
|
+ ret = krb5int_crypto_init();
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
ctx = EVP_CIPHER_CTX_new();
|
|
if (ctx == NULL)
|
|
return ENOMEM;
|
|
@@ -161,6 +169,10 @@ cts_encr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
|
|
struct iov_cursor cursor;
|
|
CAMELLIA_KEY enck;
|
|
|
|
+ ret = krb5int_crypto_init();
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
memset(iv_cts,0,sizeof(iv_cts));
|
|
if (ivec && ivec->data){
|
|
if (ivec->length != sizeof(iv_cts))
|
|
@@ -214,6 +226,10 @@ cts_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data,
|
|
struct iov_cursor cursor;
|
|
CAMELLIA_KEY deck;
|
|
|
|
+ ret = krb5int_crypto_init();
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
memset(iv_cts,0,sizeof(iv_cts));
|
|
if (ivec && ivec->data){
|
|
if (ivec->length != sizeof(iv_cts))
|
|
diff --git a/src/lib/crypto/openssl/enc_provider/rc4.c b/src/lib/crypto/openssl/enc_provider/rc4.c
|
|
index 9bf407899..4e7af3555 100644
|
|
--- a/src/lib/crypto/openssl/enc_provider/rc4.c
|
|
+++ b/src/lib/crypto/openssl/enc_provider/rc4.c
|
|
@@ -69,6 +69,10 @@ k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
|
|
if (FIPS_mode())
|
|
return KRB5_CRYPTO_INTERNAL;
|
|
|
|
+ ret = krb5int_crypto_init();
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
arcstate = (state != NULL) ? (void *)state->data : NULL;
|
|
if (arcstate != NULL) {
|
|
ctx = arcstate->ctx;
|
|
diff --git a/src/lib/crypto/openssl/hash_provider/hash_evp.c b/src/lib/crypto/openssl/hash_provider/hash_evp.c
|
|
index 2eb5139c0..09d7b3896 100644
|
|
--- a/src/lib/crypto/openssl/hash_provider/hash_evp.c
|
|
+++ b/src/lib/crypto/openssl/hash_provider/hash_evp.c
|
|
@@ -41,6 +41,11 @@ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
|
|
const krb5_data *d;
|
|
size_t i;
|
|
int ok;
|
|
+ krb5_error_code ret;
|
|
+
|
|
+ ret = krb5int_crypto_init();
|
|
+ if (ret)
|
|
+ return ret;
|
|
|
|
if (output->length != (unsigned int)EVP_MD_size(type))
|
|
return KRB5_CRYPTO_INTERNAL;
|
|
diff --git a/src/lib/crypto/openssl/init.c b/src/lib/crypto/openssl/init.c
|
|
index 1139bce53..8342dece1 100644
|
|
--- a/src/lib/crypto/openssl/init.c
|
|
+++ b/src/lib/crypto/openssl/init.c
|
|
@@ -26,6 +26,51 @@
|
|
|
|
#include "crypto_int.h"
|
|
|
|
+#ifdef HAVE_OSSL_PROVIDER_LOAD
|
|
+
|
|
+/*
|
|
+ * Starting in OpenSSL 3, algorithms are grouped into containers called
|
|
+ * "providers", not all of which are loaded by default. At time of writing,
|
|
+ * we need MD4 and RC4 from the legacy provider. Oddly, 3DES is not in
|
|
+ * legacy.
|
|
+ */
|
|
+
|
|
+#include <openssl/provider.h>
|
|
+
|
|
+OSSL_PROVIDER *legacy_provider = NULL;
|
|
+OSSL_PROVIDER *default_provider = NULL;
|
|
+
|
|
+int
|
|
+krb5int_crypto_impl_init(void)
|
|
+{
|
|
+ legacy_provider = OSSL_PROVIDER_load(NULL, "legacy");
|
|
+ default_provider = OSSL_PROVIDER_load(NULL, "default");
|
|
+
|
|
+ /*
|
|
+ * Someone might build openssl without the legacy provider. They will
|
|
+ * have a bad time, but some things will still work. I don't know think
|
|
+ * this configuration is worth supporting.
|
|
+ */
|
|
+ if (legacy_provider == NULL || default_provider == NULL)
|
|
+ abort();
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void
|
|
+krb5int_crypto_impl_cleanup(void)
|
|
+{
|
|
+ if (legacy_provider != NULL)
|
|
+ OSSL_PROVIDER_unload(legacy_provider);
|
|
+ if (default_provider != NULL)
|
|
+ OSSL_PROVIDER_unload(default_provider);
|
|
+
|
|
+ legacy_provider = NULL;
|
|
+ default_provider = NULL;
|
|
+}
|
|
+
|
|
+#else /* !HAVE_OSSL_PROVIDER_LOAD */
|
|
+
|
|
int
|
|
krb5int_crypto_impl_init(void)
|
|
{
|
|
@@ -36,3 +81,5 @@ void
|
|
krb5int_crypto_impl_cleanup(void)
|
|
{
|
|
}
|
|
+
|
|
+#endif
|
|
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
|
index 350c2118a..284702432 100644
|
|
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
|
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
|
@@ -44,6 +44,14 @@
|
|
#include <openssl/params.h>
|
|
#endif
|
|
|
|
+#ifdef HAVE_OSSL_PROVIDER_LOAD
|
|
+#include <openssl/provider.h>
|
|
+
|
|
+/* TODO these leak - where to release them? */
|
|
+OSSL_PROVIDER *legacy_provider = NULL;
|
|
+OSSL_PROVIDER *default_provider = NULL;
|
|
+#endif
|
|
+
|
|
static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context );
|
|
static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context );
|
|
|
|
@@ -2937,12 +2945,23 @@ cleanup:
|
|
return retval;
|
|
}
|
|
|
|
+/* Initialize OpenSSL. */
|
|
int
|
|
pkinit_openssl_init()
|
|
{
|
|
- /* Initialize OpenSSL. */
|
|
- ERR_load_crypto_strings();
|
|
- OpenSSL_add_all_algorithms();
|
|
+#ifdef HAVE_OSSL_PROVIDER_LOAD
|
|
+ legacy_provider = OSSL_PROVIDER_load(NULL, "legacy");
|
|
+ default_provider = OSSL_PROVIDER_load(NULL, "default");
|
|
+
|
|
+ /*
|
|
+ * Someone might build openssl without the legacy provider. They will
|
|
+ * have a bad time, but some things will still work. I don't know think
|
|
+ * this configuration is worth supporting.
|
|
+ */
|
|
+ if (legacy_provider == NULL || default_provider == NULL)
|
|
+ abort();
|
|
+#endif
|
|
+
|
|
return 0;
|
|
}
|
|
|