Add patches to support OpenSSL 3.0.0

Signed-off-by: Antonio Torres <antorres@redhat.com>
This commit is contained in:
Antonio Torres 2021-12-03 11:25:46 +01:00
parent 70255ea5b0
commit ad88d4fd50
10 changed files with 19474 additions and 77 deletions

View File

@ -0,0 +1,25 @@
From 2f039fc910022c9569fe6941a194f0b26bd6c894 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Fri, 20 Sep 2019 16:11:29 -0400
Subject: [PATCH] Add buildsystem detection of the OpenSSL-3 KDF interface
(cherry picked from commit a3e03dfd40928c4615bd9b8546eac0c104377850)
---
src/configure.ac | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/configure.ac b/src/configure.ac
index eb6307468..9c2e816fe 100644
--- a/src/configure.ac
+++ b/src/configure.ac
@@ -282,6 +282,10 @@ AC_SUBST(CRYPTO_IMPL)
AC_SUBST(CRYPTO_IMPL_CFLAGS)
AC_SUBST(CRYPTO_IMPL_LIBS)
+if test "$CRYPTO_IMPL" = openssl; then
+ AC_CHECK_FUNCS(EVP_KDF_fetch)
+fi
+
AC_ARG_WITH([prng-alg],
AC_HELP_STRING([--with-prng-alg=ALG], [use specified PRNG algorithm. @<:@fortuna@:>@]),
[PRNG_ALG=$withval

View File

@ -1,4 +1,4 @@
From 7e4429640f69acdd5d4f9caa655c011d8bd736f0 Mon Sep 17 00:00:00 2001
From 51938a8b731740299fe47d132b8840edba4141bc Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Sat, 29 May 2021 12:05:49 -0400
Subject: [PATCH] Fix k5tls module for OpenSSL 3
@ -16,6 +16,7 @@ doesn't clear existing options.
[ghudson@mit.edu: edited commit message and comment]
(cherry picked from commit aa9b4a2a64046afd2fab7cb49c346295874a5fb6)
(cherry picked from commit 201e38845e9f70234bcaa9ba7c25b28e38169b0a)
---
src/plugins/tls/k5tls/openssl.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)

View File

@ -1,4 +1,4 @@
From 391379bff864751262dbcedb897f2c2dd394345f Mon Sep 17 00:00:00 2001
From f85a818fe1a7438db7e1ea579818da67e0be017d Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Sat, 15 May 2021 17:35:25 -0400
Subject: [PATCH] Fix softpkcs11 build issues with openssl 3.0
@ -17,6 +17,7 @@ Move several argument validation checks to the top of their functions.
Fix some incorrect/inconsistent log messages.
(cherry picked from commit 00de1aad7b3647b91017c7009b0bc65cd0c8b2e0)
(cherry picked from commit a86b780ef275b35e8dc1e6d1886ec8e8d941f7c4)
---
src/tests/softpkcs11/main.c | 360 ++++++++++++++----------------------
1 file changed, 141 insertions(+), 219 deletions(-)

View File

@ -0,0 +1,301 @@
From e3f3d31a3db23f6c8437cd0efe45f67a7f4fc6aa 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.)
Use our normal initializer logic to set up providers both in the OpenSSL
provider an the PKINIT plugin. Since DT_FINI is too late, release them
using atexit() as OpenSSL does.
(cherry picked from commit bea5a703a06da1f1ab56821b77a2d3661cb0dda4)
[rharwood@redhat.com: work around des3 removal and rc4 fips changes]
---
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 | 53 +++++++++++++++++++
src/plugins/preauth/pkinit/Makefile.in | 1 +
.../preauth/pkinit/pkinit_crypto_openssl.c | 33 ++++++++++--
8 files changed, 126 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..a10cb5192 100644
--- a/src/lib/crypto/openssl/enc_provider/rc4.c
+++ b/src/lib/crypto/openssl/enc_provider/rc4.c
@@ -66,6 +66,10 @@ k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data,
EVP_CIPHER_CTX *ctx = NULL;
struct arcfour_state *arcstate;
+ ret = krb5int_crypto_init();
+ if (ret)
+ return ret;
+
if (FIPS_mode())
return KRB5_CRYPTO_INTERNAL;
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..f72dbfe81 100644
--- a/src/lib/crypto/openssl/init.c
+++ b/src/lib/crypto/openssl/init.c
@@ -26,12 +26,65 @@
#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>
+
+static OSSL_PROVIDER *legacy_provider = NULL;
+static OSSL_PROVIDER *default_provider = NULL;
+
+static void
+unload_providers(void)
+{
+ if (default_provider != NULL)
+ (void)OSSL_PROVIDER_unload(default_provider);
+ if (legacy_provider != NULL)
+ (void)OSSL_PROVIDER_unload(legacy_provider);
+ default_provider = NULL;
+ legacy_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();
+
+ /*
+ * If we attempt to do this with our normal LIBFINIFUNC logic (DT_FINI),
+ * OpenSSL will have cleaned itself up by the time we're invoked. OpenSSL
+ * registers its cleanup (OPENSSL_cleanup) with atexit() - do the same and
+ * we'll be higher on the stack.
+ */
+ atexit(unload_providers);
+ return 0;
+}
+
+#else /* !HAVE_OSSL_PROVIDER_LOAD */
+
int
krb5int_crypto_impl_init(void)
{
return 0;
}
+#endif
+
void
krb5int_crypto_impl_cleanup(void)
{
diff --git a/src/plugins/preauth/pkinit/Makefile.in b/src/plugins/preauth/pkinit/Makefile.in
index 15ca0eb48..d20fb18a8 100644
--- a/src/plugins/preauth/pkinit/Makefile.in
+++ b/src/plugins/preauth/pkinit/Makefile.in
@@ -5,6 +5,7 @@ MODULE_INSTALL_DIR = $(KRB5_PA_MODULE_DIR)
LIBBASE=pkinit
LIBMAJOR=0
LIBMINOR=0
+LIBINITFUNC=pkinit_openssl_init
RELDIR=../plugins/preauth/pkinit
# Depends on libk5crypto and libkrb5
SHLIB_EXPDEPS = \
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index 350c2118a..42e5c581d 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -44,6 +44,13 @@
#include <openssl/params.h>
#endif
+#ifdef HAVE_OSSL_PROVIDER_LOAD
+#include <openssl/provider.h>
+
+static OSSL_PROVIDER *legacy_provider = NULL;
+static 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 +2944,32 @@ cleanup:
return retval;
}
+/* pkinit_openssl_init() and unload_providers() are largely duplicated from
+ * lib/crypto/openssl/init.c - see explanations there. */
+static void
+unload_providers(void)
+{
+ if (default_provider != NULL)
+ (void)OSSL_PROVIDER_unload(default_provider);
+ if (legacy_provider != NULL)
+ (void)OSSL_PROVIDER_unload(legacy_provider);
+ default_provider = NULL;
+ legacy_provider = NULL;
+}
+
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");
+
+ if (legacy_provider == NULL || default_provider == NULL)
+ abort();
+
+ atexit(unload_providers);
+#endif
+
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
From 0a2778833d2f04a29fe9d7122913abe42299044a Mon Sep 17 00:00:00 2001
From c99ecf1bb49e2fbd0bf30a7b357cf06407b9588a Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Sat, 15 May 2021 18:04:58 -0400
Subject: [PATCH] Remove deprecated OpenSSL calls from softpkcs11
@ -7,16 +7,17 @@ Rewrite add_pubkey_info() in terms of the EVP_PKEY interface. In this
process, fix its unchecked allocations and fail fast for non-RSA keys.
(cherry picked from commit d6bf42279675100e3e4fe7c6e08eef74d49624cb)
(cherry picked from commit 5072bfdfaddae762680d0f9d97afa6dbf8274760)
---
src/configure.ac | 1 +
src/tests/softpkcs11/main.c | 106 ++++++++++++++++++++++++------------
2 files changed, 72 insertions(+), 35 deletions(-)
diff --git a/src/configure.ac b/src/configure.ac
index ea708491b..477819091 100644
index 3e1052db7..eb6307468 100644
--- a/src/configure.ac
+++ b/src/configure.ac
@@ -1118,6 +1118,7 @@ int i = 1;
@@ -1114,6 +1114,7 @@ int i = 1;
])], k5_cv_openssl_version_okay=yes, k5_cv_openssl_version_okay=no)])
old_LIBS="$LIBS"
AC_CHECK_LIB(crypto, PKCS7_get_signer_info)

View File

@ -0,0 +1,482 @@
From 21e3b9a4463f1d1aeb71de8a27c298f1307d186b Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Fri, 4 Oct 2019 14:49:29 -0400
Subject: [PATCH] Use OpenSSL's KBKDF and KRB5KDF for deriving long-term keys
If supported, use OpenSSL-provided KBKDF (aes-sha2 and camellia) and
KRB5KDF (3des and aes-sha1). We already use OpenSSL's PBKDF2 where
appropriate. OpenSSL added support for these KDFs in 3.0.
(cherry picked from commit ef8d11f6fb1232201c9efd2ae2ed567023fb85d2)
[rharwood@redhat.com: 3des removal]
---
src/lib/crypto/krb/derive.c | 409 ++++++++++++++++++++++++++++--------
1 file changed, 324 insertions(+), 85 deletions(-)
diff --git a/src/lib/crypto/krb/derive.c b/src/lib/crypto/krb/derive.c
index 6707a7308..8e474b38e 100644
--- a/src/lib/crypto/krb/derive.c
+++ b/src/lib/crypto/krb/derive.c
@@ -27,6 +27,12 @@
#include "crypto_int.h"
+#ifdef HAVE_EVP_KDF_FETCH
+#include <openssl/core_names.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#endif
+
static krb5_key
find_cached_dkey(struct derived_key *list, const krb5_data *constant)
{
@@ -77,55 +83,251 @@ cleanup:
return ENOMEM;
}
+#ifdef HAVE_EVP_KDF_FETCH
static krb5_error_code
-derive_random_rfc3961(const struct krb5_enc_provider *enc,
- krb5_key inkey, krb5_data *outrnd,
- const krb5_data *in_constant)
+openssl_kbdkf_counter_hmac(const struct krb5_hash_provider *hash,
+ krb5_key inkey, krb5_data *outrnd,
+ const krb5_data *label, const krb5_data *context)
{
- size_t blocksize, keybytes, n;
krb5_error_code ret;
- krb5_data block = empty_data();
+ EVP_KDF *kdf = NULL;
+ EVP_KDF_CTX *kctx = NULL;
+ OSSL_PARAM params[6];
+ size_t i = 0;
+ char *digest;
- blocksize = enc->block_size;
- keybytes = enc->keybytes;
+ /* On NULL hash, preserve default behavior for pbkdf2_string_to_key(). */
+ if (hash == NULL || !strcmp(hash->hash_name, "SHA1")) {
+ digest = "SHA1";
+ } else if (!strcmp(hash->hash_name, "SHA-256")) {
+ digest = "SHA256";
+ } else if (!strcmp(hash->hash_name, "SHA-384")) {
+ digest = "SHA384";
+ } else {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
- if (blocksize == 1)
- return KRB5_BAD_ENCTYPE;
- if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes)
+ kdf = EVP_KDF_fetch(NULL, "KBKDF", NULL);
+ if (!kdf) {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
+
+ kctx = EVP_KDF_CTX_new(kdf);
+ if (!kctx) {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
+
+ params[i++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ digest, 0);
+ params[i++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC,
+ "HMAC", 0);
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+ inkey->keyblock.contents,
+ inkey->keyblock.length);
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
+ context->data,
+ context->length);
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
+ label->data,
+ label->length);
+ params[i] = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, (unsigned char *)outrnd->data, outrnd->length,
+ params) <= 0) {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
+
+ ret = 0;
+done:
+ if (ret)
+ zap(outrnd->data, outrnd->length);
+ EVP_KDF_free(kdf);
+ EVP_KDF_CTX_free(kctx);
+ return ret;
+}
+
+static krb5_error_code
+openssl_kbkdf_feedback_cmac(const struct krb5_enc_provider *enc,
+ krb5_key inkey, krb5_data *outrnd,
+ const krb5_data *in_constant)
+{
+ krb5_error_code ret;
+ EVP_KDF *kdf = NULL;
+ EVP_KDF_CTX *kctx = NULL;
+ OSSL_PARAM params[7];
+ size_t i = 0;
+ char *cipher;
+ static unsigned char zeroes[16];
+
+ memset(zeroes, 0, sizeof(zeroes));
+
+ if (!memcmp(enc, &krb5int_enc_camellia128, sizeof(*enc))) {
+ cipher = "CAMELLIA-128-CBC";
+ } else if (!memcmp(enc, &krb5int_enc_camellia256, sizeof(*enc))) {
+ cipher = "CAMELLIA-256-CBC";
+ } else {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
+
+ kdf = EVP_KDF_fetch(NULL, "KBKDF", NULL);
+ if (!kdf) {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
+
+ kctx = EVP_KDF_CTX_new(kdf);
+ if (!kctx) {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
+
+ params[i++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MODE,
+ "FEEDBACK", 0);
+ params[i++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC,
+ "CMAC", 0);
+ params[i++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CIPHER,
+ cipher, 0);
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+ inkey->keyblock.contents,
+ inkey->keyblock.length);
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
+ in_constant->data,
+ in_constant->length);
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SEED,
+ zeroes, sizeof(zeroes));
+ params[i] = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, (unsigned char *)outrnd->data, outrnd->length,
+ params) <= 0) {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
+
+ ret = 0;
+done:
+ if (ret)
+ zap(outrnd->data, outrnd->length);
+ EVP_KDF_free(kdf);
+ EVP_KDF_CTX_free(kctx);
+ return ret;
+}
+
+static krb5_error_code
+openssl_krb5kdf(const struct krb5_enc_provider *enc, krb5_key inkey,
+ krb5_data *outrnd, const krb5_data *in_constant)
+{
+ krb5_error_code ret;
+ EVP_KDF *kdf = NULL;
+ EVP_KDF_CTX *kctx = NULL;
+ OSSL_PARAM params[4];
+ size_t i = 0;
+ char *cipher;
+
+ if (inkey->keyblock.length != enc->keylength ||
+ outrnd->length != enc->keybytes) {
+ return KRB5_CRYPTO_INTERNAL;
+ }
+
+ if (!memcmp(enc, &krb5int_enc_aes128, sizeof(*enc))) {
+ cipher = "AES-128-CBC";
+ } else if (!memcmp(enc, &krb5int_enc_aes256, sizeof(*enc))) {
+ cipher = "AES-256-CBC";
+ } else {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
+
+ kdf = EVP_KDF_fetch(NULL, "KRB5KDF", NULL);
+ if (kdf == NULL) {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
+
+ kctx = EVP_KDF_CTX_new(kdf);
+ if (kctx == NULL) {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
+
+ params[i++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CIPHER,
+ cipher, 0);
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+ inkey->keyblock.contents,
+ inkey->keyblock.length);
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_CONSTANT,
+ in_constant->data,
+ in_constant->length);
+ params[i] = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, (unsigned char *)outrnd->data, outrnd->length,
+ params) <= 0) {
+ ret = KRB5_CRYPTO_INTERNAL;
+ goto done;
+ }
+
+ ret = 0;
+done:
+ if (ret)
+ zap(outrnd->data, outrnd->length);
+ EVP_KDF_free(kdf);
+ EVP_KDF_CTX_free(kctx);
+ return ret;
+}
+
+#else /* HAVE_EVP_KDF_FETCH */
+
+/*
+ * NIST SP800-108 KDF in counter mode (section 5.1).
+ * Parameters:
+ * - HMAC (with hash as the hash provider) is the PRF.
+ * - A block counter of four bytes is used.
+ * - Four bytes are used to encode the output length in the PRF input.
+ *
+ * There are no uses requiring more than a single PRF invocation.
+ */
+static krb5_error_code
+builtin_sp800_108_counter_hmac(const struct krb5_hash_provider *hash,
+ krb5_key inkey, krb5_data *outrnd,
+ const krb5_data *label,
+ const krb5_data *context)
+{
+ krb5_crypto_iov iov[5];
+ krb5_error_code ret;
+ krb5_data prf;
+ unsigned char ibuf[4], lbuf[4];
+
+ if (hash == NULL || outrnd->length > hash->hashsize)
return KRB5_CRYPTO_INTERNAL;
/* Allocate encryption data buffer. */
- ret = alloc_data(&block, blocksize);
+ ret = alloc_data(&prf, hash->hashsize);
if (ret)
return ret;
- /* Initialize the input block. */
- if (in_constant->length == blocksize) {
- memcpy(block.data, in_constant->data, blocksize);
- } else {
- krb5int_nfold(in_constant->length * 8,
- (unsigned char *) in_constant->data,
- blocksize * 8, (unsigned char *) block.data);
- }
+ /* [i]2: four-byte big-endian binary string giving the block counter (1) */
+ iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[0].data = make_data(ibuf, sizeof(ibuf));
+ store_32_be(1, ibuf);
+ /* Label */
+ iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[1].data = *label;
+ /* 0x00: separator byte */
+ iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[2].data = make_data("", 1);
+ /* Context */
+ iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[3].data = *context;
+ /* [L]2: four-byte big-endian binary string giving the output length */
+ iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[4].data = make_data(lbuf, sizeof(lbuf));
+ store_32_be(outrnd->length * 8, lbuf);
- /* Loop encrypting the blocks until enough key bytes are generated. */
- n = 0;
- while (n < keybytes) {
- ret = encrypt_block(enc, inkey, &block);
- if (ret)
- goto cleanup;
-
- if ((keybytes - n) <= blocksize) {
- memcpy(outrnd->data + n, block.data, (keybytes - n));
- break;
- }
-
- memcpy(outrnd->data + n, block.data, blocksize);
- n += blocksize;
- }
-
-cleanup:
- zapfree(block.data, blocksize);
+ ret = krb5int_hmac(hash, inkey, iov, 5, &prf);
+ if (!ret)
+ memcpy(outrnd->data, prf.data, outrnd->length);
+ zapfree(prf.data, prf.length);
return ret;
}
@@ -139,9 +341,9 @@ cleanup:
* - Four bytes are used to encode the output length in the PRF input.
*/
static krb5_error_code
-derive_random_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc,
- krb5_key inkey, krb5_data *outrnd,
- const krb5_data *in_constant)
+builtin_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc,
+ krb5_key inkey, krb5_data *outrnd,
+ const krb5_data *in_constant)
{
size_t blocksize, keybytes, n;
krb5_crypto_iov iov[6];
@@ -204,56 +406,94 @@ cleanup:
return ret;
}
-/*
- * NIST SP800-108 KDF in counter mode (section 5.1).
- * Parameters:
- * - HMAC (with hash as the hash provider) is the PRF.
- * - A block counter of four bytes is used.
- * - Four bytes are used to encode the output length in the PRF input.
- *
- * There are no uses requiring more than a single PRF invocation.
- */
+static krb5_error_code
+builtin_derive_random_rfc3961(const struct krb5_enc_provider *enc,
+ krb5_key inkey, krb5_data *outrnd,
+ const krb5_data *in_constant)
+{
+ size_t blocksize, keybytes, n;
+ krb5_error_code ret;
+ krb5_data block = empty_data();
+
+ blocksize = enc->block_size;
+ keybytes = enc->keybytes;
+
+ if (blocksize == 1)
+ return KRB5_BAD_ENCTYPE;
+ if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes)
+ return KRB5_CRYPTO_INTERNAL;
+
+ /* Allocate encryption data buffer. */
+ ret = alloc_data(&block, blocksize);
+ if (ret)
+ return ret;
+
+ /* Initialize the input block. */
+ if (in_constant->length == blocksize) {
+ memcpy(block.data, in_constant->data, blocksize);
+ } else {
+ krb5int_nfold(in_constant->length * 8,
+ (unsigned char *) in_constant->data,
+ blocksize * 8, (unsigned char *) block.data);
+ }
+
+ /* Loop encrypting the blocks until enough key bytes are generated. */
+ n = 0;
+ while (n < keybytes) {
+ ret = encrypt_block(enc, inkey, &block);
+ if (ret)
+ goto cleanup;
+
+ if ((keybytes - n) <= blocksize) {
+ memcpy(outrnd->data + n, block.data, (keybytes - n));
+ break;
+ }
+
+ memcpy(outrnd->data + n, block.data, blocksize);
+ n += blocksize;
+ }
+
+cleanup:
+ zapfree(block.data, blocksize);
+ return ret;
+}
+#endif /* HAVE_EVP_KDF_FETCH */
+
krb5_error_code
k5_sp800_108_counter_hmac(const struct krb5_hash_provider *hash,
krb5_key inkey, krb5_data *outrnd,
const krb5_data *label, const krb5_data *context)
{
- krb5_crypto_iov iov[5];
- krb5_error_code ret;
- krb5_data prf;
- unsigned char ibuf[4], lbuf[4];
+#ifdef HAVE_EVP_KDF_FETCH
+ return openssl_kbdkf_counter_hmac(hash, inkey, outrnd, label, context);
+#else
+ return builtin_sp800_108_counter_hmac(hash, inkey, outrnd, label,
+ context);
+#endif
+}
- if (hash == NULL || outrnd->length > hash->hashsize)
- return KRB5_CRYPTO_INTERNAL;
+static krb5_error_code
+sp800_108_feedback_cmac(const struct krb5_enc_provider *enc,
+ krb5_key inkey, krb5_data *outrnd,
+ const krb5_data *in_constant)
+{
+#ifdef HAVE_EVP_KDF_FETCH
+ return openssl_kbkdf_feedback_cmac(enc, inkey, outrnd, in_constant);
+#else
+ return builtin_sp800_108_feedback_cmac(enc, inkey, outrnd, in_constant);
+#endif
+}
- /* Allocate encryption data buffer. */
- ret = alloc_data(&prf, hash->hashsize);
- if (ret)
- return ret;
-
- /* [i]2: four-byte big-endian binary string giving the block counter (1) */
- iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
- iov[0].data = make_data(ibuf, sizeof(ibuf));
- store_32_be(1, ibuf);
- /* Label */
- iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
- iov[1].data = *label;
- /* 0x00: separator byte */
- iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
- iov[2].data = make_data("", 1);
- /* Context */
- iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
- iov[3].data = *context;
- /* [L]2: four-byte big-endian binary string giving the output length */
- iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
- iov[4].data = make_data(lbuf, sizeof(lbuf));
- store_32_be(outrnd->length * 8, lbuf);
-
- ret = krb5int_hmac(hash, inkey, iov, 5, &prf);
- if (!ret)
- memcpy(outrnd->data, prf.data, outrnd->length);
- zapfree(prf.data, prf.length);
- return ret;
+static krb5_error_code
+derive_random_rfc3961(const struct krb5_enc_provider *enc,
+ krb5_key inkey, krb5_data *outrnd,
+ const krb5_data *in_constant)
+{
+#ifdef HAVE_EVP_KDF_FETCH
+ return openssl_krb5kdf(enc, inkey, outrnd, in_constant);
+#else
+ return builtin_derive_random_rfc3961(enc, inkey, outrnd, in_constant);
+#endif
}
krb5_error_code
@@ -268,8 +508,7 @@ krb5int_derive_random(const struct krb5_enc_provider *enc,
case DERIVE_RFC3961:
return derive_random_rfc3961(enc, inkey, outrnd, in_constant);
case DERIVE_SP800_108_CMAC:
- return derive_random_sp800_108_feedback_cmac(enc, inkey, outrnd,
- in_constant);
+ return sp800_108_feedback_cmac(enc, inkey, outrnd, in_constant);
case DERIVE_SP800_108_HMAC:
return k5_sp800_108_counter_hmac(hash, inkey, outrnd, in_constant,
&empty);

View File

@ -0,0 +1,408 @@
From 8bbb492f2be1418e1e4bb2cf197414810dac9589 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Fri, 20 Sep 2019 17:20:59 -0400
Subject: [PATCH] Use OpenSSL's SSKDF in PKINIT when available
Starting in 3.0, OpenSSL implements SSKDF, which is the basis of our
id-pkinit-kdf (RFC 8636). Factor out common setup code around
other_info. Adjust code to comply to existing style.
(cherry picked from commit 4376a22e41fb639be31daf81275a332d3f930996)
---
.../preauth/pkinit/pkinit_crypto_openssl.c | 294 +++++++++++-------
1 file changed, 181 insertions(+), 113 deletions(-)
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index e1153344e..350c2118a 100644
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -38,6 +38,12 @@
#include <dirent.h>
#include <arpa/inet.h>
+#ifdef HAVE_EVP_KDF_FETCH
+#include <openssl/core_names.h>
+#include <openssl/kdf.h>
+#include <openssl/params.h>
+#endif
+
static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context );
static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context );
@@ -2294,15 +2300,16 @@ cleanup:
}
-/**
+/*
* Given an algorithm_identifier, this function returns the hash length
* and EVP function associated with that algorithm.
+ *
+ * RFC 8636 defines a SHA384 variant, but we don't use it.
*/
static krb5_error_code
-pkinit_alg_values(krb5_context context,
- const krb5_data *alg_id,
- size_t *hash_bytes,
- const EVP_MD *(**func)(void))
+pkinit_alg_values(krb5_context context, const krb5_data *alg_id,
+ size_t *hash_bytes, const EVP_MD *(**func)(void),
+ char **hash_name)
{
*hash_bytes = 0;
*func = NULL;
@@ -2311,18 +2318,21 @@ pkinit_alg_values(krb5_context context,
krb5_pkinit_sha1_oid_len))) {
*hash_bytes = 20;
*func = &EVP_sha1;
+ *hash_name = strdup("SHA1");
return 0;
} else if ((alg_id->length == krb5_pkinit_sha256_oid_len) &&
(0 == memcmp(alg_id->data, krb5_pkinit_sha256_oid,
krb5_pkinit_sha256_oid_len))) {
*hash_bytes = 32;
*func = &EVP_sha256;
+ *hash_name = strdup("SHA256");
return 0;
} else if ((alg_id->length == krb5_pkinit_sha512_oid_len) &&
(0 == memcmp(alg_id->data, krb5_pkinit_sha512_oid,
krb5_pkinit_sha512_oid_len))) {
*hash_bytes = 64;
*func = &EVP_sha512;
+ *hash_name = strdup("SHA512");
return 0;
} else {
krb5_set_error_message(context, KRB5_ERR_BAD_S2K_PARAMS,
@@ -2331,11 +2341,60 @@ pkinit_alg_values(krb5_context context,
}
} /* pkinit_alg_values() */
+#ifdef HAVE_EVP_KDF_FETCH
+static krb5_error_code
+openssl_sskdf(krb5_context context, size_t hash_bytes, krb5_data *key,
+ krb5_data *info, char *out, size_t out_len, char *digest)
+{
+ krb5_error_code ret;
+ EVP_KDF *kdf = NULL;
+ EVP_KDF_CTX *kctx = NULL;
+ OSSL_PARAM params[4];
+ size_t i = 0;
-/* pkinit_alg_agility_kdf() --
- * This function generates a key using the KDF described in
- * draft_ietf_krb_wg_pkinit_alg_agility-04.txt. The algorithm is
- * described as follows:
+ if (digest == NULL) {
+ ret = oerr(context, ENOMEM,
+ _("Failed to allocate space for digest algorithm name"));
+ goto done;
+ }
+
+ kdf = EVP_KDF_fetch(NULL, "SSKDF", NULL);
+ if (kdf == NULL) {
+ ret = oerr(context, KRB5_CRYPTO_INTERNAL, _("Failed to fetch SSKDF"));
+ goto done;
+ }
+
+ kctx = EVP_KDF_CTX_new(kdf);
+ if (!kctx) {
+ ret = oerr(context, KRB5_CRYPTO_INTERNAL,
+ _("Failed to instantiate SSKDF"));
+ goto done;
+ }
+
+ params[i++] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ digest, 0);
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+ key->data, key->length);
+ params[i++] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
+ info->data, info->length);
+ params[i] = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, (unsigned char *)out, out_len, params) <= 0) {
+ ret = oerr(context, KRB5_CRYPTO_INTERNAL,
+ _("Failed to derive key using SSKDF"));
+ goto done;
+ }
+
+ ret = 0;
+done:
+ EVP_KDF_free(kdf);
+ EVP_KDF_CTX_free(kctx);
+ return ret;
+}
+#else
+/*
+ * Generate a key using the KDF described in RFC 8636, also known as SSKDF
+ * (single-step kdf). Our caller precomputes `reps`, but otherwise the
+ * algorithm is as follows:
*
* 1. reps = keydatalen (K) / hash length (H)
*
@@ -2349,95 +2408,16 @@ pkinit_alg_values(krb5_context context,
*
* 4. Set key = Hash1 || Hash2 || ... so that length of key is K bytes.
*/
-krb5_error_code
-pkinit_alg_agility_kdf(krb5_context context,
- krb5_data *secret,
- krb5_data *alg_oid,
- krb5_const_principal party_u_info,
- krb5_const_principal party_v_info,
- krb5_enctype enctype,
- krb5_data *as_req,
- krb5_data *pk_as_rep,
- krb5_keyblock *key_block)
+static krb5_error_code
+builtin_sskdf(krb5_context context, unsigned int reps, size_t hash_len,
+ const EVP_MD *(*EVP_func)(void), krb5_data *secret,
+ krb5_data *other_info, char *out, size_t out_len)
{
- krb5_error_code retval = 0;
+ krb5_error_code ret = 0;
- unsigned int reps = 0;
- uint32_t counter = 1; /* Does this type work on Windows? */
+ uint32_t counter = 1;
size_t offset = 0;
- size_t hash_len = 0;
- size_t rand_len = 0;
- size_t key_len = 0;
- krb5_data random_data;
- krb5_sp80056a_other_info other_info_fields;
- krb5_pkinit_supp_pub_info supp_pub_info_fields;
- krb5_data *other_info = NULL;
- krb5_data *supp_pub_info = NULL;
- krb5_algorithm_identifier alg_id;
EVP_MD_CTX *ctx = NULL;
- const EVP_MD *(*EVP_func)(void);
-
- /* initialize random_data here to make clean-up safe */
- random_data.length = 0;
- random_data.data = NULL;
-
- /* allocate and initialize the key block */
- key_block->magic = 0;
- key_block->enctype = enctype;
- if (0 != (retval = krb5_c_keylengths(context, enctype, &rand_len,
- &key_len)))
- goto cleanup;
-
- random_data.length = rand_len;
- key_block->length = key_len;
-
- if (NULL == (key_block->contents = malloc(key_block->length))) {
- retval = ENOMEM;
- goto cleanup;
- }
-
- memset (key_block->contents, 0, key_block->length);
-
- /* If this is anonymous pkinit, use the anonymous principle for party_u_info */
- if (party_u_info && krb5_principal_compare_any_realm(context, party_u_info,
- krb5_anonymous_principal()))
- party_u_info = (krb5_principal)krb5_anonymous_principal();
-
- if (0 != (retval = pkinit_alg_values(context, alg_oid, &hash_len, &EVP_func)))
- goto cleanup;
-
- /* 1. reps = keydatalen (K) / hash length (H) */
- reps = key_block->length/hash_len;
-
- /* ... and round up, if necessary */
- if (key_block->length > (reps * hash_len))
- reps++;
-
- /* Allocate enough space in the random data buffer to hash directly into
- * it, even if the last hash will make it bigger than the key length. */
- if (NULL == (random_data.data = malloc(reps * hash_len))) {
- retval = ENOMEM;
- goto cleanup;
- }
-
- /* Encode the ASN.1 octet string for "SuppPubInfo" */
- supp_pub_info_fields.enctype = enctype;
- supp_pub_info_fields.as_req = *as_req;
- supp_pub_info_fields.pk_as_rep = *pk_as_rep;
- if (0 != ((retval = encode_krb5_pkinit_supp_pub_info(&supp_pub_info_fields,
- &supp_pub_info))))
- goto cleanup;
-
- /* Now encode the ASN.1 octet string for "OtherInfo" */
- memset(&alg_id, 0, sizeof alg_id);
- alg_id.algorithm = *alg_oid; /*alias*/
-
- other_info_fields.algorithm_identifier = alg_id;
- other_info_fields.party_u_info = (krb5_principal) party_u_info;
- other_info_fields.party_v_info = (krb5_principal) party_v_info;
- other_info_fields.supp_pub_info = *supp_pub_info;
- if (0 != (retval = encode_krb5_sp80056a_other_info(&other_info_fields, &other_info)))
- goto cleanup;
/* 2. Initialize a 32-bit, big-endian bit string counter as 1.
* 3. For i = 1 to reps by 1, do the following:
@@ -2450,7 +2430,7 @@ pkinit_alg_agility_kdf(krb5_context context,
ctx = EVP_MD_CTX_new();
if (ctx == NULL) {
- retval = KRB5_CRYPTO_INTERNAL;
+ ret = KRB5_CRYPTO_INTERNAL;
goto cleanup;
}
@@ -2458,7 +2438,7 @@ pkinit_alg_agility_kdf(krb5_context context,
if (!EVP_DigestInit(ctx, EVP_func())) {
krb5_set_error_message(context, KRB5_CRYPTO_INTERNAL,
"Call to OpenSSL EVP_DigestInit() returned an error.");
- retval = KRB5_CRYPTO_INTERNAL;
+ ret = KRB5_CRYPTO_INTERNAL;
goto cleanup;
}
@@ -2467,15 +2447,16 @@ pkinit_alg_agility_kdf(krb5_context context,
!EVP_DigestUpdate(ctx, other_info->data, other_info->length)) {
krb5_set_error_message(context, KRB5_CRYPTO_INTERNAL,
"Call to OpenSSL EVP_DigestUpdate() returned an error.");
- retval = KRB5_CRYPTO_INTERNAL;
+ ret = KRB5_CRYPTO_INTERNAL;
goto cleanup;
}
- /* 4. Set key = Hash1 || Hash2 || ... so that length of key is K bytes. */
- if (!EVP_DigestFinal(ctx, (uint8_t *)random_data.data + offset, &s)) {
+ /* 4. Set key = Hash1 || Hash2 || ... so that length of key is K
+ * bytes. */
+ if (!EVP_DigestFinal(ctx, (unsigned char *)out + offset, &s)) {
krb5_set_error_message(context, KRB5_CRYPTO_INTERNAL,
"Call to OpenSSL EVP_DigestUpdate() returned an error.");
- retval = KRB5_CRYPTO_INTERNAL;
+ ret = KRB5_CRYPTO_INTERNAL;
goto cleanup;
}
offset += s;
@@ -2484,26 +2465,113 @@ pkinit_alg_agility_kdf(krb5_context context,
EVP_MD_CTX_free(ctx);
ctx = NULL;
}
-
- retval = krb5_c_random_to_key(context, enctype, &random_data,
- key_block);
-
cleanup:
EVP_MD_CTX_free(ctx);
+ return ret;
+} /* builtin_sskdf() */
+#endif /* HAVE_EVP_KDF_FETCH */
- /* If this has been an error, free the allocated key_block, if any */
- if (retval) {
- krb5_free_keyblock_contents(context, key_block);
+/* id-pkinit-kdf family, as specified by RFC 8636. */
+krb5_error_code
+pkinit_alg_agility_kdf(krb5_context context, krb5_data *secret,
+ krb5_data *alg_oid, krb5_const_principal party_u_info,
+ krb5_const_principal party_v_info,
+ krb5_enctype enctype, krb5_data *as_req,
+ krb5_data *pk_as_rep, krb5_keyblock *key_block)
+{
+ krb5_error_code ret;
+ size_t hash_len = 0, rand_len = 0, key_len = 0;
+ const EVP_MD *(*EVP_func)(void);
+ krb5_sp80056a_other_info other_info_fields;
+ krb5_pkinit_supp_pub_info supp_pub_info_fields;
+ krb5_data *other_info = NULL, *supp_pub_info = NULL;
+ krb5_data random_data = empty_data();
+ krb5_algorithm_identifier alg_id;
+ unsigned int reps;
+ char *hash_name = NULL;
+
+ /* Allocate and initialize the key block. */
+ key_block->magic = 0;
+ key_block->enctype = enctype;
+
+ /* Use separate variables to avoid alignment restriction problems. */
+ ret = krb5_c_keylengths(context, enctype, &rand_len, &key_len);
+ if (ret)
+ goto cleanup;
+ random_data.length = rand_len;
+ key_block->length = key_len;
+
+ key_block->contents = k5calloc(key_block->length, 1, &ret);
+ if (key_block->contents == NULL)
+ goto cleanup;
+
+ /* If this is anonymous pkinit, use the anonymous principle for
+ * party_u_info. */
+ if (party_u_info &&
+ krb5_principal_compare_any_realm(context, party_u_info,
+ krb5_anonymous_principal())) {
+ party_u_info = (krb5_principal)krb5_anonymous_principal();
}
- /* free other allocated resources, either way */
- if (random_data.data)
- free(random_data.data);
+ ret = pkinit_alg_values(context, alg_oid, &hash_len, &EVP_func,
+ &hash_name);
+ if (ret)
+ goto cleanup;
+
+ /* 1. reps = keydatalen (K) / hash length (H) */
+ reps = key_block->length / hash_len;
+
+ /* ... and round up, if necessary. */
+ if (key_block->length > (reps * hash_len))
+ reps++;
+
+ /* Allocate enough space in the random data buffer to hash directly into
+ * it, even if the last hash will make it bigger than the key length. */
+ random_data.data = k5alloc(reps * hash_len, &ret);
+ if (random_data.data == NULL)
+ goto cleanup;
+
+ /* Encode the ASN.1 octet string for "SuppPubInfo". */
+ supp_pub_info_fields.enctype = enctype;
+ supp_pub_info_fields.as_req = *as_req;
+ supp_pub_info_fields.pk_as_rep = *pk_as_rep;
+ ret = encode_krb5_pkinit_supp_pub_info(&supp_pub_info_fields,
+ &supp_pub_info);
+ if (ret)
+ goto cleanup;
+
+ /* Now encode the ASN.1 octet string for "OtherInfo". */
+ memset(&alg_id, 0, sizeof(alg_id));
+ alg_id.algorithm = *alg_oid;
+ other_info_fields.algorithm_identifier = alg_id;
+ other_info_fields.party_u_info = (krb5_principal)party_u_info;
+ other_info_fields.party_v_info = (krb5_principal)party_v_info;
+ other_info_fields.supp_pub_info = *supp_pub_info;
+ ret = encode_krb5_sp80056a_other_info(&other_info_fields, &other_info);
+ if (ret)
+ goto cleanup;
+
+#ifdef HAVE_EVP_KDF_FETCH
+ ret = openssl_sskdf(context, hash_len, secret, other_info,
+ random_data.data, key_block->length, hash_name);
+#else
+ ret = builtin_sskdf(context, reps, hash_len, EVP_func, secret,
+ other_info, random_data.data, key_block->length);
+#endif
+ if (ret)
+ goto cleanup;
+
+ ret = krb5_c_random_to_key(context, enctype, &random_data, key_block);
+cleanup:
+ if (ret)
+ krb5_free_keyblock_contents(context, key_block);
+
+ free(hash_name);
+ zapfree(random_data.data, random_data.length);
krb5_free_data(context, other_info);
krb5_free_data(context, supp_pub_info);
-
- return retval;
-} /*pkinit_alg_agility_kdf() */
+ return ret;
+}
/* Call DH_compute_key() and ensure that we left-pad short results instead of
* leaving junk bytes at the end of the buffer. */

View File

@ -9,6 +9,12 @@ to user other enctypes. Mark the 3DES enctypes UNSUPPORTED and retain
their constants.
Last-updated: 1.19-beta1
[antorres@redhat.com: remove diffs for:
- src/kdamin/testing/proto/kdc.conf.proto
- src/lib/kadm5/unit-test/api.current/chpass-principal-v2.exp
- src/lib/kadm5/unit-test/api.current/get-principal-v2.exp
- src/lib/kadm5/unit-test/api.current/randkey-principal-v2.exp
since they were removed by Remove-TCL-based-libkadm5-API-tests.patch]
---
doc/admin/advanced/retiring-des.rst | 11 +
doc/admin/conf_files/kdc_conf.rst | 7 +-
@ -350,19 +356,6 @@ index db80063eb..63e67a2ba 100644
#define CKSUMTYPE_HMAC_SHA1_96_AES128 0x000f /**< RFC 3962. Used with
ENCTYPE_AES128_CTS_HMAC_SHA1_96 */
#define CKSUMTYPE_HMAC_SHA1_96_AES256 0x0010 /**< RFC 3962. Used with
diff --git a/src/kadmin/testing/proto/kdc.conf.proto b/src/kadmin/testing/proto/kdc.conf.proto
index 8a4b87de1..d7f1d076b 100644
--- a/src/kadmin/testing/proto/kdc.conf.proto
+++ b/src/kadmin/testing/proto/kdc.conf.proto
@@ -11,6 +11,6 @@
dict_file = __K5ROOT__/ovsec_adm.dict
kadmind_port = 1751
kpasswd_port = 1752
- master_key_type = des3-hmac-sha1
- supported_enctypes = des3-hmac-sha1:normal aes256-cts:normal aes128-cts:normal aes256-sha2:normal aes128-sha2:normal
+ master_key_type = aes256-cts
+ supported_enctypes = aes256-cts:normal aes128-cts:normal aes256-sha2:normal aes128-sha2:normal
}
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index 60f30c4f4..c65375aef 100644
--- a/src/kdc/kdc_util.c
@ -5575,55 +5568,6 @@ index 84f194988..32150f5e3 100644
case ENCTYPE_ARCFOUR_HMAC:
case ENCTYPE_ARCFOUR_HMAC_EXP:
/* RFC 4121 accidentally omits RC4-HMAC-EXP as a "not-newer" enctype,
diff --git a/src/lib/kadm5/unit-test/api.current/chpass-principal-v2.exp b/src/lib/kadm5/unit-test/api.current/chpass-principal-v2.exp
index 740425c69..6b45f5f72 100644
--- a/src/lib/kadm5/unit-test/api.current/chpass-principal-v2.exp
+++ b/src/lib/kadm5/unit-test/api.current/chpass-principal-v2.exp
@@ -53,10 +53,10 @@ proc test200 {} {
}
# XXX Perhaps I should actually check the key type returned.
- if {$num_keys == 5} {
+ if {$num_keys == 4} {
pass "$test"
} else {
- fail "$test: $num_keys keys, should be 5"
+ fail "$test: $num_keys keys, should be 4"
}
if { ! [cmd {kadm5_destroy $server_handle}]} {
perror "$test: unexpected failure in destroy"
diff --git a/src/lib/kadm5/unit-test/api.current/get-principal-v2.exp b/src/lib/kadm5/unit-test/api.current/get-principal-v2.exp
index 3ea1ba29b..d2c6d1afa 100644
--- a/src/lib/kadm5/unit-test/api.current/get-principal-v2.exp
+++ b/src/lib/kadm5/unit-test/api.current/get-principal-v2.exp
@@ -143,8 +143,8 @@ proc test101_102 {rpc} {
}
set failed 0
- if {$num_keys != 5} {
- fail "$test: num_keys $num_keys should be 5"
+ if {$num_keys != 4} {
+ fail "$test: num_keys $num_keys should be 4"
set failed 1
}
for {set i 0} {$i < $num_keys} {incr i} {
diff --git a/src/lib/kadm5/unit-test/api.current/randkey-principal-v2.exp b/src/lib/kadm5/unit-test/api.current/randkey-principal-v2.exp
index 2925c1c43..2f76c8b43 100644
--- a/src/lib/kadm5/unit-test/api.current/randkey-principal-v2.exp
+++ b/src/lib/kadm5/unit-test/api.current/randkey-principal-v2.exp
@@ -46,10 +46,10 @@ proc test100 {} {
}
# XXX Perhaps I should actually check the key type returned.
- if {$num_keys == 5} {
+ if {$num_keys == 4} {
pass "$test"
} else {
- fail "$test: $num_keys keys, should be 5"
+ fail "$test: $num_keys keys, should be 4"
}
if { ! [cmd {kadm5_destroy $server_handle}]} {
perror "$test: unexpected failure in destroy"
diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c
index aa35baa3c..bfa99d9eb 100644
--- a/src/lib/krb5/krb/init_ctx.c

View File

@ -42,7 +42,7 @@
Summary: The Kerberos network authentication system
Name: krb5
Version: 1.19.2
Release: %{?zdpd}3%{?dist}.1
Release: %{?zdpd}4%{?dist}
# rharwood has trust path to signing key and verifies on check-in
Source0: https://web.mit.edu/kerberos/dist/krb5/%{version}/krb5-%{version}%{?dashpre}.tar.gz
@ -68,7 +68,6 @@ Patch1: downstream-SELinux-integration.patch
Patch3: downstream-netlib-and-dns.patch
Patch4: downstream-fix-debuginfo-with-y.tab.c.patch
Patch5: downstream-Remove-3des-support.patch
Patch6: downstream-Use-backported-version-of-OpenSSL-3-KDF-i.patch
Patch7: downstream-FIPS-with-PRNG-and-RADIUS-and-MD4.patch
Patch8: Add-APIs-for-marshalling-credentials.patch
Patch9: Add-hostname-canonicalization-helper-to-k5test.py.patch
@ -90,6 +89,11 @@ Patch25: Clean-up-context-after-failed-open-in-libkdb5.patch
Patch26: Use-asan-in-one-of-the-CI-builds.patch
Patch29: Clean-up-gssapi_krb5-ccache-name-functions.patch
Patch30: Fix-KDC-null-deref-on-TGS-inner-body-null-server.patch
Patch32: Add-buildsystem-detection-of-the-OpenSSL-3-KDF-inter.patch
Patch33: Use-OpenSSL-s-SSKDF-in-PKINIT-when-available.patch
Patch34: Use-OpenSSL-s-KBKDF-and-KRB5KDF-for-deriving-long-te.patch
Patch35: Handle-OpenSSL-3-s-providers.patch
Patch36: Remove-TCL-based-libkadm5-API-tests.patch
License: MIT
URL: https://web.mit.edu/kerberos/www/
@ -118,11 +122,11 @@ BuildRequires: net-tools, rpcbind
BuildRequires: hostname
BuildRequires: iproute
BuildRequires: python3-pyrad
BuildRequires: procps-ng
%endif
# Need KDFs. This is the backported version
BuildRequires: openssl-devel >= 1:1.1.1d-4
BuildRequires: openssl-devel < 1:3.0.0
# Need KDFs. This is the "real" version
BuildRequires: openssl-devel => 1:3.0.0
%description
Kerberos V5 is a trusted-third-party network authentication system,
@ -148,7 +152,7 @@ to install this package.
%package libs
Summary: The non-admin shared libraries used by Kerberos 5
Requires: openssl-libs >= 1:1.1.1d-4
Requires: openssl-libs >= 1:3.0.0
Requires: coreutils, gawk, grep, sed
Requires: keyutils-libs >= 1.5.8
Requires: /etc/crypto-policies/back-ends/krb5.config
@ -248,10 +252,7 @@ popd
# Mess with some of the default ports that we use for testing, so that multiple
# builds going on the same host don't step on each other.
cfg="src/kadmin/testing/proto/kdc.conf.proto \
src/kadmin/testing/proto/krb5.conf.proto \
src/lib/kadm5/unit-test/api.current/init-v2.exp \
src/util/k5test.py"
cfg="src/util/k5test.py"
LONG_BIT=`getconf LONG_BIT`
PORT=`expr 61000 + $LONG_BIT - 48`
sed -i -e s,61000,`expr "$PORT" + 0`,g $cfg
@ -647,6 +648,10 @@ exit 0
%{_libdir}/libkadm5srv_mit.so.*
%changelog
* Fri Dec 3 2021 Antonio Torres <antorres@redhat.com> - 1.19.2-4
- Add patches to support OpenSLL 3.0.0
- Remove TCL-based libkadm5 API tests
* Tue Sep 14 2021 Sahana Prasad <sahana@redhat.com> - 1.19.2-3.1
- Rebuilt with OpenSSL 3.0.0