summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Hartman <hartmans@mit.edu>2009-04-03 03:39:58 +0000
committerSam Hartman <hartmans@mit.edu>2009-04-03 03:39:58 +0000
commitbeda97c8639b7101b224a50cb0035acaaf626ec7 (patch)
tree256dbeae48f2eaeb6c4d1f66ddf19ed42457e50f
parentd1408b89077c5e4eab4f1ccbd0ae775ff5eae20e (diff)
downloadkrb5-fast.tar.gz
Implement strengthen keyfast
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
-rw-r--r--src/include/k5-int.h2
-rw-r--r--src/kdc/do_as_req.c15
-rw-r--r--src/kdc/do_tgs_req.c3
-rw-r--r--src/kdc/fast_util.c36
-rw-r--r--src/kdc/kdc_util.h11
-rw-r--r--src/lib/krb5/asn.1/asn1_k_encode.c4
-rw-r--r--src/lib/krb5/asn.1/krb5_decode.c4
-rw-r--r--src/lib/krb5/krb/fast.c31
-rw-r--r--src/lib/krb5/krb/fast.h8
-rw-r--r--src/lib/krb5/krb/get_in_tkt.c37
-rw-r--r--src/lib/krb5/krb/kfree.c1
11 files changed, 114 insertions, 38 deletions
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index 7ba5d5835..5e159d9a4 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 2aa8d64d9..4f1715d67 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 7ff601cd8..598c87971 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 da965f591..ac6aa22c4 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 e9ccc4477..060442604 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 8baab371d..f234a593f 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 272c07042..084672fbe 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 fff05fb3c..ef57e6d83 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 7e58fd060..4cc142335 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 2001a1623..2944652ff 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 d17d46bc7..bec9a61bf 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);
}