From beda97c8639b7101b224a50cb0035acaaf626ec7 Mon Sep 17 00:00:00 2001 From: Sam Hartman Date: Fri, 3 Apr 2009 03:39:58 +0000 Subject: Implement strengthen key Per ietf-krb-wg discussion, the reply key mechanism is being replaced with a strengthen key mechanism. git-svn-id: svn://anonsvn.mit.edu/krb5/branches/fast@22166 dc483132-0cff-0310-8789-dd5450dbe970 --- src/include/k5-int.h | 2 +- src/kdc/do_as_req.c | 15 +++++++++++---- src/kdc/do_tgs_req.c | 3 ++- src/kdc/fast_util.c | 36 +++++++++++++++++++++++++++++++----- src/kdc/kdc_util.h | 11 +++++++++-- src/lib/krb5/asn.1/asn1_k_encode.c | 4 ++-- src/lib/krb5/asn.1/krb5_decode.c | 4 ++-- src/lib/krb5/krb/fast.c | 31 +++++++++++++++++++++++++++---- src/lib/krb5/krb/fast.h | 8 +++++++- src/lib/krb5/krb/get_in_tkt.c | 37 +++++++++++++++++++++---------------- src/lib/krb5/krb/kfree.c | 1 + 11 files changed, 114 insertions(+), 38 deletions(-) diff --git a/src/include/k5-int.h b/src/include/k5-int.h index 7ba5d58..5e159d9 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -1001,7 +1001,7 @@ typedef struct _krb5_fast_finished { typedef struct _krb5_fast_response { krb5_magic magic; krb5_pa_data **padata; - krb5_keyblock *rep_key; + krb5_keyblock *strengthen_key; krb5_fast_finished *finished; krb5_int32 nonce; } krb5_fast_response; diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c index 2aa8d64..4f1715d 100644 --- a/src/kdc/do_as_req.c +++ b/src/kdc/do_as_req.c @@ -119,6 +119,7 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, krb5_keylist_node *tmp_mkey_list; struct kdc_request_state *state = NULL; krb5_data encoded_req_body; + krb5_keyblock *as_encrypting_key = NULL; #if APPLE_PKINIT @@ -592,7 +593,7 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, goto errout; } ticket_reply.enc_part.kvno = server_key->key_data_kvno; - errcode = kdc_fast_response_handle_padata(state, request, &reply); + errcode = kdc_fast_response_handle_padata(state, request, &reply, client_keyblock.enctype); if (errcode) { status = "fast response handling"; goto errout; @@ -602,8 +603,13 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, reply.enc_part.enctype = client_keyblock.enctype; - errcode = krb5_encode_kdc_rep(kdc_context, KRB5_AS_REP, &reply_encpart, - 0, &client_keyblock, &reply, response); + errcode = kdc_fast_handle_reply_key(state, &client_keyblock, &as_encrypting_key); + if (errcode) { + status = "generating reply key"; + goto errout; + } + errcode = krb5_encode_kdc_rep(kdc_context, KRB5_AS_REP, &reply_encpart, + 0, as_encrypting_key, &reply, response); reply.enc_part.kvno = client_key->key_data_kvno; if (errcode) { status = "ENCODE_KDC_REP"; @@ -637,7 +643,8 @@ errout: egress: if (pa_context) free_padata_context(kdc_context, &pa_context); - + if (as_encrypting_key) + krb5_free_keyblock(kdc_context, as_encrypting_key); if (errcode) emsg = krb5_get_error_message(kdc_context, errcode); diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c index 7ff601c..598c879 100644 --- a/src/kdc/do_tgs_req.c +++ b/src/kdc/do_tgs_req.c @@ -878,7 +878,8 @@ tgt_again: reply.enc_part.enctype = subkey ? subkey->enctype : header_ticket->enc_part2->session->enctype; - errcode = kdc_fast_response_handle_padata(state, request, &reply); + errcode = kdc_fast_response_handle_padata(state, request, &reply, + subkey?subkey->enctype:header_ticket->enc_part2->session->enctype); if (errcode !=0 ) { status = "Preparing FAST padata"; goto cleanup; diff --git a/src/kdc/fast_util.c b/src/kdc/fast_util.c index da965f5..ac6aa22 100644 --- a/src/kdc/fast_util.c +++ b/src/kdc/fast_util.c @@ -251,8 +251,8 @@ void kdc_free_rstate return; if (s->armor_key) krb5_free_keyblock(kdc_context, s->armor_key); - if (s->reply_key) - krb5_free_keyblock(kdc_context, s->reply_key); + if (s->strengthen_key) + krb5_free_keyblock(kdc_context, s->strengthen_key); if (s->cookie) { free(s->cookie->contents); free(s->cookie); @@ -263,7 +263,7 @@ void kdc_free_rstate krb5_error_code kdc_fast_response_handle_padata (struct kdc_request_state *state, krb5_kdc_req *request, - krb5_kdc_rep *rep) + krb5_kdc_rep *rep, krb5_enctype enctype) { krb5_error_code retval = 0; krb5_fast_finished finish; @@ -273,14 +273,23 @@ krb5_error_code kdc_fast_response_handle_padata krb5_pa_data *pa = NULL, **pa_array = NULL; krb5_cksumtype cksumtype = CKSUMTYPE_RSA_MD5; krb5_pa_data *empty_padata[] = {NULL}; + krb5_keyblock *strengthen_key = NULL; if (!state->armor_key) return 0; memset(&finish, 0, sizeof(finish)); + retval = krb5_init_keyblock(kdc_context, enctype, 0, &strengthen_key); + if (retval == 0) + retval = krb5_c_make_random_key(kdc_context, enctype, strengthen_key); + if (retval == 0) { + state->strengthen_key = strengthen_key; + strengthen_key = NULL; + } + fast_response.padata = rep->padata; if (fast_response.padata == NULL) fast_response.padata = &empty_padata[0]; - fast_response.rep_key = state->reply_key; + fast_response.strengthen_key = state->strengthen_key; fast_response.nonce = request->nonce; fast_response.finished = &finish; finish.client = rep->client; @@ -321,6 +330,8 @@ krb5_error_code kdc_fast_response_handle_padata krb5_free_data(kdc_context, encrypted_reply); if (encoded_ticket) krb5_free_data(kdc_context, encoded_ticket); + if (strengthen_key != NULL) + krb5_free_keyblock(kdc_context, strengthen_key); if (finish.ticket_checksum.contents) krb5_free_checksum_contents(kdc_context, &finish.ticket_checksum); return retval; @@ -377,7 +388,7 @@ krb5_error_code kdc_fast_handle_error if (retval == 0) { resp.padata = inner_pa; resp.nonce = request->nonce; - resp.rep_key = NULL; + resp.strengthen_key = NULL; resp.finished = NULL; } if (retval == 0) @@ -411,6 +422,21 @@ krb5_error_code kdc_fast_handle_error return retval; } +krb5_error_code kdc_fast_handle_reply_key(struct kdc_request_state *state, + krb5_keyblock *existing_key, + krb5_keyblock **out_key) +{ + krb5_error_code retval = 0; + if (state->armor_key) + retval = krb5_c_fx_cf2_simple(kdc_context, + state->strengthen_key, "strengthenkey", + existing_key, + "replykey", out_key); + else retval = krb5_copy_keyblock(kdc_context, existing_key, out_key); + return retval; +} + + krb5_error_code kdc_preauth_get_cookie(struct kdc_request_state *state, krb5_pa_data **cookie) { diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h index e9ccc44..0604426 100644 --- a/src/kdc/kdc_util.h +++ b/src/kdc/kdc_util.h @@ -302,11 +302,12 @@ void log_tgs_alt_tgt(krb5_principal p); struct kdc_request_state { krb5_keyblock *armor_key; - krb5_keyblock *reply_key; /*When replaced by FAST*/ + krb5_keyblock *strengthen_key; krb5_pa_data *cookie; krb5_int32 fast_options; krb5_int32 fast_internal_flags; }; + krb5_error_code kdc_make_rstate(struct kdc_request_state **out); void kdc_free_rstate (struct kdc_request_state *s); @@ -325,12 +326,18 @@ krb5_error_code kdc_find_fast krb5_error_code kdc_fast_response_handle_padata (struct kdc_request_state *state, krb5_kdc_req *request, - krb5_kdc_rep *rep); + krb5_kdc_rep *rep, + krb5_enctype enctype); krb5_error_code kdc_fast_handle_error (krb5_context context, struct kdc_request_state *state, krb5_kdc_req *request, krb5_pa_data **in_padata, krb5_error *err); +krb5_error_code kdc_fast_handle_reply_key(struct kdc_request_state *state, + krb5_keyblock *existing_key, + krb5_keyblock **out_key); + + krb5_error_code kdc_preauth_get_cookie(struct kdc_request_state *state, krb5_pa_data **cookie); diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c index 8baab37..f234a59 100644 --- a/src/lib/krb5/asn.1/asn1_k_encode.c +++ b/src/lib/krb5/asn.1/asn1_k_encode.c @@ -1233,7 +1233,7 @@ DEFPTRTYPE( ptr_fast_finished, fast_finished); static const struct field_info fast_response_fields[] = { FIELDOF_NORM(krb5_fast_response, ptr_seqof_pa_data, padata, 0), - FIELDOF_OPT( krb5_fast_response, ptr_encryption_key, rep_key, 1, 1), + FIELDOF_OPT( krb5_fast_response, ptr_encryption_key, strengthen_key, 1, 1), FIELDOF_OPT( krb5_fast_response, ptr_fast_finished, finished, 2, 2), FIELDOF_NORM(krb5_fast_response, int32, nonce, 3), }; @@ -1242,7 +1242,7 @@ static unsigned int fast_response_optional (const void *p) { unsigned int optional = 0; const krb5_fast_response *val = p; - if (val->rep_key) + if (val->strengthen_key) optional |= (1u <<1); if (val->finished) optional |= (1u<<2); diff --git a/src/lib/krb5/asn.1/krb5_decode.c b/src/lib/krb5/asn.1/krb5_decode.c index 272c070..084672f 100644 --- a/src/lib/krb5/asn.1/krb5_decode.c +++ b/src/lib/krb5/asn.1/krb5_decode.c @@ -1137,10 +1137,10 @@ krb5_error_code decode_krb5_fast_response alloc_field(rep); clear_field(rep, finished); clear_field(rep, padata); - clear_field(rep,rep_key); + clear_field(rep,strengthen_key); {begin_structure(); get_field(rep->padata, 0, asn1_decode_sequence_of_pa_data); - opt_field(rep->rep_key, 1, asn1_decode_encryption_key_ptr); + opt_field(rep->strengthen_key, 1, asn1_decode_encryption_key_ptr); opt_field(rep->finished, 2, asn1_decode_fast_finished_ptr); get_field(rep->nonce, 3, asn1_decode_int32); end_structure(); } diff --git a/src/lib/krb5/krb/fast.c b/src/lib/krb5/krb/fast.c index fff05fb..ef57e6d 100644 --- a/src/lib/krb5/krb/fast.c +++ b/src/lib/krb5/krb/fast.c @@ -412,14 +412,14 @@ krb5int_fast_process_error(krb5_context context, struct krb5int_fast_request_sta krb5_error_code krb5int_fast_process_response (krb5_context context, struct krb5int_fast_request_state *state, krb5_kdc_rep *resp, - krb5_keyblock **as_key) + krb5_keyblock **strengthen_key) { krb5_error_code retval = 0; krb5_fast_response *fast_response = NULL; krb5_data *encoded_ticket = NULL; krb5_boolean cksum_valid; krb5_clear_error_message(context); - *as_key = NULL; + *strengthen_key = NULL; if (state->armor_key == 0) return 0; retval = decrypt_fast_reply(context, state, resp->padata, @@ -446,8 +446,8 @@ krb5_error_code krb5int_fast_process_response krb5_free_principal(context, resp->client); resp->client = fast_response->finished->client; fast_response->finished->client = NULL; - *as_key = fast_response->rep_key; - fast_response->rep_key = NULL; + *strengthen_key = fast_response->strengthen_key; + fast_response->strengthen_key = NULL; krb5_free_pa_data(context, resp->padata); resp->padata = fast_response->padata; fast_response->padata = NULL; @@ -458,6 +458,29 @@ krb5_error_code krb5int_fast_process_response krb5_free_data(context, encoded_ticket); return retval; } + +krb5_error_code krb5int_fast_reply_key(krb5_context context, + krb5_keyblock *strengthen_key, + krb5_keyblock *existing_key, + krb5_keyblock *out_key) +{ + krb5_keyblock *key = NULL; + krb5_error_code retval = 0; + krb5_free_keyblock_contents(context, out_key); + if (strengthen_key) { + retval = krb5_c_fx_cf2_simple(context, strengthen_key, + "strengthenkey", existing_key, "replykey", &key); + if (retval == 0) { + *out_key = *key; + free(key); + } + } else { + retval = krb5_copy_keyblock_contents(context, existing_key, out_key); + } + return retval; +} + + krb5_error_code krb5int_fast_make_state( krb5_context context, struct krb5int_fast_request_state **state) { diff --git a/src/lib/krb5/krb/fast.h b/src/lib/krb5/krb/fast.h index 7e58fd0..4cc1423 100644 --- a/src/lib/krb5/krb/fast.h +++ b/src/lib/krb5/krb/fast.h @@ -60,7 +60,7 @@ krb5int_fast_process_error(krb5_context context, struct krb5int_fast_request_sta krb5_error_code krb5int_fast_process_response (krb5_context context, struct krb5int_fast_request_state *state, krb5_kdc_rep *resp, - krb5_keyblock **as_key); + krb5_keyblock **strengthen_key); krb5_error_code krb5int_fast_make_state( krb5_context context, struct krb5int_fast_request_state **state); @@ -72,5 +72,11 @@ krb5_error_code krb5int_fast_as_armor krb5_gic_opt_ext *opte, krb5_kdc_req *request); +krb5_error_code krb5int_fast_reply_key(krb5_context context, + krb5_keyblock *strengthen_key, + krb5_keyblock *existing_key, + krb5_keyblock *output_key); + + #endif diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c index 2001a16..2944652 100644 --- a/src/lib/krb5/krb/get_in_tkt.c +++ b/src/lib/krb5/krb/get_in_tkt.c @@ -967,8 +967,8 @@ krb5_get_init_creds(krb5_context context, int loopcount; krb5_data salt; krb5_data s2kparams; - krb5_keyblock as_key; - krb5_keyblock *fast_as_key = NULL; + krb5_keyblock as_key, encrypting_key; + krb5_keyblock *strengthen_key = NULL; krb5_error *err_reply; krb5_kdc_rep *local_as_reply; krb5_timestamp time_now; @@ -994,6 +994,8 @@ krb5_get_init_creds(krb5_context context, preauth_to_use = NULL; kdc_padata = NULL; as_key.length = 0; + encrypting_key.length = 0; + encrypting_key.contents = NULL; salt.length = 0; salt.data = NULL; @@ -1397,7 +1399,7 @@ krb5_get_init_creds(krb5_context context, /* process any preauth data in the as_reply */ krb5_clear_preauth_context_use_counts(context); ret = krb5int_fast_process_response(context, fast_state, - local_as_reply, &fast_as_key); + local_as_reply, &strengthen_key); if (ret) goto cleanup; if ((ret = sort_krb5_padata_sequence(context, &request.server->realm, @@ -1445,18 +1447,15 @@ krb5_get_init_creds(krb5_context context, it. If decrypting the as_rep fails, or if there isn't an as_key at all yet, then use the gak_fct to get one, and try again. */ - if (fast_as_key) { - if (as_key.length) - krb5_free_keyblock_contents(context, &as_key); - as_key = *fast_as_key; - free(fast_as_key); - fast_as_key = NULL; - } - if (as_key.length) - ret = decrypt_as_reply(context, NULL, local_as_reply, NULL, - NULL, &as_key, krb5_kdc_rep_decrypt_proc, + if (as_key.length) { + ret = krb5int_fast_reply_key(context, strengthen_key, &as_key, + &encrypting_key); + if (ret) + goto cleanup; + ret = decrypt_as_reply(context, NULL, local_as_reply, NULL, + NULL, &encrypting_key, krb5_kdc_rep_decrypt_proc, NULL); - else + } else ret = -1; if (ret) { @@ -1468,6 +1467,10 @@ krb5_get_init_creds(krb5_context context, &as_key, gak_data)))) goto cleanup; + ret = krb5int_fast_reply_key(context, strengthen_key, &as_key, + &encrypting_key); + if (ret) + goto cleanup; if ((ret = decrypt_as_reply(context, NULL, local_as_reply, NULL, NULL, &as_key, krb5_kdc_rep_decrypt_proc, NULL))) @@ -1509,8 +1512,10 @@ cleanup: } } krb5_preauth_request_context_fini(context); - krb5_free_keyblock(context, fast_as_key); - if (fast_state) + krb5_free_keyblock(context, strengthen_key); + if (encrypting_key.contents) + krb5_free_keyblock_contents(context, &encrypting_key); + if (fast_state) krb5int_fast_free_state(context, fast_state); if (out_padata) krb5_free_pa_data(context, out_padata); diff --git a/src/lib/krb5/krb/kfree.c b/src/lib/krb5/krb/kfree.c index d17d46b..bec9a61 100644 --- a/src/lib/krb5/krb/kfree.c +++ b/src/lib/krb5/krb/kfree.c @@ -819,6 +819,7 @@ void krb5_free_fast_response(krb5_context context, krb5_fast_response *val) return; krb5_free_pa_data(context, val->padata); krb5_free_fast_finished(context, val->finished); + krb5_free_keyblock(context, val->strengthen_key); free(val); } -- cgit v1.1