aboutsummaryrefslogtreecommitdiff
path: root/lib/krb5/pkinit.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/krb5/pkinit.c')
-rw-r--r--lib/krb5/pkinit.c103
1 files changed, 101 insertions, 2 deletions
diff --git a/lib/krb5/pkinit.c b/lib/krb5/pkinit.c
index 0adb65e7afa1..7ede91c3fa9a 100644
--- a/lib/krb5/pkinit.c
+++ b/lib/krb5/pkinit.c
@@ -784,6 +784,8 @@ _krb5_pk_mk_padata(krb5_context context,
req_body->realm,
"pkinit_require_krbtgt_otherName",
NULL);
+ if (ic_flags & KRB5_INIT_CREDS_PKINIT_NO_KRBTGT_OTHERNAME_CHECK)
+ ctx->require_krbtgt_otherName = FALSE;
ctx->require_hostname_match =
krb5_config_get_bool_default(context, NULL,
@@ -1220,6 +1222,98 @@ pk_rd_pa_reply_enckey(krb5_context context,
return ret;
}
+/*
+ * RFC 8062 section 7:
+ *
+ * The client then decrypts the KDC contribution key and verifies that
+ * the ticket session key in the returned ticket is the combined key of
+ * the KDC contribution key and the reply key.
+ */
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+_krb5_pk_kx_confirm(krb5_context context,
+ krb5_pk_init_ctx ctx,
+ krb5_keyblock *reply_key,
+ krb5_keyblock *session_key,
+ PA_DATA *pa_pkinit_kx)
+{
+ krb5_error_code ret;
+ EncryptedData ed;
+ krb5_keyblock ck, sk_verify;
+ krb5_crypto ck_crypto = NULL;
+ krb5_crypto rk_crypto = NULL;
+ size_t len;
+ krb5_data data;
+ krb5_data p1 = { sizeof("PKINIT") - 1, "PKINIT" };
+ krb5_data p2 = { sizeof("KEYEXCHANGE") - 1, "KEYEXCHANGE" };
+
+ heim_assert(ctx != NULL, "PKINIT context is non-NULL");
+ heim_assert(reply_key != NULL, "reply key is non-NULL");
+ heim_assert(session_key != NULL, "session key is non-NULL");
+
+ /* PA-PKINIT-KX is optional unless anonymous */
+ if (pa_pkinit_kx == NULL)
+ return ctx->anonymous ? KRB5_KDCREP_MODIFIED : 0;
+
+ memset(&ed, 0, sizeof(ed));
+ krb5_keyblock_zero(&ck);
+ krb5_keyblock_zero(&sk_verify);
+ krb5_data_zero(&data);
+
+ ret = decode_EncryptedData(pa_pkinit_kx->padata_value.data,
+ pa_pkinit_kx->padata_value.length,
+ &ed, &len);
+ if (ret)
+ goto out;
+
+ if (len != pa_pkinit_kx->padata_value.length) {
+ ret = KRB5_KDCREP_MODIFIED;
+ goto out;
+ }
+
+ ret = krb5_crypto_init(context, reply_key, 0, &rk_crypto);
+ if (ret)
+ goto out;
+
+ ret = krb5_decrypt_EncryptedData(context, rk_crypto,
+ KRB5_KU_PA_PKINIT_KX,
+ &ed, &data);
+ if (ret)
+ goto out;
+
+ ret = decode_EncryptionKey(data.data, data.length,
+ &ck, &len);
+ if (ret)
+ goto out;
+
+ ret = krb5_crypto_init(context, &ck, 0, &ck_crypto);
+ if (ret)
+ goto out;
+
+ ret = krb5_crypto_fx_cf2(context, ck_crypto, rk_crypto,
+ &p1, &p2, session_key->keytype,
+ &sk_verify);
+ if (ret)
+ goto out;
+
+ if (sk_verify.keytype != session_key->keytype ||
+ krb5_data_ct_cmp(&sk_verify.keyvalue, &session_key->keyvalue) != 0) {
+ ret = KRB5_KDCREP_MODIFIED;
+ goto out;
+ }
+
+out:
+ free_EncryptedData(&ed);
+ krb5_free_keyblock_contents(context, &ck);
+ krb5_free_keyblock_contents(context, &sk_verify);
+ if (ck_crypto)
+ krb5_crypto_destroy(context, ck_crypto);
+ if (rk_crypto)
+ krb5_crypto_destroy(context, rk_crypto);
+ krb5_data_free(&data);
+
+ return ret;
+}
+
static krb5_error_code
pk_rd_pa_reply_dh(krb5_context context,
const heim_octet_string *indata,
@@ -2269,7 +2363,7 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
x509_anchors = anchors;
}
- if (flags & 4)
+ if (flags & KRB5_GIC_OPT_PKINIT_ANONYMOUS)
opt->opt_private->pk_init_ctx->anonymous = 1;
ret = _krb5_pk_load_id(context,
@@ -2286,6 +2380,11 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
opt->opt_private->pk_init_ctx = NULL;
return ret;
}
+ if (flags & KRB5_GIC_OPT_PKINIT_BTMM)
+ opt->opt_private->pk_init_ctx->id->flags |= PKINIT_BTMM;
+
+ if (principal && krb5_principal_is_lkdc(context, principal))
+ opt->opt_private->pk_init_ctx->id->flags |= PKINIT_BTMM;
if (opt->opt_private->pk_init_ctx->id->certs) {
_krb5_pk_set_user_id(context,
@@ -2295,7 +2394,7 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
} else
opt->opt_private->pk_init_ctx->id->cert = NULL;
- if ((flags & 2) == 0) {
+ if ((flags & KRB5_GIC_OPT_PKINIT_USE_ENCKEY) == 0) {
hx509_context hx509ctx = context->hx509ctx;
hx509_cert cert = opt->opt_private->pk_init_ctx->id->cert;