svn rev #23514: branches/anonymous/src/ include/krb5/ lib/krb5/krb/

hartmans@MIT.EDU hartmans at MIT.EDU
Wed Dec 23 16:11:06 EST 2009


http://src.mit.edu/fisheye/changelog/krb5/?cs=23514
Commit By: hartmans
Log Message:
Client side of PA_PKINIT_KX

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


Changed Files:
U   branches/anonymous/src/include/krb5/krb5.hin
U   branches/anonymous/src/lib/krb5/krb/get_in_tkt.c
Modified: branches/anonymous/src/include/krb5/krb5.hin
===================================================================
--- branches/anonymous/src/include/krb5/krb5.hin	2009-12-23 21:11:03 UTC (rev 23513)
+++ branches/anonymous/src/include/krb5/krb5.hin	2009-12-23 21:11:06 UTC (rev 23514)
@@ -638,7 +638,7 @@
 #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 @@
 #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

Modified: branches/anonymous/src/lib/krb5/krb/get_in_tkt.c
===================================================================
--- branches/anonymous/src/lib/krb5/krb/get_in_tkt.c	2009-12-23 21:11:03 UTC (rev 23513)
+++ branches/anonymous/src/lib/krb5/krb/get_in_tkt.c	2009-12-23 21:11:06 UTC (rev 23514)
@@ -283,7 +283,72 @@
     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,
                 krb5_kdc_req            *request,
@@ -1994,6 +2059,10 @@
                            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);




More information about the cvs-krb5 mailing list