]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Client side of PA_PKINIT_KX
authorSam Hartman <hartmans@mit.edu>
Wed, 23 Dec 2009 21:11:06 +0000 (21:11 +0000)
committerSam Hartman <hartmans@mit.edu>
Wed, 23 Dec 2009 21:11:06 +0000 (21:11 +0000)
The anonymous draft specifies the use of PA_PKINIT_KX to confirm that
both the client and KDc contributed to the session key and to confirm
the session key is fresh.  Implement client support for this item.

* krb5.hin: define padata and key usage constants
* get_in_tkt.c: New function verify_anonymous to perform verification

git-svn-id: svn://anonsvn.mit.edu/krb5/branches/anonymous@23514 dc483132-0cff-0310-8789-dd5450dbe970

src/include/krb5/krb5.hin
src/lib/krb5/krb/get_in_tkt.c

index e94fe67adeb3153307ec093ad48d34615188c01b..6d8b7217b5c0d2da806893c6d2b3e5da00179f62 100644 (file)
@@ -638,7 +638,7 @@ krb5_c_keyed_checksum_types(krb5_context context, krb5_enctype enctype,
 #define KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY    27 /* XXX note conflict with above */
 
 #define KRB5_KEYUSAGE_AD_SIGNEDPATH             -21
-
+#define KRB5_KEYUSAGE_PA_PKINIT_KX 44
 /* define in draft-ietf-krb-wg-preauth-framework*/
 #define KRB5_KEYUSAGE_FAST_REQ_CHKSUM 50
 #define KRB5_KEYUSAGE_FAST_ENC 51
@@ -1041,6 +1041,7 @@ krb5_verify_checksum(krb5_context context, krb5_cksumtype ctype,
 #define KRB5_PADATA_FX_FAST  136
 #define KRB5_PADATA_FX_ERROR 137
 #define KRB5_PADATA_ENCRYPTED_CHALLENGE 138
+#define KRB5_PADATA_PKINIT_KX 147
 #define KRB5_ENCPADATA_REQ_ENC_PA_REP 149
 
 #define KRB5_SAM_USE_SAD_AS_KEY         0x80000000
index 64989ac61abec1abb3619088e14b066d334c0ce3..f20ba54b3b23a1f89125ca02e949b874e86d1487 100644 (file)
@@ -283,6 +283,71 @@ cleanup:
     return (retval);
 }
 
+/**
+ * Fully anonymous replies include a pa_pkinit_kx padata type including the KDC
+ * contribution key.  This routine confirms that the session key is of the
+ * right form for fully anonymous requests.  It is here rather than in the
+ * preauth code because the session key cannot be verified until the AS reply
+ * is decrypted and the preauth code all runs before the AS reply is decrypted.
+ */
+static krb5_error_code
+verify_anonymous( krb5_context context, krb5_kdc_req *request,
+                  krb5_kdc_rep *reply, krb5_keyblock *as_key)
+{
+    krb5_error_code ret = 0;
+    krb5_pa_data *pa;
+    krb5_data scratch;
+    krb5_keyblock *kdc_key = NULL, *expected = NULL;
+    krb5_enc_data *enc = NULL;
+    krb5_keyblock *session = reply->enc_part2->session;
+    if (!krb5_principal_compare_any_realm(context, request->client,
+                                          krb5_anonymous_principal()))
+        return 0; /*Only applies to fully anonymous*/
+    pa = krb5int_find_pa_data(context, reply->padata, KRB5_PADATA_PKINIT_KX);
+    if (pa == NULL)
+        goto verification_error;
+    scratch.length = pa->length;
+    scratch.data = (char  *) pa->contents;
+    ret = decode_krb5_enc_data( &scratch, &enc);
+    if (ret)
+        goto cleanup;
+    scratch.data = k5alloc(enc->ciphertext.length, &ret);
+    if (ret)
+        goto cleanup;
+    scratch.length = enc->ciphertext.length;
+    ret = krb5_c_decrypt(context, as_key, KRB5_KEYUSAGE_PA_PKINIT_KX,
+                         NULL /*cipherstate*/, enc, &scratch);
+    if (ret) {
+        free( scratch.data);
+        goto cleanup;
+    }
+    ret = decode_krb5_encryption_key( &scratch, &kdc_key);
+    zap(scratch.data, scratch.length);
+    free(scratch.data);
+    if (ret)
+        goto cleanup;
+    ret = krb5_c_fx_cf2_simple( context, kdc_key, "PKINIT",
+                                as_key, "KEYEXCHANGE", &expected);
+    if (ret)
+        goto cleanup;
+    if ((expected->enctype != session->enctype)
+        || (expected->length != session->length)
+        || (memcmp(expected->contents, session->contents, expected->length) != 0))
+        goto verification_error;
+cleanup:
+    if (kdc_key)
+        krb5_free_keyblock(context, kdc_key);
+    if (expected)
+        krb5_free_keyblock(context, expected);
+    if (enc)
+        krb5_free_enc_data(context, enc);
+    return ret;
+verification_error:
+    ret = KRB5_KDCREP_MODIFIED;
+    krb5_set_error_message(context, ret, "Reply has wrong form of session key for anonymous request");
+    goto cleanup;
+}
+
 static krb5_error_code
 verify_as_reply(krb5_context            context,
                 krb5_timestamp          time_now,
@@ -1994,6 +2059,10 @@ init_creds_step_reply(krb5_context context,
                            ctx->request, ctx->reply);
     if (code != 0)
         goto cleanup;
+    code = verify_anonymous( context, ctx->request, ctx->reply,
+                             &encrypting_key);
+    if (code)
+        goto cleanup;
 
     code = stash_as_reply(context, ctx->request_time, ctx->request,
                           ctx->reply, &ctx->cred, NULL);