]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Implement strengthen key fast
authorSam Hartman <hartmans@mit.edu>
Fri, 3 Apr 2009 03:39:58 +0000 (03:39 +0000)
committerSam Hartman <hartmans@mit.edu>
Fri, 3 Apr 2009 03:39:58 +0000 (03:39 +0000)
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
src/kdc/do_as_req.c
src/kdc/do_tgs_req.c
src/kdc/fast_util.c
src/kdc/kdc_util.h
src/lib/krb5/asn.1/asn1_k_encode.c
src/lib/krb5/asn.1/krb5_decode.c
src/lib/krb5/krb/fast.c
src/lib/krb5/krb/fast.h
src/lib/krb5/krb/get_in_tkt.c
src/lib/krb5/krb/kfree.c

index 7ba5d5835dcc643d2d8e4129d621c82777035071..5e159d9a4fb67503f43710b479a4f19692953485 100644 (file)
@@ -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;
index 2aa8d64d9237a279683a2b2a9b898335309c1629..4f1715d678ade8ce03e77dc82337cd4efdf01df1 100644 (file)
@@ -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);
 
index 7ff601cd8183aca145c380d46b348c7591146a2a..598c8797176c5b83065a769e606b6de5175a164d 100644 (file)
@@ -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;
index da965f591a2a632b8046d36f8d0d028786f172a0..ac6aa22c48c9102f688a270ccf76e5faf79d9624 100644 (file)
@@ -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)
 {
index e9ccc4477dc3c37440c96fb041027cec8c89b21c..0604426045e5b5e426b2736b340329692807e84b 100644 (file)
@@ -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);
 
index 8baab371d23561aa9242c260b9f23843f0f87685..f234a593f0a2fa73d676cca07de3f750002c747d 100644 (file)
@@ -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);
index 272c0704246fdc37ff5dab2c10518dbfea2709f2..084672fbe7cd846c60f3fa558a54ea0a1889b14c 100644 (file)
@@ -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(); }
index fff05fb3c459f1a669770d7dd4ae00dcd0745827..ef57e6d832f4128099e090079b9bc3d15aa8a8ce 100644 (file)
@@ -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)
 {
index 7e58fd060ecceadb008e7d0308d7d1339be38c5d..4cc142335e1125b338cbf77ba13fb19a076b9e29 100644 (file)
@@ -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
index 2001a1623b7c2df385e4a528a8344d285144cc73..2944652ffc63bc1efe545e150d6756c5dfe605a7 100644 (file)
@@ -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);
index d17d46bc7d94ad247e354009c0fca893ad76e7a3..bec9a61bfa894cb92bc1b4b38aebf3bf6235535f 100644 (file)
@@ -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);
 }