From: Sam Hartman Date: Wed, 23 Dec 2009 21:11:06 +0000 (+0000) Subject: Client side of PA_PKINIT_KX X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9992f7384f904f32e5fd8975f713786b441cc706;p=thirdparty%2Fkrb5.git 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 git-svn-id: svn://anonsvn.mit.edu/krb5/branches/anonymous@23514 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin index e94fe67ade..6d8b7217b5 100644 --- a/src/include/krb5/krb5.hin +++ b/src/include/krb5/krb5.hin @@ -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 diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c index 64989ac61a..f20ba54b3b 100644 --- a/src/lib/krb5/krb/get_in_tkt.c +++ b/src/lib/krb5/krb/get_in_tkt.c @@ -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);