Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 19c363a900 |
619
SOURCES/Add-PKINIT-paChecksum2-from-MS-PKCA-v20230920.patch
Normal file
619
SOURCES/Add-PKINIT-paChecksum2-from-MS-PKCA-v20230920.patch
Normal file
@ -0,0 +1,619 @@
|
||||
From 7b5dad42e9d5103b763f3c79b82fc619bd3d2d32 Mon Sep 17 00:00:00 2001
|
||||
From: Julien Rische <jrische@redhat.com>
|
||||
Date: Thu, 3 Apr 2025 16:29:07 +0200
|
||||
Subject: [PATCH] Add PKINIT paChecksum2 from MS-PKCA v20230920
|
||||
|
||||
(This commit was rewrote for CentOS 8 Stream)
|
||||
|
||||
In 2023, Microsoft updated MS-PKCA to add the optional paChecksum2
|
||||
element in the PKAuthenticator sequence. This checksum accepts SHA-1,
|
||||
SHA-256, SHA-384, and SHA-512 digests.
|
||||
|
||||
In Windows Server 2025, this checksum becomes mandatory when using
|
||||
PKINIT with FFDH (but strangely not with ECDH if SHA-1 is configured as
|
||||
allowed).
|
||||
|
||||
[ghudson@mit.edu: refactored crypto interfaces to reduce complexity of
|
||||
calling code]
|
||||
|
||||
ticket: 9166 (new)
|
||||
---
|
||||
src/include/k5-int-pkinit.h | 25 ++--
|
||||
src/lib/krb5/asn.1/asn1_k_encode.c | 18 ++-
|
||||
src/plugins/preauth/pkinit/pkinit.h | 1 +
|
||||
src/plugins/preauth/pkinit/pkinit_clnt.c | 41 +++----
|
||||
src/plugins/preauth/pkinit/pkinit_crypto.h | 18 +++
|
||||
.../preauth/pkinit/pkinit_crypto_openssl.c | 110 ++++++++++++++++++
|
||||
.../preauth/pkinit/pkinit_kdf_constants.c | 24 ++++
|
||||
src/plugins/preauth/pkinit/pkinit_lib.c | 16 ++-
|
||||
src/plugins/preauth/pkinit/pkinit_srv.c | 39 ++-----
|
||||
src/plugins/preauth/pkinit/pkinit_trace.h | 5 +-
|
||||
src/tests/asn.1/krb5_decode_test.c | 2 +-
|
||||
src/tests/asn.1/ktest.c | 7 +-
|
||||
src/tests/asn.1/ktest_equal.c | 2 +-
|
||||
src/tests/asn.1/pkinit_encode.out | 2 +-
|
||||
src/tests/asn.1/pkinit_trval.out | 2 +-
|
||||
15 files changed, 233 insertions(+), 79 deletions(-)
|
||||
|
||||
diff --git a/src/include/k5-int-pkinit.h b/src/include/k5-int-pkinit.h
|
||||
index c23cfd3043..096f4e6145 100644
|
||||
--- a/src/include/k5-int-pkinit.h
|
||||
+++ b/src/include/k5-int-pkinit.h
|
||||
@@ -36,15 +36,6 @@
|
||||
* pkinit structures
|
||||
*/
|
||||
|
||||
-/* PKAuthenticator */
|
||||
-typedef struct _krb5_pk_authenticator {
|
||||
- krb5_int32 cusec; /* (0..999999) */
|
||||
- krb5_timestamp ctime;
|
||||
- krb5_int32 nonce; /* (0..4294967295) */
|
||||
- krb5_checksum paChecksum;
|
||||
- krb5_data *freshnessToken;
|
||||
-} krb5_pk_authenticator;
|
||||
-
|
||||
/* AlgorithmIdentifier */
|
||||
typedef struct _krb5_algorithm_identifier {
|
||||
krb5_data algorithm; /* OID */
|
||||
@@ -57,6 +48,22 @@ typedef struct _krb5_subject_pk_info {
|
||||
krb5_data subjectPublicKey; /* BIT STRING */
|
||||
} krb5_subject_pk_info;
|
||||
|
||||
+/* PAChecksum2 */
|
||||
+typedef struct _krb5_pachecksum2 {
|
||||
+ krb5_data checksum;
|
||||
+ krb5_algorithm_identifier algorithmIdentifier;
|
||||
+} krb5_pachecksum2;
|
||||
+
|
||||
+/* PKAuthenticator */
|
||||
+typedef struct _krb5_pk_authenticator {
|
||||
+ krb5_int32 cusec; /* (0..999999) */
|
||||
+ krb5_timestamp ctime;
|
||||
+ krb5_int32 nonce; /* (0..4294967295) */
|
||||
+ krb5_data paChecksum;
|
||||
+ krb5_data *freshnessToken; /* Optional */
|
||||
+ krb5_pachecksum2 *paChecksum2; /* Optional */
|
||||
+} krb5_pk_authenticator;
|
||||
+
|
||||
/** AuthPack from RFC 4556*/
|
||||
typedef struct _krb5_auth_pack {
|
||||
krb5_pk_authenticator pkAuthenticator;
|
||||
diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c
|
||||
index 39fa8e3bbb..79c845b5d6 100644
|
||||
--- a/src/lib/krb5/asn.1/asn1_k_encode.c
|
||||
+++ b/src/lib/krb5/asn.1/asn1_k_encode.c
|
||||
@@ -1429,20 +1429,30 @@ DEFSEQTYPE(pkinit_supp_pub_info, krb5_pkinit_supp_pub_info,
|
||||
MAKE_ENCODER(encode_krb5_pkinit_supp_pub_info, pkinit_supp_pub_info);
|
||||
MAKE_ENCODER(encode_krb5_sp80056a_other_info, sp80056a_other_info);
|
||||
|
||||
-/* A krb5_checksum encoded as an OCTET STRING, for PKAuthenticator. */
|
||||
-DEFCOUNTEDTYPE(ostring_checksum, krb5_checksum, contents, length, octetstring);
|
||||
+DEFFIELD(pachecksum2_0, krb5_pachecksum2, checksum, 0, ostring_data);
|
||||
+DEFFIELD(pachecksum2_1, krb5_pachecksum2, algorithmIdentifier, 1,
|
||||
+ algorithm_identifier);
|
||||
+static const struct atype_info *pachecksum2_fields[] = {
|
||||
+ &k5_atype_pachecksum2_0, &k5_atype_pachecksum2_1
|
||||
+};
|
||||
+DEFSEQTYPE(pachecksum2, krb5_pachecksum2, pachecksum2_fields);
|
||||
+
|
||||
+DEFPTRTYPE(pachecksum2_ptr, pachecksum2);
|
||||
+DEFOPTIONALZEROTYPE(opt_pachecksum2_ptr, pachecksum2_ptr);
|
||||
|
||||
DEFFIELD(pk_authenticator_0, krb5_pk_authenticator, cusec, 0, int32);
|
||||
DEFFIELD(pk_authenticator_1, krb5_pk_authenticator, ctime, 1, kerberos_time);
|
||||
DEFFIELD(pk_authenticator_2, krb5_pk_authenticator, nonce, 2, int32);
|
||||
DEFFIELD(pk_authenticator_3, krb5_pk_authenticator, paChecksum, 3,
|
||||
- ostring_checksum);
|
||||
+ ostring_data);
|
||||
DEFFIELD(pk_authenticator_4, krb5_pk_authenticator, freshnessToken, 4,
|
||||
opt_ostring_data_ptr);
|
||||
+DEFFIELD(pk_authenticator_5, krb5_pk_authenticator, paChecksum2, 5,
|
||||
+ opt_pachecksum2_ptr);
|
||||
static const struct atype_info *pk_authenticator_fields[] = {
|
||||
&k5_atype_pk_authenticator_0, &k5_atype_pk_authenticator_1,
|
||||
&k5_atype_pk_authenticator_2, &k5_atype_pk_authenticator_3,
|
||||
- &k5_atype_pk_authenticator_4
|
||||
+ &k5_atype_pk_authenticator_4, &k5_atype_pk_authenticator_5
|
||||
};
|
||||
DEFSEQTYPE(pk_authenticator, krb5_pk_authenticator, pk_authenticator_fields);
|
||||
|
||||
diff --git a/src/plugins/preauth/pkinit/pkinit.h b/src/plugins/preauth/pkinit/pkinit.h
|
||||
index ab132d78a9..b4120f3c61 100644
|
||||
--- a/src/plugins/preauth/pkinit/pkinit.h
|
||||
+++ b/src/plugins/preauth/pkinit/pkinit.h
|
||||
@@ -339,6 +339,7 @@ void free_krb5_algorithm_identifiers(krb5_algorithm_identifier ***in);
|
||||
void free_krb5_algorithm_identifier(krb5_algorithm_identifier *in);
|
||||
void free_krb5_kdc_dh_key_info(krb5_kdc_dh_key_info **in);
|
||||
void free_krb5_subject_pk_info(krb5_subject_pk_info **in);
|
||||
+void free_pachecksum2(krb5_context context, krb5_pachecksum2 **in);
|
||||
krb5_error_code pkinit_copy_krb5_data(krb5_data *dst, const krb5_data *src);
|
||||
|
||||
|
||||
diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c
|
||||
index ca0162897b..e07c05518c 100644
|
||||
--- a/src/plugins/preauth/pkinit/pkinit_clnt.c
|
||||
+++ b/src/plugins/preauth/pkinit/pkinit_clnt.c
|
||||
@@ -57,10 +57,9 @@ use_content_info(krb5_context context, pkinit_req_context req,
|
||||
static krb5_error_code
|
||||
pkinit_as_req_create(krb5_context context, pkinit_context plgctx,
|
||||
pkinit_req_context reqctx, krb5_timestamp ctsec,
|
||||
- krb5_int32 cusec, krb5_ui_4 nonce,
|
||||
- const krb5_checksum *cksum,
|
||||
- krb5_principal client, krb5_principal server,
|
||||
- krb5_data **as_req);
|
||||
+ krb5_int32 cusec, krb5_ui_4 nonce, const krb5_data *cksum,
|
||||
+ const krb5_pachecksum2 *cksum2, krb5_principal client,
|
||||
+ krb5_principal server, krb5_data **as_req);
|
||||
|
||||
static krb5_error_code
|
||||
pkinit_as_rep_parse(krb5_context context, pkinit_context plgctx,
|
||||
@@ -90,7 +89,8 @@ pa_pkinit_gen_req(krb5_context context,
|
||||
krb5_timestamp ctsec = 0;
|
||||
krb5_int32 cusec = 0;
|
||||
krb5_ui_4 nonce = 0;
|
||||
- krb5_checksum cksum;
|
||||
+ krb5_data cksum = empty_data();
|
||||
+ krb5_pachecksum2 *cksum2 = NULL;
|
||||
krb5_data *der_req = NULL;
|
||||
krb5_pa_data **return_pa_data = NULL;
|
||||
|
||||
@@ -119,15 +119,10 @@ pa_pkinit_gen_req(krb5_context context,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
- retval = krb5_c_make_checksum(context, CKSUMTYPE_SHA1, NULL, 0, der_req,
|
||||
- &cksum);
|
||||
+ retval = crypto_generate_checksums(context, der_req, &cksum, &cksum2);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
- TRACE_PKINIT_CLIENT_REQ_CHECKSUM(context, &cksum);
|
||||
-#ifdef DEBUG_CKSUM
|
||||
- pkiDebug("calculating checksum on buf size (%d)\n", der_req->length);
|
||||
- print_buffer(der_req->data, der_req->length);
|
||||
-#endif
|
||||
+ TRACE_PKINIT_CLIENT_REQ_CHECKSUMS(context, &cksum, cksum2);
|
||||
|
||||
retval = cb->get_preauth_time(context, rock, TRUE, &ctsec, &cusec);
|
||||
if (retval)
|
||||
@@ -141,7 +136,8 @@ pa_pkinit_gen_req(krb5_context context,
|
||||
nonce = request->nonce;
|
||||
|
||||
retval = pkinit_as_req_create(context, plgctx, reqctx, ctsec, cusec,
|
||||
- nonce, &cksum, request->client, request->server, &out_data);
|
||||
+ nonce, &cksum, cksum2, request->client,
|
||||
+ request->server, &out_data);
|
||||
if (retval) {
|
||||
pkiDebug("error %d on pkinit_as_req_create; aborting PKINIT\n",
|
||||
(int) retval);
|
||||
@@ -169,23 +165,19 @@ pa_pkinit_gen_req(krb5_context context,
|
||||
|
||||
cleanup:
|
||||
krb5_free_data(context, der_req);
|
||||
- krb5_free_checksum_contents(context, &cksum);
|
||||
+ krb5_free_data_contents(context, &cksum);
|
||||
+ free_pachecksum2(context, &cksum2);
|
||||
krb5_free_data(context, out_data);
|
||||
krb5_free_pa_data(context, return_pa_data);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static krb5_error_code
|
||||
-pkinit_as_req_create(krb5_context context,
|
||||
- pkinit_context plgctx,
|
||||
- pkinit_req_context reqctx,
|
||||
- krb5_timestamp ctsec,
|
||||
- krb5_int32 cusec,
|
||||
- krb5_ui_4 nonce,
|
||||
- const krb5_checksum * cksum,
|
||||
- krb5_principal client,
|
||||
- krb5_principal server,
|
||||
- krb5_data ** as_req)
|
||||
+pkinit_as_req_create(krb5_context context, pkinit_context plgctx,
|
||||
+ pkinit_req_context reqctx, krb5_timestamp ctsec,
|
||||
+ krb5_int32 cusec, krb5_ui_4 nonce, const krb5_data *cksum,
|
||||
+ const krb5_pachecksum2 *cksum2, krb5_principal client,
|
||||
+ krb5_principal server, krb5_data **as_req)
|
||||
{
|
||||
krb5_error_code retval = ENOMEM;
|
||||
krb5_subject_pk_info info;
|
||||
@@ -207,6 +199,7 @@ pkinit_as_req_create(krb5_context context,
|
||||
auth_pack.pkAuthenticator.paChecksum = *cksum;
|
||||
if (!reqctx->opts->disable_freshness)
|
||||
auth_pack.pkAuthenticator.freshnessToken = reqctx->freshness_token;
|
||||
+ auth_pack.pkAuthenticator.paChecksum2 = (krb5_pachecksum2 *)cksum2;
|
||||
auth_pack.clientDHNonce.length = 0;
|
||||
auth_pack.clientPublicValue = &info;
|
||||
auth_pack.supportedKDFs = (krb5_data **)supported_kdf_alg_ids;
|
||||
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto.h b/src/plugins/preauth/pkinit/pkinit_crypto.h
|
||||
index f251e41064..d576cd6cef 100644
|
||||
--- a/src/plugins/preauth/pkinit/pkinit_crypto.h
|
||||
+++ b/src/plugins/preauth/pkinit/pkinit_crypto.h
|
||||
@@ -568,6 +568,10 @@ extern const krb5_octet krb5_pkinit_sha256_oid[];
|
||||
extern const size_t krb5_pkinit_sha256_oid_len;
|
||||
extern const krb5_octet krb5_pkinit_sha512_oid[];
|
||||
extern const size_t krb5_pkinit_sha512_oid_len;
|
||||
+extern const krb5_data cms_sha1_id;
|
||||
+extern const krb5_data cms_sha256_id;
|
||||
+extern const krb5_data cms_sha384_id;
|
||||
+extern const krb5_data cms_sha512_id;
|
||||
/**
|
||||
* An ordered set of OIDs, stored as krb5_data, of KDF algorithms
|
||||
* supported by this implementation. The order of this array controls
|
||||
@@ -585,4 +589,18 @@ crypto_req_cert_matching_data(krb5_context context,
|
||||
pkinit_req_crypto_context reqctx,
|
||||
pkinit_cert_matching_data **md_out);
|
||||
|
||||
+/* Generate a SHA-1 checksum over body in *cksum1_out and a SHA-256 checksum
|
||||
+ * over body in *cksum2_out with appropriate metadata. */
|
||||
+krb5_error_code
|
||||
+crypto_generate_checksums(krb5_context context, const krb5_data *body,
|
||||
+ krb5_data *cksum1_out,
|
||||
+ krb5_pachecksum2 **cksum2_out);
|
||||
+
|
||||
+/* Verify the SHA-1 checksum in cksum1 and the tagged checksum in cksum2.
|
||||
+ * cksum2 may be NULL, in which case only cksum1 is verified. */
|
||||
+krb5_error_code
|
||||
+crypto_verify_checksums(krb5_context context, krb5_data *body,
|
||||
+ const krb5_data *cksum1,
|
||||
+ const krb5_pachecksum2 *cksum2);
|
||||
+
|
||||
#endif /* _PKINIT_CRYPTO_H */
|
||||
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
||||
index 76ad7526bb..638971fe83 100644
|
||||
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
||||
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
||||
@@ -5413,3 +5413,113 @@ crypto_req_cert_matching_data(krb5_context context,
|
||||
return get_matching_data(context, plgctx, reqctx, reqctx->received_cert,
|
||||
md_out);
|
||||
}
|
||||
+
|
||||
+/* Return the OpenSSL message digest type matching the given CMS OID, or NULL
|
||||
+ * if it doesn't match any of the CMS OIDs we know about. */
|
||||
+static const EVP_MD *
|
||||
+md_from_cms_oid(const krb5_data *alg_id)
|
||||
+{
|
||||
+ if (data_eq(*alg_id, cms_sha1_id))
|
||||
+ return EVP_sha1();
|
||||
+ if (data_eq(*alg_id, cms_sha256_id))
|
||||
+ return EVP_sha256();
|
||||
+ if (data_eq(*alg_id, cms_sha384_id))
|
||||
+ return EVP_sha384();
|
||||
+ if (data_eq(*alg_id, cms_sha512_id))
|
||||
+ return EVP_sha512();
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+/* Compute a message digest of the given type over body, placing the result in
|
||||
+ * *digest_out in allocated storage. Return true on success. */
|
||||
+static krb5_boolean
|
||||
+make_digest(const krb5_data *body, const EVP_MD *md, krb5_data *digest_out)
|
||||
+{
|
||||
+ krb5_error_code ret;
|
||||
+ krb5_data d;
|
||||
+
|
||||
+ if (md == NULL)
|
||||
+ return FALSE;
|
||||
+ ret = alloc_data(&d, EVP_MD_size(md));
|
||||
+ if (ret)
|
||||
+ return FALSE;
|
||||
+ if (!EVP_Digest(body->data, body->length, (uint8_t *)d.data, &d.length, md,
|
||||
+ NULL)) {
|
||||
+ free(d.data);
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ *digest_out = d;
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
+/* Return true if digest verifies for the given body and message digest
|
||||
+ * type. */
|
||||
+static krb5_boolean
|
||||
+check_digest(const krb5_data *body, const EVP_MD *md, const krb5_data *digest)
|
||||
+{
|
||||
+ unsigned int digest_len;
|
||||
+ uint8_t buf[EVP_MAX_MD_SIZE];
|
||||
+
|
||||
+ if (md == NULL)
|
||||
+ return FALSE;
|
||||
+ if (!EVP_Digest(body->data, body->length, buf, &digest_len, md, NULL))
|
||||
+ return FALSE;
|
||||
+ return (digest->length == digest_len &&
|
||||
+ CRYPTO_memcmp(digest->data, buf, digest_len) == 0);
|
||||
+}
|
||||
+
|
||||
+krb5_error_code
|
||||
+crypto_generate_checksums(krb5_context context, const krb5_data *body,
|
||||
+ krb5_data *cksum1_out, krb5_pachecksum2 **cksum2_out)
|
||||
+{
|
||||
+ krb5_data cksum1 = empty_data();
|
||||
+ krb5_pachecksum2 *cksum2 = NULL;
|
||||
+ krb5_error_code ret;
|
||||
+
|
||||
+ if (!make_digest(body, EVP_sha1(), &cksum1))
|
||||
+ goto fail;
|
||||
+
|
||||
+ cksum2 = k5alloc(sizeof(*cksum2), &ret);
|
||||
+ if (cksum2 == NULL)
|
||||
+ goto fail;
|
||||
+
|
||||
+ if (!make_digest(body, EVP_sha256(), &cksum2->checksum))
|
||||
+ goto fail;
|
||||
+
|
||||
+ if (krb5int_copy_data_contents(context, &cms_sha256_id,
|
||||
+ &cksum2->algorithmIdentifier.algorithm))
|
||||
+ goto fail;
|
||||
+
|
||||
+ cksum2->algorithmIdentifier.parameters = empty_data();
|
||||
+
|
||||
+ *cksum1_out = cksum1;
|
||||
+ *cksum2_out = cksum2;
|
||||
+ return 0;
|
||||
+
|
||||
+fail:
|
||||
+ krb5_free_data_contents(context, &cksum1);
|
||||
+ free_pachecksum2(context, &cksum2);
|
||||
+ return KRB5_CRYPTO_INTERNAL;
|
||||
+}
|
||||
+
|
||||
+krb5_error_code
|
||||
+crypto_verify_checksums(krb5_context context, krb5_data *body,
|
||||
+ const krb5_data *cksum1,
|
||||
+ const krb5_pachecksum2 *cksum2)
|
||||
+{
|
||||
+ const EVP_MD *md;
|
||||
+
|
||||
+ /* RFC 4556 doesn't say what error to return if the checksum doesn't match.
|
||||
+ * Windows returns this one. */
|
||||
+ if (!check_digest(body, EVP_sha1(), cksum1))
|
||||
+ return KRB5KRB_AP_ERR_MODIFIED;
|
||||
+
|
||||
+ if (cksum2 == NULL)
|
||||
+ return 0;
|
||||
+
|
||||
+ md = md_from_cms_oid(&cksum2->algorithmIdentifier.algorithm);
|
||||
+ if (!check_digest(body, md, &cksum2->checksum))
|
||||
+ return KRB5KRB_AP_ERR_MODIFIED;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/src/plugins/preauth/pkinit/pkinit_kdf_constants.c b/src/plugins/preauth/pkinit/pkinit_kdf_constants.c
|
||||
index 1604f1670a..315fc36866 100644
|
||||
--- a/src/plugins/preauth/pkinit/pkinit_kdf_constants.c
|
||||
+++ b/src/plugins/preauth/pkinit/pkinit_kdf_constants.c
|
||||
@@ -57,3 +57,27 @@ krb5_data const * const supported_kdf_alg_ids[] = {
|
||||
&sha512_id,
|
||||
NULL
|
||||
};
|
||||
+
|
||||
+/* RFC 3370 sha-1: iso(1) identified-organization(3) oiw(14) secsig(3)
|
||||
+ * algorithm(2) 26 */
|
||||
+static char cms_sha1[] = { 0x2b, 0x0e, 0x03, 0x02, 0x1a };
|
||||
+/* RFC 5754 id-sha256: joint-iso-itu-t(2) country(16) us(840) organization(1)
|
||||
+ * gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 */
|
||||
+static char cms_sha256[] = {
|
||||
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
|
||||
+};
|
||||
+/* RFC 5754 id-sha384: joint-iso-itu-t(2) country(16) us(840) organization(1)
|
||||
+ * gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 */
|
||||
+static char cms_sha384[] = {
|
||||
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
|
||||
+};
|
||||
+/* RFC 5754 id-sha512: joint-iso-itu-t(2) country(16) us(840) organization(1)
|
||||
+ * gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 */
|
||||
+static char cms_sha512[] = {
|
||||
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
|
||||
+};
|
||||
+
|
||||
+const krb5_data cms_sha1_id = { KV5M_DATA, sizeof(cms_sha1), cms_sha1 };
|
||||
+const krb5_data cms_sha256_id = { KV5M_DATA, sizeof(cms_sha256), cms_sha256 };
|
||||
+const krb5_data cms_sha384_id = { KV5M_DATA, sizeof(cms_sha384), cms_sha384 };
|
||||
+const krb5_data cms_sha512_id = { KV5M_DATA, sizeof(cms_sha512), cms_sha512 };
|
||||
diff --git a/src/plugins/preauth/pkinit/pkinit_lib.c b/src/plugins/preauth/pkinit/pkinit_lib.c
|
||||
index 7af880bf5c..47972bb5eb 100644
|
||||
--- a/src/plugins/preauth/pkinit/pkinit_lib.c
|
||||
+++ b/src/plugins/preauth/pkinit/pkinit_lib.c
|
||||
@@ -29,6 +29,7 @@
|
||||
* SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
+#include "k5-int.h"
|
||||
#include "pkinit.h"
|
||||
|
||||
#define FAKECERT
|
||||
@@ -127,8 +128,9 @@ free_krb5_auth_pack(krb5_auth_pack **in)
|
||||
free((*in)->clientPublicValue->subjectPublicKey.data);
|
||||
free((*in)->clientPublicValue);
|
||||
}
|
||||
- free((*in)->pkAuthenticator.paChecksum.contents);
|
||||
+ free((*in)->pkAuthenticator.paChecksum.data);
|
||||
krb5_free_data(NULL, (*in)->pkAuthenticator.freshnessToken);
|
||||
+ free_pachecksum2(NULL, &(*in)->pkAuthenticator.paChecksum2);
|
||||
if ((*in)->supportedCMSTypes != NULL)
|
||||
free_krb5_algorithm_identifiers(&((*in)->supportedCMSTypes));
|
||||
if ((*in)->supportedKDFs) {
|
||||
@@ -213,6 +215,18 @@ free_krb5_kdc_dh_key_info(krb5_kdc_dh_key_info **in)
|
||||
free(*in);
|
||||
}
|
||||
|
||||
+void
|
||||
+free_pachecksum2(krb5_context context, krb5_pachecksum2 **in)
|
||||
+{
|
||||
+ if (*in == NULL)
|
||||
+ return;
|
||||
+ krb5_free_data_contents(context, &(*in)->checksum);
|
||||
+ krb5_free_data_contents(context, &(*in)->algorithmIdentifier.algorithm);
|
||||
+ krb5_free_data_contents(context, &(*in)->algorithmIdentifier.parameters);
|
||||
+ free(*in);
|
||||
+ *in = NULL;
|
||||
+}
|
||||
+
|
||||
void
|
||||
init_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in)
|
||||
{
|
||||
diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
|
||||
index 4eab5a2761..f5b3d98ef8 100644
|
||||
--- a/src/plugins/preauth/pkinit/pkinit_srv.c
|
||||
+++ b/src/plugins/preauth/pkinit/pkinit_srv.c
|
||||
@@ -426,11 +426,12 @@ pkinit_server_verify_padata(krb5_context context,
|
||||
krb5_data authp_data = {0, 0, NULL}, krb5_authz = {0, 0, NULL};
|
||||
krb5_pa_pk_as_req *reqp = NULL;
|
||||
krb5_auth_pack *auth_pack = NULL;
|
||||
+ krb5_pk_authenticator *pka;
|
||||
pkinit_kdc_context plgctx = NULL;
|
||||
pkinit_kdc_req_context reqctx = NULL;
|
||||
krb5_checksum cksum = {0, 0, 0, NULL};
|
||||
krb5_data *der_req = NULL;
|
||||
- krb5_data k5data, *ftoken;
|
||||
+ krb5_data k5data;
|
||||
int is_signed = 1;
|
||||
krb5_pa_data **e_data = NULL;
|
||||
krb5_kdcpreauth_modreq modreq = NULL;
|
||||
@@ -522,8 +523,9 @@ pkinit_server_verify_padata(krb5_context context,
|
||||
pkiDebug("failed to decode krb5_auth_pack\n");
|
||||
goto cleanup;
|
||||
}
|
||||
+ pka = &auth_pack->pkAuthenticator;
|
||||
|
||||
- retval = krb5_check_clockskew(context, auth_pack->pkAuthenticator.ctime);
|
||||
+ retval = krb5_check_clockskew(context, pka->ctime);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
|
||||
@@ -546,36 +548,13 @@ pkinit_server_verify_padata(krb5_context context,
|
||||
goto cleanup;
|
||||
}
|
||||
der_req = cb->request_body(context, rock);
|
||||
- retval = krb5_c_make_checksum(context, CKSUMTYPE_SHA1, NULL, 0, der_req,
|
||||
- &cksum);
|
||||
- if (retval) {
|
||||
- pkiDebug("unable to calculate AS REQ checksum\n");
|
||||
- goto cleanup;
|
||||
- }
|
||||
- if (cksum.length != auth_pack->pkAuthenticator.paChecksum.length ||
|
||||
- k5_bcmp(cksum.contents, auth_pack->pkAuthenticator.paChecksum.contents,
|
||||
- cksum.length) != 0) {
|
||||
- pkiDebug("failed to match the checksum\n");
|
||||
-#ifdef DEBUG_CKSUM
|
||||
- pkiDebug("calculating checksum on buf size (%d)\n", req_pkt->length);
|
||||
- print_buffer(req_pkt->data, req_pkt->length);
|
||||
- pkiDebug("received checksum type=%d size=%d ",
|
||||
- auth_pack->pkAuthenticator.paChecksum.checksum_type,
|
||||
- auth_pack->pkAuthenticator.paChecksum.length);
|
||||
- print_buffer(auth_pack->pkAuthenticator.paChecksum.contents,
|
||||
- auth_pack->pkAuthenticator.paChecksum.length);
|
||||
- pkiDebug("expected checksum type=%d size=%d ",
|
||||
- cksum.checksum_type, cksum.length);
|
||||
- print_buffer(cksum.contents, cksum.length);
|
||||
-#endif
|
||||
-
|
||||
- retval = KRB5KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED;
|
||||
+ retval = crypto_verify_checksums(context, der_req, &pka->paChecksum,
|
||||
+ pka->paChecksum2);
|
||||
+ if (retval)
|
||||
goto cleanup;
|
||||
- }
|
||||
|
||||
- ftoken = auth_pack->pkAuthenticator.freshnessToken;
|
||||
- if (ftoken != NULL) {
|
||||
- retval = cb->check_freshness_token(context, rock, ftoken);
|
||||
+ if (pka->freshnessToken != NULL) {
|
||||
+ retval = cb->check_freshness_token(context, rock, pka->freshnessToken);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
valid_freshness_token = TRUE;
|
||||
diff --git a/src/plugins/preauth/pkinit/pkinit_trace.h b/src/plugins/preauth/pkinit/pkinit_trace.h
|
||||
index 4f80e0b9b6..3017f9e059 100644
|
||||
--- a/src/plugins/preauth/pkinit/pkinit_trace.h
|
||||
+++ b/src/plugins/preauth/pkinit/pkinit_trace.h
|
||||
@@ -58,8 +58,9 @@
|
||||
TRACE(c, "PKINIT client verified DH reply")
|
||||
#define TRACE_PKINIT_CLIENT_REP_DH_FAIL(c) \
|
||||
TRACE(c, "PKINIT client could not verify DH reply")
|
||||
-#define TRACE_PKINIT_CLIENT_REQ_CHECKSUM(c, cksum) \
|
||||
- TRACE(c, "PKINIT client computed kdc-req-body checksum {cksum}", cksum)
|
||||
+#define TRACE_PKINIT_CLIENT_REQ_CHECKSUMS(c, ck1, ck2) \
|
||||
+ TRACE(c, "PKINIT client computed checksums: {hexdata} {hexdata}", \
|
||||
+ ck1, &(ck2)->checksum)
|
||||
#define TRACE_PKINIT_CLIENT_REQ_DH(c) \
|
||||
TRACE(c, "PKINIT client making DH request")
|
||||
#define TRACE_PKINIT_CLIENT_SAN_CONFIG_DNSNAME(c, host) \
|
||||
diff --git a/src/tests/asn.1/krb5_decode_test.c b/src/tests/asn.1/krb5_decode_test.c
|
||||
index 7a116b40d9..9946ebd3a5 100644
|
||||
--- a/src/tests/asn.1/krb5_decode_test.c
|
||||
+++ b/src/tests/asn.1/krb5_decode_test.c
|
||||
@@ -1173,7 +1173,7 @@ int main(argc, argv)
|
||||
/* decode_krb5_auth_pack */
|
||||
{
|
||||
setup(krb5_auth_pack,ktest_make_sample_auth_pack);
|
||||
- decode_run("krb5_auth_pack","","30 81 93 A0 29 30 27 A0 05 02 03 01 E2 40 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 06 04 04 31 32 33 34 A1 22 30 20 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 03 09 00 6B 72 62 35 64 61 74 61 A2 24 30 22 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 10 30 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61",
|
||||
+ decode_run("krb5_auth_pack","","30 81 97 A0 2D 30 2B A0 05 02 03 01 E2 40 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 0A 04 08 6B 72 62 35 64 61 74 61 A1 22 30 20 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 03 09 00 6B 72 62 35 64 61 74 61 A2 24 30 22 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 10 30 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61",
|
||||
acc.decode_krb5_auth_pack,
|
||||
ktest_equal_auth_pack,ktest_free_auth_pack);
|
||||
ktest_empty_auth_pack(&ref);
|
||||
diff --git a/src/tests/asn.1/ktest.c b/src/tests/asn.1/ktest.c
|
||||
index 7bb698732b..fc953ac9b7 100644
|
||||
--- a/src/tests/asn.1/ktest.c
|
||||
+++ b/src/tests/asn.1/ktest.c
|
||||
@@ -722,9 +722,7 @@ ktest_make_sample_pk_authenticator(krb5_pk_authenticator *p)
|
||||
p->cusec = SAMPLE_USEC;
|
||||
p->ctime = SAMPLE_TIME;
|
||||
p->nonce = SAMPLE_NONCE;
|
||||
- ktest_make_sample_checksum(&p->paChecksum);
|
||||
- /* We don't encode the checksum type, only the contents. */
|
||||
- p->paChecksum.checksum_type = 0;
|
||||
+ ktest_make_sample_data(&p->paChecksum);
|
||||
p->freshnessToken = ealloc(sizeof(krb5_data));
|
||||
ktest_make_sample_data(p->freshnessToken);
|
||||
}
|
||||
@@ -1666,8 +1664,7 @@ ktest_empty_pa_otp_req(krb5_pa_otp_req *p)
|
||||
static void
|
||||
ktest_empty_pk_authenticator(krb5_pk_authenticator *p)
|
||||
{
|
||||
- ktest_empty_checksum(&p->paChecksum);
|
||||
- p->paChecksum.contents = NULL;
|
||||
+ ktest_empty_data(&p->paChecksum);
|
||||
krb5_free_data(NULL, p->freshnessToken);
|
||||
p->freshnessToken = NULL;
|
||||
}
|
||||
diff --git a/src/tests/asn.1/ktest_equal.c b/src/tests/asn.1/ktest_equal.c
|
||||
index eed6872f9f..eec7a71601 100644
|
||||
--- a/src/tests/asn.1/ktest_equal.c
|
||||
+++ b/src/tests/asn.1/ktest_equal.c
|
||||
@@ -872,7 +872,7 @@ ktest_equal_pk_authenticator(krb5_pk_authenticator *ref,
|
||||
p = p && scalar_equal(cusec);
|
||||
p = p && scalar_equal(ctime);
|
||||
p = p && scalar_equal(nonce);
|
||||
- p = p && struct_equal(paChecksum, ktest_equal_checksum);
|
||||
+ p = p && data_eq(ref->paChecksum, var->paChecksum);
|
||||
return p;
|
||||
}
|
||||
|
||||
diff --git a/src/tests/asn.1/pkinit_encode.out b/src/tests/asn.1/pkinit_encode.out
|
||||
index 9bd08e159f..cab27cfb68 100644
|
||||
--- a/src/tests/asn.1/pkinit_encode.out
|
||||
+++ b/src/tests/asn.1/pkinit_encode.out
|
||||
@@ -1,7 +1,7 @@
|
||||
encode_krb5_pa_pk_as_req: 30 38 80 08 6B 72 62 35 64 61 74 61 A1 22 30 20 30 1E 80 08 6B 72 62 35 64 61 74 61 81 08 6B 72 62 35 64 61 74 61 82 08 6B 72 62 35 64 61 74 61 82 08 6B 72 62 35 64 61 74 61
|
||||
encode_krb5_pa_pk_as_rep(dhInfo): A0 28 30 26 80 08 6B 72 62 35 64 61 74 61 A1 0A 04 08 6B 72 62 35 64 61 74 61 A2 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61
|
||||
encode_krb5_pa_pk_as_rep(encKeyPack): 81 08 6B 72 62 35 64 61 74 61
|
||||
-encode_krb5_auth_pack: 30 81 9F A0 35 30 33 A0 05 02 03 01 E2 40 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 06 04 04 31 32 33 34 A4 0A 04 08 6B 72 62 35 64 61 74 61 A1 22 30 20 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 03 09 00 6B 72 62 35 64 61 74 61 A2 24 30 22 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 10 30 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61
|
||||
+encode_krb5_auth_pack: 30 81 A3 A0 39 30 37 A0 05 02 03 01 E2 40 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 0A 04 08 6B 72 62 35 64 61 74 61 A1 22 30 20 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 03 09 00 6B 72 62 35 64 61 74 61 A2 24 30 22 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 10 30 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61
|
||||
encode_krb5_kdc_dh_key_info: 30 25 A0 0B 03 09 00 6B 72 62 35 64 61 74 61 A1 03 02 01 2A A2 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A
|
||||
encode_krb5_reply_key_pack: 30 26 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34
|
||||
encode_krb5_sp80056a_other_info: 30 81 81 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A0 32 04 30 30 2E A0 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A1 32 04 30 30 2E A0 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 0A 04 08 6B 72 62 35 64 61 74 61
|
||||
diff --git a/src/tests/asn.1/pkinit_trval.out b/src/tests/asn.1/pkinit_trval.out
|
||||
index 3675fba386..047dec842e 100644
|
||||
--- a/src/tests/asn.1/pkinit_trval.out
|
||||
+++ b/src/tests/asn.1/pkinit_trval.out
|
||||
@@ -38,7 +38,7 @@ encode_krb5_auth_pack:
|
||||
. . [0] [Integer] 123456
|
||||
. . [1] [Generalized Time] "19940610060317Z"
|
||||
. . [2] [Integer] 42
|
||||
-. . [3] [Octet String] "1234"
|
||||
+. . [3] [Octet String] "krb5data"
|
||||
. . [4] [Octet String] "krb5data"
|
||||
. [1] [Sequence/Sequence Of]
|
||||
. . [Sequence/Sequence Of]
|
||||
--
|
||||
2.49.0
|
||||
|
||||
374
SOURCES/Don-t-issue-session-keys-with-deprecated-enctypes.patch
Normal file
374
SOURCES/Don-t-issue-session-keys-with-deprecated-enctypes.patch
Normal file
@ -0,0 +1,374 @@
|
||||
From bf57cb193ef7180bb01c8e307258ee6ac93d9b8f Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Fri, 16 Dec 2022 18:31:07 -0500
|
||||
Subject: [PATCH] Don't issue session keys with deprecated enctypes
|
||||
|
||||
A paper by Tom Tervoort noted that rc4-hmac pre-hashes the input for
|
||||
its checksum and GSS operations before applying HMAC, and is therefore
|
||||
potentially vulnerable to hash collision attacks if a protocol
|
||||
contains a restricted signing oracle.
|
||||
|
||||
In light of these potential attacks, begin the functional deprecation
|
||||
of DES3 and RC4 by disallowing their use as session key enctypes by
|
||||
default. Add the variables allow_des3 and allow_rc4 in case
|
||||
negotiability of these enctypes for session keys needs to be turned
|
||||
back on, with the expectation that in future releases the enctypes
|
||||
will be more comprehensively deprecated.
|
||||
|
||||
ticket: 9081
|
||||
(cherry picked from commit 1b57a4d134bbd0e7c52d5885a92eccc815726463)
|
||||
---
|
||||
doc/admin/conf_files/krb5_conf.rst | 12 +++++
|
||||
doc/admin/enctypes.rst | 23 ++++++--
|
||||
src/include/k5-int.h | 4 ++
|
||||
src/kdc/kdc_util.c | 10 ++++
|
||||
src/lib/krb5/krb/get_in_tkt.c | 85 ++++++++++++++++++++++++++++++
|
||||
src/lib/krb5/krb/init_ctx.c | 10 ++++
|
||||
src/tests/gssapi/t_enctypes.py | 5 +-
|
||||
src/tests/t_etype_info.py | 4 +-
|
||||
src/tests/t_sesskeynego.py | 28 +++++++++-
|
||||
src/util/k5test.py | 9 +++-
|
||||
10 files changed, 180 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
|
||||
index 98fe231813..c77a9fd46d 100644
|
||||
--- a/doc/admin/conf_files/krb5_conf.rst
|
||||
+++ b/doc/admin/conf_files/krb5_conf.rst
|
||||
@@ -95,6 +95,18 @@ Additionally, krb5.conf may include any of the relations described in
|
||||
|
||||
The libdefaults section may contain any of the following relations:
|
||||
|
||||
+**allow_des3**
|
||||
+ Permit the KDC to issue tickets with des3-cbc-sha1 session keys.
|
||||
+ In future releases, this flag will allow des3-cbc-sha1 to be used
|
||||
+ at all. The default value for this tag is false. (Added in
|
||||
+ release 1.21.)
|
||||
+
|
||||
+**allow_rc4**
|
||||
+ Permit the KDC to issue tickets with arcfour-hmac session keys.
|
||||
+ In future releases, this flag will allow arcfour-hmac to be used
|
||||
+ at all. The default value for this tag is false. (Added in
|
||||
+ release 1.21.)
|
||||
+
|
||||
**allow_weak_crypto**
|
||||
If this flag is set to false, then weak encryption types (as noted
|
||||
in :ref:`Encryption_types` in :ref:`kdc.conf(5)`) will be filtered
|
||||
diff --git a/doc/admin/enctypes.rst b/doc/admin/enctypes.rst
|
||||
index 65b55cdb9d..76ef2a2133 100644
|
||||
--- a/doc/admin/enctypes.rst
|
||||
+++ b/doc/admin/enctypes.rst
|
||||
@@ -48,12 +48,15 @@ Session key selection
|
||||
The KDC chooses the session key enctype by taking the intersection of
|
||||
its **permitted_enctypes** list, the list of long-term keys for the
|
||||
most recent kvno of the service, and the client's requested list of
|
||||
-enctypes.
|
||||
+enctypes. Starting in krb5-1.21, all services are assumed to support
|
||||
+aes256-cts-hmac-sha1-96; also, des3-cbc-sha1 and arcfour-hmac session
|
||||
+keys will not be issued by default.
|
||||
|
||||
Starting in krb5-1.11, it is possible to set a string attribute on a
|
||||
service principal to control what session key enctypes the KDC may
|
||||
-issue for service tickets for that principal. See :ref:`set_string`
|
||||
-in :ref:`kadmin(1)` for details.
|
||||
+issue for service tickets for that principal, overriding the service's
|
||||
+long-term keys and the assumption of aes256-cts-hmac-sha1-96 support.
|
||||
+See :ref:`set_string` in :ref:`kadmin(1)` for details.
|
||||
|
||||
|
||||
Choosing enctypes for a service
|
||||
@@ -87,6 +90,20 @@ affect how enctypes are chosen.
|
||||
acceptable risk for your environment and the weak enctypes are
|
||||
required for backward compatibility.
|
||||
|
||||
+**allow_des3**
|
||||
+ was added in release 1.21 and defaults to *false*. Unless this
|
||||
+ flag is set to *true*, the KDC will not issue tickets with
|
||||
+ des3-cbc-sha1 session keys. In a future release, this flag will
|
||||
+ control whether des3-cbc-sha1 is permitted in similar fashion to
|
||||
+ weak enctypes.
|
||||
+
|
||||
+**allow_rc4**
|
||||
+ was added in release 1.21 and defaults to *false*. Unless this
|
||||
+ flag is set to *true*, the KDC will not issue tickets with
|
||||
+ arcfour-hmac session keys. In a future release, this flag will
|
||||
+ control whether arcfour-hmac is permitted in similar fashion to
|
||||
+ weak enctypes.
|
||||
+
|
||||
**permitted_enctypes**
|
||||
controls the set of enctypes that a service will permit for
|
||||
session keys and for ticket and authenticator encryption. The KDC
|
||||
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
|
||||
index d062617268..c3d081fd30 100644
|
||||
--- a/src/include/k5-int.h
|
||||
+++ b/src/include/k5-int.h
|
||||
@@ -181,6 +181,8 @@ typedef unsigned char u_char;
|
||||
* matches the variable name. Keep these alphabetized. */
|
||||
#define KRB5_CONF_ACL_FILE "acl_file"
|
||||
#define KRB5_CONF_ADMIN_SERVER "admin_server"
|
||||
+#define KRB5_CONF_ALLOW_DES3 "allow_des3"
|
||||
+#define KRB5_CONF_ALLOW_RC4 "allow_rc4"
|
||||
#define KRB5_CONF_ALLOW_WEAK_CRYPTO "allow_weak_crypto"
|
||||
#define KRB5_CONF_AUTH_TO_LOCAL "auth_to_local"
|
||||
#define KRB5_CONF_AUTH_TO_LOCAL_NAMES "auth_to_local_names"
|
||||
@@ -1259,6 +1261,8 @@ struct _krb5_context {
|
||||
struct _kdb_log_context *kdblog_context;
|
||||
|
||||
krb5_boolean allow_weak_crypto;
|
||||
+ krb5_boolean allow_des3;
|
||||
+ krb5_boolean allow_rc4;
|
||||
krb5_boolean ignore_acceptor_hostname;
|
||||
krb5_boolean enforce_ok_as_delegate;
|
||||
enum dns_canonhost dns_canonicalize_hostname;
|
||||
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
|
||||
index 23aadb88e9..b081d8e439 100644
|
||||
--- a/src/kdc/kdc_util.c
|
||||
+++ b/src/kdc/kdc_util.c
|
||||
@@ -1041,6 +1041,16 @@ select_session_keytype(kdc_realm_t *kdc_active_realm, krb5_db_entry *server,
|
||||
if (!krb5_is_permitted_enctype(kdc_context, ktype[i]))
|
||||
continue;
|
||||
|
||||
+ /*
|
||||
+ * Prevent these deprecated enctypes from being used as session keys
|
||||
+ * unless they are explicitly allowed. In the future they will be more
|
||||
+ * comprehensively disabled and eventually removed.
|
||||
+ */
|
||||
+ if (ktype[i] == ENCTYPE_DES3_CBC_SHA1 && !kdc_context->allow_des3)
|
||||
+ continue;
|
||||
+ if (ktype[i] == ENCTYPE_ARCFOUR_HMAC && !kdc_context->allow_rc4)
|
||||
+ continue;
|
||||
+
|
||||
if (dbentry_supports_enctype(kdc_active_realm, server, ktype[i]))
|
||||
return ktype[i];
|
||||
}
|
||||
diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
|
||||
index f5dd7518b0..322fc94892 100644
|
||||
--- a/src/lib/krb5/krb/get_in_tkt.c
|
||||
+++ b/src/lib/krb5/krb/get_in_tkt.c
|
||||
@@ -1592,6 +1592,90 @@ warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options,
|
||||
(*prompter)(context, data, 0, banner, 0, 0);
|
||||
}
|
||||
|
||||
+/* Display a warning via the prompter if a deprecated enctype was used for
|
||||
+ * either the reply key or the session key. */
|
||||
+static void
|
||||
+warn_deprecated(krb5_context context, krb5_init_creds_context ctx,
|
||||
+ krb5_enctype as_key_enctype)
|
||||
+{
|
||||
+ krb5_enctype etype;
|
||||
+ char encbuf[128], banner[256];
|
||||
+
|
||||
+ if (ctx->prompter == NULL)
|
||||
+ return;
|
||||
+
|
||||
+ if (krb5int_c_deprecated_enctype(as_key_enctype))
|
||||
+ etype = as_key_enctype;
|
||||
+ else if (krb5int_c_deprecated_enctype(ctx->cred.keyblock.enctype))
|
||||
+ etype = ctx->cred.keyblock.enctype;
|
||||
+ else
|
||||
+ return;
|
||||
+
|
||||
+ if (krb5_enctype_to_name(etype, FALSE, encbuf, sizeof(encbuf)) != 0)
|
||||
+ return;
|
||||
+ snprintf(banner, sizeof(banner),
|
||||
+ _("Warning: encryption type %s used for authentication is "
|
||||
+ "deprecated and will be disabled"), encbuf);
|
||||
+
|
||||
+ /* PROMPTER_INVOCATION */
|
||||
+ (*ctx->prompter)(context, ctx->prompter_data, NULL, banner, 0, NULL);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * If ctx specifies an output ccache, create or refresh it (atomically, if
|
||||
+ * possible) with the obtained credential and any appropriate ccache
|
||||
+ * configuration.
|
||||
+ */
|
||||
+static krb5_error_code
|
||||
+write_out_ccache(krb5_context context, krb5_init_creds_context ctx,
|
||||
+ krb5_boolean fast_avail)
|
||||
+{
|
||||
+ krb5_error_code ret;
|
||||
+ krb5_ccache out_ccache = k5_gic_opt_get_out_ccache(ctx->opt);
|
||||
+ krb5_ccache mcc = NULL;
|
||||
+ krb5_data yes = string2data("yes");
|
||||
+
|
||||
+ if (out_ccache == NULL)
|
||||
+ return 0;
|
||||
+
|
||||
+ ret = krb5_cc_new_unique(context, "MEMORY", NULL, &mcc);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ ret = krb5_cc_initialize(context, mcc, ctx->cred.client);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ if (fast_avail) {
|
||||
+ ret = krb5_cc_set_config(context, mcc, ctx->cred.server,
|
||||
+ KRB5_CC_CONF_FAST_AVAIL, &yes);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ ret = save_selected_preauth_type(context, mcc, ctx);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ ret = save_cc_config_out_data(context, mcc, ctx);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ ret = k5_cc_store_primary_cred(context, mcc, &ctx->cred);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ ret = krb5_cc_move(context, mcc, out_ccache);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+ mcc = NULL;
|
||||
+
|
||||
+cleanup:
|
||||
+ if (mcc != NULL)
|
||||
+ krb5_cc_destroy(context, mcc);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static krb5_error_code
|
||||
init_creds_step_reply(krb5_context context,
|
||||
krb5_init_creds_context ctx,
|
||||
@@ -1805,6 +1889,7 @@ init_creds_step_reply(krb5_context context,
|
||||
ctx->complete = TRUE;
|
||||
warn_pw_expiry(context, ctx->opt, ctx->prompter, ctx->prompter_data,
|
||||
ctx->in_tkt_service, ctx->reply);
|
||||
+ warn_deprecated(context, ctx, encrypting_key.enctype);
|
||||
|
||||
cleanup:
|
||||
krb5_free_pa_data(context, kdc_padata);
|
||||
diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c
|
||||
index 1a6e0bf672..4b23738817 100644
|
||||
--- a/src/lib/krb5/krb/init_ctx.c
|
||||
+++ b/src/lib/krb5/krb/init_ctx.c
|
||||
@@ -226,6 +226,16 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
|
||||
goto cleanup;
|
||||
ctx->allow_weak_crypto = tmp;
|
||||
|
||||
+ retval = get_boolean(ctx, KRB5_CONF_ALLOW_DES3, 0, &tmp);
|
||||
+ if (retval)
|
||||
+ goto cleanup;
|
||||
+ ctx->allow_des3 = tmp;
|
||||
+
|
||||
+ retval = get_boolean(ctx, KRB5_CONF_ALLOW_RC4, 0, &tmp);
|
||||
+ if (retval)
|
||||
+ goto cleanup;
|
||||
+ ctx->allow_rc4 = tmp;
|
||||
+
|
||||
retval = get_boolean(ctx, KRB5_CONF_IGNORE_ACCEPTOR_HOSTNAME, 0, &tmp);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
diff --git a/src/tests/gssapi/t_enctypes.py b/src/tests/gssapi/t_enctypes.py
|
||||
index 2f95d89967..e6bde47afc 100755
|
||||
--- a/src/tests/gssapi/t_enctypes.py
|
||||
+++ b/src/tests/gssapi/t_enctypes.py
|
||||
@@ -10,8 +10,9 @@ d_rc4 = 'DEPRECATED:arcfour-hmac'
|
||||
|
||||
# These tests make assumptions about the default enctype lists, so set
|
||||
# them explicitly rather than relying on the library defaults.
|
||||
-supp='aes256-cts:normal aes128-cts:normal rc4-hmac:normal'
|
||||
-conf = {'libdefaults': {'permitted_enctypes': 'aes rc4'},
|
||||
+supp='aes256-cts:normal aes128-cts:normal des3-cbc-sha1:normal rc4-hmac:normal'
|
||||
+conf = {'libdefaults': {'permitted_enctypes': 'aes des3 rc4',
|
||||
+ 'allow_des3': 'true', 'allow_rc4': 'true'},
|
||||
'realms': {'$realm': {'supported_enctypes': supp}}}
|
||||
realm = K5Realm(krb5_conf=conf)
|
||||
shutil.copyfile(realm.ccache, os.path.join(realm.testdir, 'save'))
|
||||
diff --git a/src/tests/t_etype_info.py b/src/tests/t_etype_info.py
|
||||
index ace0edc3c4..9ea5ca6228 100644
|
||||
--- a/src/tests/t_etype_info.py
|
||||
+++ b/src/tests/t_etype_info.py
|
||||
@@ -1,7 +1,7 @@
|
||||
from k5test import *
|
||||
|
||||
-supported_enctypes = 'aes128-cts rc4-hmac'
|
||||
-conf = {'libdefaults': {'allow_weak_crypto': 'true'},
|
||||
+supported_enctypes = 'aes128-cts des3-cbc-sha1 rc4-hmac'
|
||||
+conf = {'libdefaults': {'allow_des3': 'true', 'allow_rc4': 'true'},
|
||||
'realms': {'$realm': {'supported_enctypes': supported_enctypes}}}
|
||||
realm = K5Realm(create_host=False, get_creds=False, krb5_conf=conf)
|
||||
|
||||
diff --git a/src/tests/t_sesskeynego.py b/src/tests/t_sesskeynego.py
|
||||
index 73a55366c4..f30d0bc16c 100755
|
||||
--- a/src/tests/t_sesskeynego.py
|
||||
+++ b/src/tests/t_sesskeynego.py
|
||||
@@ -25,6 +25,8 @@ conf3 = {'libdefaults': {
|
||||
'default_tkt_enctypes': 'aes128-cts',
|
||||
'default_tgs_enctypes': 'rc4-hmac,aes128-cts'}}
|
||||
conf4 = {'libdefaults': {'permitted_enctypes': 'aes256-cts'}}
|
||||
+conf5 = {'libdefaults': {'allow_rc4': 'true'}}
|
||||
+conf6 = {'libdefaults': {'allow_des3': 'true'}}
|
||||
# Test with client request and session_enctypes preferring aes128, but
|
||||
# aes256 long-term key.
|
||||
realm = K5Realm(krb5_conf=conf1, create_host=False, get_creds=False)
|
||||
@@ -54,10 +56,12 @@ realm.run([kadminl, 'setstr', 'server', 'session_enctypes',
|
||||
'aes128-cts,aes256-cts'])
|
||||
test_kvno(realm, 'aes128-cts-hmac-sha1-96', 'aes256-cts-hmac-sha1-96')
|
||||
|
||||
-# 3b: Negotiate rc4-hmac session key when principal only has aes256 long-term.
|
||||
+# 3b: Skip RC4 (as the KDC does not allow it for session keys by
|
||||
+# default) and negotiate aes128-cts session key, with only an aes256
|
||||
+# long-term service key.
|
||||
realm.run([kadminl, 'setstr', 'server', 'session_enctypes',
|
||||
'rc4-hmac,aes128-cts,aes256-cts'])
|
||||
-test_kvno(realm, 'DEPRECATED:arcfour-hmac', 'aes256-cts-hmac-sha1-96')
|
||||
+test_kvno(realm, 'aes128-cts-hmac-sha1-96', 'aes256-cts-hmac-sha1-96')
|
||||
realm.stop()
|
||||
|
||||
# 4: Check that permitted_enctypes is a default for session key enctypes.
|
||||
@@ -67,4 +71,24 @@ realm.run([kvno, 'user'],
|
||||
expected_trace=('etypes requested in TGS request: aes256-cts',))
|
||||
realm.stop()
|
||||
|
||||
+# 5: allow_rc4 permits negotiation of rc4-hmac session key.
|
||||
+realm = K5Realm(krb5_conf=conf5, create_host=False, get_creds=False)
|
||||
+realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts', 'server'])
|
||||
+realm.run([kadminl, 'setstr', 'server', 'session_enctypes', 'rc4-hmac'])
|
||||
+test_kvno(realm, 'DEPRECATED:arcfour-hmac', 'aes256-cts-hmac-sha1-96')
|
||||
+realm.stop()
|
||||
+
|
||||
+# 6: allow_des3 permits negotiation of des3-cbc-sha1 session key.
|
||||
+realm = K5Realm(krb5_conf=conf6, create_host=False, get_creds=False)
|
||||
+realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts', 'server'])
|
||||
+realm.run([kadminl, 'setstr', 'server', 'session_enctypes', 'des3-cbc-sha1'])
|
||||
+test_kvno(realm, 'DEPRECATED:des3-cbc-sha1', 'aes256-cts-hmac-sha1-96')
|
||||
+realm.stop()
|
||||
+
|
||||
+# 7: default config negotiates aes256-sha1 session key for RC4-only service.
|
||||
+realm = K5Realm(create_host=False, get_creds=False)
|
||||
+realm.run([kadminl, 'addprinc', '-randkey', '-e', 'rc4-hmac', 'server'])
|
||||
+test_kvno(realm, 'aes256-cts-hmac-sha1-96', 'DEPRECATED:arcfour-hmac')
|
||||
+realm.stop()
|
||||
+
|
||||
success('sesskeynego')
|
||||
diff --git a/src/util/k5test.py b/src/util/k5test.py
|
||||
index eea92275d7..96474cc5aa 100644
|
||||
--- a/src/util/k5test.py
|
||||
+++ b/src/util/k5test.py
|
||||
@@ -1299,9 +1299,16 @@ _passes = [
|
||||
# No special settings; exercises AES256.
|
||||
('default', None, None, None),
|
||||
|
||||
+ # Exercise the DES3 enctype.
|
||||
+ ('des3', None,
|
||||
+ {'libdefaults': {'permitted_enctypes': 'des3 aes256-sha1'}},
|
||||
+ {'realms': {'$realm': {
|
||||
+ 'supported_enctypes': 'des3-cbc-sha1:normal',
|
||||
+ 'master_key_type': 'des3-cbc-sha1'}}}),
|
||||
+
|
||||
# Exercise the arcfour enctype.
|
||||
('arcfour', None,
|
||||
- {'libdefaults': {'permitted_enctypes': 'rc4'}},
|
||||
+ {'libdefaults': {'permitted_enctypes': 'rc4 aes256-sha1'}},
|
||||
{'realms': {'$realm': {
|
||||
'supported_enctypes': 'arcfour-hmac:normal',
|
||||
'master_key_type': 'arcfour-hmac'}}}),
|
||||
--
|
||||
2.49.0
|
||||
|
||||
51
SOURCES/In-KDC-assume-all-services-support-aes256-sha1.patch
Normal file
51
SOURCES/In-KDC-assume-all-services-support-aes256-sha1.patch
Normal file
@ -0,0 +1,51 @@
|
||||
From 5b67abf41026a420974f2d938c3e42d7f072abe5 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Hudson <ghudson@mit.edu>
|
||||
Date: Wed, 14 Dec 2022 13:20:46 -0500
|
||||
Subject: [PATCH] In KDC, assume all services support aes256-sha1
|
||||
|
||||
To facilitate negotiating session keys with acceptable security,
|
||||
assume that services support aes256-cts-hmac-sha1 unless a
|
||||
session_enctypes string attribute says otherwise.
|
||||
|
||||
ticket: 9075
|
||||
(cherry picked from commit 2cbd847e0e92bc4e219b65c770ae33f851b22afc)
|
||||
---
|
||||
src/kdc/kdc_util.c | 4 ++++
|
||||
src/tests/t_keyrollover.py | 6 +++---
|
||||
2 files changed, 7 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
|
||||
index e3352f9cc6..23aadb88e9 100644
|
||||
--- a/src/kdc/kdc_util.c
|
||||
+++ b/src/kdc/kdc_util.c
|
||||
@@ -1015,6 +1015,10 @@ dbentry_supports_enctype(kdc_realm_t *kdc_active_realm, krb5_db_entry *server,
|
||||
free(etypes_str);
|
||||
free(etypes);
|
||||
|
||||
+ /* Assume every server without a session_enctypes attribute supports
|
||||
+ * aes256-cts-hmac-sha1-96. */
|
||||
+ if (enctype == ENCTYPE_AES256_CTS_HMAC_SHA1_96)
|
||||
+ return TRUE;
|
||||
/* Assume the server supports any enctype it has a long-term key for. */
|
||||
return !krb5_dbe_find_enctype(kdc_context, server, enctype, -1, 0, &datap);
|
||||
}
|
||||
diff --git a/src/tests/t_keyrollover.py b/src/tests/t_keyrollover.py
|
||||
index f29e0d5500..583c2fa27e 100755
|
||||
--- a/src/tests/t_keyrollover.py
|
||||
+++ b/src/tests/t_keyrollover.py
|
||||
@@ -22,9 +22,9 @@ realm.run([kvno, princ1])
|
||||
realm.run([kadminl, 'purgekeys', realm.krbtgt_princ])
|
||||
# Make sure an old TGT fails after purging old TGS key.
|
||||
realm.run([kvno, princ2], expected_code=1)
|
||||
-et = "aes128-cts-hmac-sha256-128"
|
||||
-msg = 'krbtgt/%s@%s\n\tEtype (skey, tkt): %s, %s' % \
|
||||
- (realm.realm, realm.realm, et, et)
|
||||
+msg = 'krbtgt/%s@%s\n\tEtype (skey, tkt): ' \
|
||||
+ 'aes256-cts-hmac-sha1-96, aes128-cts-hmac-sha256-128' % \
|
||||
+ (realm.realm, realm.realm)
|
||||
realm.run([klist, '-e'], expected_msg=msg)
|
||||
|
||||
# Check that new key actually works.
|
||||
--
|
||||
2.49.0
|
||||
|
||||
157
SOURCES/downstream-Do-not-block-HMAC-MD4-5-in-FIPS-mode.patch
Normal file
157
SOURCES/downstream-Do-not-block-HMAC-MD4-5-in-FIPS-mode.patch
Normal file
@ -0,0 +1,157 @@
|
||||
From 400c8d5253a81c2bc220dc158a4f60ab7dbc5951 Mon Sep 17 00:00:00 2001
|
||||
From: Julien Rische <jrische@redhat.com>
|
||||
Date: Thu, 24 Apr 2025 15:56:32 +0200
|
||||
Subject: [PATCH] [downstream] Do not block HMAC-MD4/5 in FIPS mode
|
||||
|
||||
To ensure RC4 HMAC-MD5 was not used in FIPS mode, access to HMAC-MD4/5
|
||||
was not allowed in this mode. However, since we provide the
|
||||
"radius_md5_fips_override" configuration parameter to allow using RADIUS
|
||||
regardless to the FIPS restrictions, we should allow HMAC-MD5 to be used
|
||||
too in this case, because it is required for the newly supported
|
||||
Message-Authenticator attribute.
|
||||
|
||||
A FIPS mode check is added in calculate_mac() which will fail if
|
||||
"radius_md5_fips_override" is not true. It will not affect interactions
|
||||
between krb5kdc and ipa-otpd, because the Message-Authenticator
|
||||
attribute is not generated in this case.
|
||||
|
||||
This C8S patch does not include the code for loading the OpenSSL default
|
||||
and legacy providers in a library context. A flag is enough to unblock
|
||||
MD5 and HMAC-MD5 in FIPS mode on C8S, contrary to C9S and C10S.
|
||||
---
|
||||
src/lib/crypto/openssl/hmac.c | 19 +++++++++++--------
|
||||
src/lib/krad/packet.c | 19 ++++++++++++-------
|
||||
2 files changed, 23 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/src/lib/crypto/openssl/hmac.c b/src/lib/crypto/openssl/hmac.c
|
||||
index 769a50c007..5814328e3c 100644
|
||||
--- a/src/lib/crypto/openssl/hmac.c
|
||||
+++ b/src/lib/crypto/openssl/hmac.c
|
||||
@@ -103,11 +103,7 @@ map_digest(const struct krb5_hash_provider *hash)
|
||||
return EVP_sha256();
|
||||
else if (!strncmp(hash->hash_name, "SHA-384",7))
|
||||
return EVP_sha384();
|
||||
-
|
||||
- if (FIPS_mode())
|
||||
- return NULL;
|
||||
-
|
||||
- if (!strncmp(hash->hash_name, "MD5", 3))
|
||||
+ else if (!strncmp(hash->hash_name, "MD5", 3))
|
||||
return EVP_md5();
|
||||
else if (!strncmp(hash->hash_name, "MD4", 3))
|
||||
return EVP_md4();
|
||||
@@ -125,6 +121,7 @@ krb5int_hmac_keyblock(const struct krb5_hash_provider *hash,
|
||||
unsigned char md[EVP_MAX_MD_SIZE];
|
||||
HMAC_CTX *ctx;
|
||||
size_t hashsize, blocksize;
|
||||
+ const EVP_MD *md_alg;
|
||||
|
||||
hashsize = hash->hashsize;
|
||||
blocksize = hash->blocksize;
|
||||
@@ -134,15 +131,21 @@ krb5int_hmac_keyblock(const struct krb5_hash_provider *hash,
|
||||
if (output->length < hashsize)
|
||||
return(KRB5_BAD_MSIZE);
|
||||
|
||||
- if (!map_digest(hash))
|
||||
+ md_alg = map_digest(hash);
|
||||
+ if (!md_alg)
|
||||
return(KRB5_CRYPTO_INTERNAL); // unsupported alg
|
||||
|
||||
ctx = HMAC_CTX_new();
|
||||
if (ctx == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
- ok = HMAC_Init_ex(ctx, keyblock->contents, keyblock->length,
|
||||
- map_digest(hash), NULL);
|
||||
+ if (md_alg == EVP_md4() || md_alg == EVP_md5()) {
|
||||
+ /* HMAC-MD5 and HMAC-MD4 are blocked by default in FIPS mode,
|
||||
+ * but needed to support RADIUS Message-Authenticator. */
|
||||
+ HMAC_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
|
||||
+ }
|
||||
+
|
||||
+ ok = HMAC_Init_ex(ctx, keyblock->contents, keyblock->length, md_alg, NULL);
|
||||
for (i = 0; ok && i < num_data; i++) {
|
||||
const krb5_crypto_iov *iov = &data[i];
|
||||
|
||||
diff --git a/src/lib/krad/packet.c b/src/lib/krad/packet.c
|
||||
index 257bbc6345..b1a31d78cc 100644
|
||||
--- a/src/lib/krad/packet.c
|
||||
+++ b/src/lib/krad/packet.c
|
||||
@@ -278,7 +278,7 @@ lookup_msgauth_addr(const krad_packet *pkt)
|
||||
* auth, which may be from pkt or from a corresponding request.
|
||||
*/
|
||||
static krb5_error_code
|
||||
-calculate_mac(const char *secret, const krad_packet *pkt,
|
||||
+calculate_mac(krb5_context ctx, const char *secret, const krad_packet *pkt,
|
||||
const uint8_t auth[AUTH_FIELD_SIZE],
|
||||
uint8_t mac_out[MD5_DIGEST_SIZE])
|
||||
{
|
||||
@@ -288,6 +288,10 @@ calculate_mac(const char *secret, const krad_packet *pkt,
|
||||
krb5_crypto_iov input[5];
|
||||
krb5_data ksecr, mac;
|
||||
|
||||
+ /* Do not use HMAC-MD5 if not explicitly allowed */
|
||||
+ if (kr_use_fips(ctx))
|
||||
+ return KRB5_CRYPTO_INTERNAL;
|
||||
+
|
||||
msgauth_attr = lookup_msgauth_addr(pkt);
|
||||
if (msgauth_attr == NULL)
|
||||
return EINVAL;
|
||||
@@ -393,7 +397,8 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code,
|
||||
|
||||
if (msgauth_required) {
|
||||
/* Calculate and set the Message-Authenticator MAC. */
|
||||
- retval = calculate_mac(secret, pkt, pkt_auth(pkt), pkt_attr(pkt) + 2);
|
||||
+ retval = calculate_mac(ctx, secret, pkt, pkt_auth(pkt),
|
||||
+ pkt_attr(pkt) + 2);
|
||||
if (retval != 0)
|
||||
goto error;
|
||||
}
|
||||
@@ -454,7 +459,7 @@ krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code,
|
||||
* section 5.14, use the authenticator from the request, not from the
|
||||
* response.
|
||||
*/
|
||||
- retval = calculate_mac(secret, pkt, pkt_auth(request),
|
||||
+ retval = calculate_mac(ctx, secret, pkt, pkt_auth(request),
|
||||
pkt_attr(pkt) + 2);
|
||||
if (retval != 0)
|
||||
goto error;
|
||||
@@ -476,7 +481,7 @@ error:
|
||||
/* Verify the Message-Authenticator value in pkt, using the provided
|
||||
* authenticator (which may be from pkt or from a corresponding request). */
|
||||
static krb5_error_code
|
||||
-verify_msgauth(const char *secret, const krad_packet *pkt,
|
||||
+verify_msgauth(krb5_context ctx, const char *secret, const krad_packet *pkt,
|
||||
const uint8_t auth[AUTH_FIELD_SIZE])
|
||||
{
|
||||
uint8_t mac[MD5_DIGEST_SIZE];
|
||||
@@ -488,7 +493,7 @@ verify_msgauth(const char *secret, const krad_packet *pkt,
|
||||
if (msgauth == NULL)
|
||||
return ENODATA;
|
||||
|
||||
- retval = calculate_mac(secret, pkt, auth, mac);
|
||||
+ retval = calculate_mac(ctx, secret, pkt, auth, mac);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
@@ -561,7 +566,7 @@ krad_packet_decode_request(krb5_context ctx, const char *secret,
|
||||
|
||||
/* Verify Message-Authenticator if present. */
|
||||
if (has_pkt_msgauth(req)) {
|
||||
- retval = verify_msgauth(secret, req, pkt_auth(req));
|
||||
+ retval = verify_msgauth(ctx, secret, req, pkt_auth(req));
|
||||
if (retval) {
|
||||
krad_packet_free(req);
|
||||
return retval;
|
||||
@@ -613,7 +618,7 @@ krad_packet_decode_response(krb5_context ctx, const char *secret,
|
||||
|
||||
/* Verify Message-Authenticator if present. */
|
||||
if (has_pkt_msgauth(*rsppkt)) {
|
||||
- if (verify_msgauth(secret, *rsppkt, pkt_auth(tmp)) != 0)
|
||||
+ if (verify_msgauth(ctx, secret, *rsppkt, pkt_auth(tmp)) != 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
--
|
||||
2.49.0
|
||||
|
||||
239
SOURCES/downstream-Remove-3des-support-cumulative-1.patch
Normal file
239
SOURCES/downstream-Remove-3des-support-cumulative-1.patch
Normal file
@ -0,0 +1,239 @@
|
||||
From dea76c0b677ae02f59f6e5a796b0cf8c5d2e02f2 Mon Sep 17 00:00:00 2001
|
||||
From: Julien Rische <jrische@redhat.com>
|
||||
Date: Fri, 4 Apr 2025 15:08:36 +0200
|
||||
Subject: [PATCH] [downstream] Remove 3des support (cumulative 1)
|
||||
|
||||
Remove mentions for the triple-DES encryption type which were added
|
||||
since the previous downstream patch.
|
||||
---
|
||||
README | 3 +++
|
||||
doc/admin/conf_files/krb5_conf.rst | 6 ------
|
||||
doc/admin/enctypes.rst | 11 ++---------
|
||||
doc/mitK5features.rst | 3 +++
|
||||
src/include/k5-int.h | 2 --
|
||||
src/kdc/kdc_util.c | 2 --
|
||||
src/lib/krb5/krb/init_ctx.c | 5 -----
|
||||
src/man/krb5.conf.man | 6 ++++++
|
||||
src/tests/gssapi/t_enctypes.py | 5 ++---
|
||||
src/tests/t_etype_info.py | 4 ++--
|
||||
src/tests/t_sesskeynego.py | 8 --------
|
||||
src/util/k5test.py | 7 -------
|
||||
12 files changed, 18 insertions(+), 44 deletions(-)
|
||||
|
||||
diff --git a/README b/README
|
||||
index 0f39ac2443..b863ef84a3 100644
|
||||
--- a/README
|
||||
+++ b/README
|
||||
@@ -168,6 +168,9 @@ Developer experience:
|
||||
|
||||
Protocol evolution:
|
||||
|
||||
+* The KDC will no longer issue tickets with RC4 session keys unless
|
||||
+ explicitly configured with the new allow_rc4 variable.
|
||||
+
|
||||
* Add KDC support for S4U2Self requests where the user is identified
|
||||
by X.509 certificate. (Requires support for certificate lookup from
|
||||
a third-party KDB module.)
|
||||
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
|
||||
index c77a9fd46d..54e4780327 100644
|
||||
--- a/doc/admin/conf_files/krb5_conf.rst
|
||||
+++ b/doc/admin/conf_files/krb5_conf.rst
|
||||
@@ -95,12 +95,6 @@ Additionally, krb5.conf may include any of the relations described in
|
||||
|
||||
The libdefaults section may contain any of the following relations:
|
||||
|
||||
-**allow_des3**
|
||||
- Permit the KDC to issue tickets with des3-cbc-sha1 session keys.
|
||||
- In future releases, this flag will allow des3-cbc-sha1 to be used
|
||||
- at all. The default value for this tag is false. (Added in
|
||||
- release 1.21.)
|
||||
-
|
||||
**allow_rc4**
|
||||
Permit the KDC to issue tickets with arcfour-hmac session keys.
|
||||
In future releases, this flag will allow arcfour-hmac to be used
|
||||
diff --git a/doc/admin/enctypes.rst b/doc/admin/enctypes.rst
|
||||
index 76ef2a2133..90e85309fa 100644
|
||||
--- a/doc/admin/enctypes.rst
|
||||
+++ b/doc/admin/enctypes.rst
|
||||
@@ -49,8 +49,8 @@ The KDC chooses the session key enctype by taking the intersection of
|
||||
its **permitted_enctypes** list, the list of long-term keys for the
|
||||
most recent kvno of the service, and the client's requested list of
|
||||
enctypes. Starting in krb5-1.21, all services are assumed to support
|
||||
-aes256-cts-hmac-sha1-96; also, des3-cbc-sha1 and arcfour-hmac session
|
||||
-keys will not be issued by default.
|
||||
+aes256-cts-hmac-sha1-96; also, arcfour-hmac session keys will not be
|
||||
+issued by default.
|
||||
|
||||
Starting in krb5-1.11, it is possible to set a string attribute on a
|
||||
service principal to control what session key enctypes the KDC may
|
||||
@@ -90,13 +90,6 @@ affect how enctypes are chosen.
|
||||
acceptable risk for your environment and the weak enctypes are
|
||||
required for backward compatibility.
|
||||
|
||||
-**allow_des3**
|
||||
- was added in release 1.21 and defaults to *false*. Unless this
|
||||
- flag is set to *true*, the KDC will not issue tickets with
|
||||
- des3-cbc-sha1 session keys. In a future release, this flag will
|
||||
- control whether des3-cbc-sha1 is permitted in similar fashion to
|
||||
- weak enctypes.
|
||||
-
|
||||
**allow_rc4**
|
||||
was added in release 1.21 and defaults to *false*. Unless this
|
||||
flag is set to *true*, the KDC will not issue tickets with
|
||||
diff --git a/doc/mitK5features.rst b/doc/mitK5features.rst
|
||||
index f4594ed137..d7e516861f 100644
|
||||
--- a/doc/mitK5features.rst
|
||||
+++ b/doc/mitK5features.rst
|
||||
@@ -501,6 +501,9 @@ Release 1.18
|
||||
|
||||
* Protocol evolution:
|
||||
|
||||
+ - The KDC will no longer issue tickets with RC4 session keys unless
|
||||
+ explicitly configured with the new allow_rc4 variable.
|
||||
+
|
||||
- Add KDC support for S4U2Self requests where the user is identified
|
||||
by X.509 certificate. (Requires support for certificate lookup
|
||||
from a third-party KDB module.)
|
||||
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
|
||||
index c3d081fd30..3c74934f25 100644
|
||||
--- a/src/include/k5-int.h
|
||||
+++ b/src/include/k5-int.h
|
||||
@@ -181,7 +181,6 @@ typedef unsigned char u_char;
|
||||
* matches the variable name. Keep these alphabetized. */
|
||||
#define KRB5_CONF_ACL_FILE "acl_file"
|
||||
#define KRB5_CONF_ADMIN_SERVER "admin_server"
|
||||
-#define KRB5_CONF_ALLOW_DES3 "allow_des3"
|
||||
#define KRB5_CONF_ALLOW_RC4 "allow_rc4"
|
||||
#define KRB5_CONF_ALLOW_WEAK_CRYPTO "allow_weak_crypto"
|
||||
#define KRB5_CONF_AUTH_TO_LOCAL "auth_to_local"
|
||||
@@ -1261,7 +1260,6 @@ struct _krb5_context {
|
||||
struct _kdb_log_context *kdblog_context;
|
||||
|
||||
krb5_boolean allow_weak_crypto;
|
||||
- krb5_boolean allow_des3;
|
||||
krb5_boolean allow_rc4;
|
||||
krb5_boolean ignore_acceptor_hostname;
|
||||
krb5_boolean enforce_ok_as_delegate;
|
||||
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
|
||||
index b081d8e439..5a2589b0c0 100644
|
||||
--- a/src/kdc/kdc_util.c
|
||||
+++ b/src/kdc/kdc_util.c
|
||||
@@ -1046,8 +1046,6 @@ select_session_keytype(kdc_realm_t *kdc_active_realm, krb5_db_entry *server,
|
||||
* unless they are explicitly allowed. In the future they will be more
|
||||
* comprehensively disabled and eventually removed.
|
||||
*/
|
||||
- if (ktype[i] == ENCTYPE_DES3_CBC_SHA1 && !kdc_context->allow_des3)
|
||||
- continue;
|
||||
if (ktype[i] == ENCTYPE_ARCFOUR_HMAC && !kdc_context->allow_rc4)
|
||||
continue;
|
||||
|
||||
diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c
|
||||
index 4b23738817..980cc0893b 100644
|
||||
--- a/src/lib/krb5/krb/init_ctx.c
|
||||
+++ b/src/lib/krb5/krb/init_ctx.c
|
||||
@@ -226,11 +226,6 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
|
||||
goto cleanup;
|
||||
ctx->allow_weak_crypto = tmp;
|
||||
|
||||
- retval = get_boolean(ctx, KRB5_CONF_ALLOW_DES3, 0, &tmp);
|
||||
- if (retval)
|
||||
- goto cleanup;
|
||||
- ctx->allow_des3 = tmp;
|
||||
-
|
||||
retval = get_boolean(ctx, KRB5_CONF_ALLOW_RC4, 0, &tmp);
|
||||
if (retval)
|
||||
goto cleanup;
|
||||
diff --git a/src/man/krb5.conf.man b/src/man/krb5.conf.man
|
||||
index 067a9cbfe8..1a1c13b1a1 100644
|
||||
--- a/src/man/krb5.conf.man
|
||||
+++ b/src/man/krb5.conf.man
|
||||
@@ -178,6 +178,12 @@ kdc.conf(5), but it is not a recommended practice.
|
||||
The libdefaults section may contain any of the following relations:
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
+\fBallow_rc4\fP
|
||||
+Permit the KDC to issue tickets with arcfour\-hmac session keys.
|
||||
+In future releases, this flag will allow arcfour\-hmac to be used
|
||||
+at all. The default value for this tag is false. (Added in
|
||||
+release 1.21.)
|
||||
+.TP
|
||||
\fBallow_weak_crypto\fP
|
||||
If this flag is set to false, then weak encryption types (as noted
|
||||
in Encryption_types in kdc.conf(5)) will be filtered
|
||||
diff --git a/src/tests/gssapi/t_enctypes.py b/src/tests/gssapi/t_enctypes.py
|
||||
index e6bde47afc..1bb8c40b6b 100755
|
||||
--- a/src/tests/gssapi/t_enctypes.py
|
||||
+++ b/src/tests/gssapi/t_enctypes.py
|
||||
@@ -10,9 +10,8 @@ d_rc4 = 'DEPRECATED:arcfour-hmac'
|
||||
|
||||
# These tests make assumptions about the default enctype lists, so set
|
||||
# them explicitly rather than relying on the library defaults.
|
||||
-supp='aes256-cts:normal aes128-cts:normal des3-cbc-sha1:normal rc4-hmac:normal'
|
||||
-conf = {'libdefaults': {'permitted_enctypes': 'aes des3 rc4',
|
||||
- 'allow_des3': 'true', 'allow_rc4': 'true'},
|
||||
+supp='aes256-cts:normal aes128-cts:normal rc4-hmac:normal'
|
||||
+conf = {'libdefaults': {'permitted_enctypes': 'aes rc4', 'allow_rc4': 'true'},
|
||||
'realms': {'$realm': {'supported_enctypes': supp}}}
|
||||
realm = K5Realm(krb5_conf=conf)
|
||||
shutil.copyfile(realm.ccache, os.path.join(realm.testdir, 'save'))
|
||||
diff --git a/src/tests/t_etype_info.py b/src/tests/t_etype_info.py
|
||||
index 9ea5ca6228..cfdd6ab83c 100644
|
||||
--- a/src/tests/t_etype_info.py
|
||||
+++ b/src/tests/t_etype_info.py
|
||||
@@ -1,7 +1,7 @@
|
||||
from k5test import *
|
||||
|
||||
-supported_enctypes = 'aes128-cts des3-cbc-sha1 rc4-hmac'
|
||||
-conf = {'libdefaults': {'allow_des3': 'true', 'allow_rc4': 'true'},
|
||||
+supported_enctypes = 'aes128-cts rc4-hmac'
|
||||
+conf = {'libdefaults': {'allow_rc4': 'true'},
|
||||
'realms': {'$realm': {'supported_enctypes': supported_enctypes}}}
|
||||
realm = K5Realm(create_host=False, get_creds=False, krb5_conf=conf)
|
||||
|
||||
diff --git a/src/tests/t_sesskeynego.py b/src/tests/t_sesskeynego.py
|
||||
index f30d0bc16c..43bdcd5d7e 100755
|
||||
--- a/src/tests/t_sesskeynego.py
|
||||
+++ b/src/tests/t_sesskeynego.py
|
||||
@@ -26,7 +26,6 @@ conf3 = {'libdefaults': {
|
||||
'default_tgs_enctypes': 'rc4-hmac,aes128-cts'}}
|
||||
conf4 = {'libdefaults': {'permitted_enctypes': 'aes256-cts'}}
|
||||
conf5 = {'libdefaults': {'allow_rc4': 'true'}}
|
||||
-conf6 = {'libdefaults': {'allow_des3': 'true'}}
|
||||
# Test with client request and session_enctypes preferring aes128, but
|
||||
# aes256 long-term key.
|
||||
realm = K5Realm(krb5_conf=conf1, create_host=False, get_creds=False)
|
||||
@@ -78,13 +77,6 @@ realm.run([kadminl, 'setstr', 'server', 'session_enctypes', 'rc4-hmac'])
|
||||
test_kvno(realm, 'DEPRECATED:arcfour-hmac', 'aes256-cts-hmac-sha1-96')
|
||||
realm.stop()
|
||||
|
||||
-# 6: allow_des3 permits negotiation of des3-cbc-sha1 session key.
|
||||
-realm = K5Realm(krb5_conf=conf6, create_host=False, get_creds=False)
|
||||
-realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts', 'server'])
|
||||
-realm.run([kadminl, 'setstr', 'server', 'session_enctypes', 'des3-cbc-sha1'])
|
||||
-test_kvno(realm, 'DEPRECATED:des3-cbc-sha1', 'aes256-cts-hmac-sha1-96')
|
||||
-realm.stop()
|
||||
-
|
||||
# 7: default config negotiates aes256-sha1 session key for RC4-only service.
|
||||
realm = K5Realm(create_host=False, get_creds=False)
|
||||
realm.run([kadminl, 'addprinc', '-randkey', '-e', 'rc4-hmac', 'server'])
|
||||
diff --git a/src/util/k5test.py b/src/util/k5test.py
|
||||
index 96474cc5aa..c3ab63f8e8 100644
|
||||
--- a/src/util/k5test.py
|
||||
+++ b/src/util/k5test.py
|
||||
@@ -1299,13 +1299,6 @@ _passes = [
|
||||
# No special settings; exercises AES256.
|
||||
('default', None, None, None),
|
||||
|
||||
- # Exercise the DES3 enctype.
|
||||
- ('des3', None,
|
||||
- {'libdefaults': {'permitted_enctypes': 'des3 aes256-sha1'}},
|
||||
- {'realms': {'$realm': {
|
||||
- 'supported_enctypes': 'des3-cbc-sha1:normal',
|
||||
- 'master_key_type': 'des3-cbc-sha1'}}}),
|
||||
-
|
||||
# Exercise the arcfour enctype.
|
||||
('arcfour', None,
|
||||
{'libdefaults': {'permitted_enctypes': 'rc4 aes256-sha1'}},
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
[libdefaults]
|
||||
# Allow RC4 HMAC-MD5 for session keys (see CVE-2022-37966)
|
||||
#allow_rc4 = true
|
||||
|
||||
[kdcdefaults]
|
||||
kdc_ports = 88
|
||||
kdc_tcp_ports = 88
|
||||
|
||||
@ -18,7 +18,7 @@ Summary: The Kerberos network authentication system
|
||||
Name: krb5
|
||||
Version: 1.18.2
|
||||
# for prerelease, should be e.g., 0.% {prerelease}.1% { ?dist } (without spaces)
|
||||
Release: 31%{?dist}
|
||||
Release: 32%{?dist}
|
||||
|
||||
# lookaside-cached sources; two downloads and a build artifact
|
||||
Source0: https://web.mit.edu/kerberos/dist/krb5/1.18/krb5-%{version}%{prerelease}.tar.gz
|
||||
@ -111,6 +111,11 @@ Patch165: Remove-PKINIT-RSA-support.patch
|
||||
Patch166: Generate-and-verify-message-MACs-in-libkrad.patch
|
||||
Patch167: Set-missing-mask-flags-for-kdb5_util-operations.patch
|
||||
Patch168: Prevent-overflow-when-calculating-ulog-block-size.patch
|
||||
Patch169: In-KDC-assume-all-services-support-aes256-sha1.patch
|
||||
Patch170: Don-t-issue-session-keys-with-deprecated-enctypes.patch
|
||||
Patch171: downstream-Remove-3des-support-cumulative-1.patch
|
||||
Patch172: Add-PKINIT-paChecksum2-from-MS-PKCA-v20230920.patch
|
||||
Patch173: downstream-Do-not-block-HMAC-MD4-5-in-FIPS-mode.patch
|
||||
|
||||
License: MIT
|
||||
URL: http://web.mit.edu/kerberos/www/
|
||||
@ -721,6 +726,14 @@ exit 0
|
||||
%{_libdir}/libkadm5srv_mit.so.*
|
||||
|
||||
%changelog
|
||||
* Thu Apr 24 2025 Julien Rische <jrische@redhat.com> - 1.18.2-32
|
||||
- Do not block HMAC-MD4/5 in FIPS mode
|
||||
Resolves: RHEL-86786
|
||||
- Don't issue RC4 session keys by default (CVE-2025-3576)
|
||||
Resolves: RHEL-88049
|
||||
- Add PKINIT paChecksum2 from MS-PKCA v20230920
|
||||
Resolves: RHEL-82648
|
||||
|
||||
* Tue Feb 11 2025 Julien Rische <jrische@redhat.com> - 1.18.2-31
|
||||
- Prevent overflow when calculating ulog block size (CVE-2025-24528)
|
||||
Resolves: RHEL-78248
|
||||
|
||||
Loading…
Reference in New Issue
Block a user