svn rev #22919: branches/enc-perf/src/ include/ lib/crypto/krb/ lib/crypto/krb/dk/

ghudson@MIT.EDU ghudson at MIT.EDU
Sun Oct 18 14:28:27 EDT 2009


http://src.mit.edu/fisheye/changelog/krb5/?cs=22919
Commit By: ghudson
Log Message:
Implement derived key caching.  For now, omit the "nocache" flag, because it
would add code bulk without necessarily saving much work.



Changed Files:
U   branches/enc-perf/src/include/k5-int.h
U   branches/enc-perf/src/lib/crypto/krb/dk/derive.c
U   branches/enc-perf/src/lib/crypto/krb/key.c
Modified: branches/enc-perf/src/include/k5-int.h
===================================================================
--- branches/enc-perf/src/include/k5-int.h	2009-10-18 17:17:42 UTC (rev 22918)
+++ branches/enc-perf/src/include/k5-int.h	2009-10-18 18:28:26 UTC (rev 22919)
@@ -635,10 +635,17 @@
 		       struct addrlist *, enum locate_service_type svc,
 		       int sockettype, int family);
 
+struct derived_key {
+    krb5_data constant;
+    krb5_key dkey;
+    struct derived_key *next;
+};
+
 /* Internal structure of an opaque key identifier */
 struct krb5_key_st {
     krb5_keyblock keyblock;
     int refcount;
+    struct derived_key *derived;
 };
 
 /* new encryption provider api */

Modified: branches/enc-perf/src/lib/crypto/krb/dk/derive.c
===================================================================
--- branches/enc-perf/src/lib/crypto/krb/dk/derive.c	2009-10-18 17:17:42 UTC (rev 22918)
+++ branches/enc-perf/src/lib/crypto/krb/dk/derive.c	2009-10-18 18:28:26 UTC (rev 22919)
@@ -27,6 +27,63 @@
 #include "k5-int.h"
 #include "dk.h"
 
+static krb5_key
+find_cached_dkey(struct derived_key *list, const krb5_data *constant)
+{
+    for (; list; list = list->next) {
+	if (data_eq(list->constant, *constant)) {
+	    krb5_k_reference_key(NULL, list->dkey);
+	    return list->dkey;
+	}
+    }
+    return NULL;
+}
+
+static krb5_error_code
+add_cached_dkey(krb5_key key, const krb5_data *constant,
+		const krb5_keyblock *dkeyblock, krb5_key *cached_dkey)
+{
+    krb5_key dkey;
+    krb5_error_code ret;
+    struct derived_key *dkent = NULL;
+    char *data = NULL;
+
+    /* Allocate fields for the new entry. */
+    dkent = malloc(sizeof(*dkent));
+    if (dkent == NULL)
+	goto cleanup;
+    data = malloc(constant->length);
+    if (data == NULL)
+	goto cleanup;
+    ret = krb5_k_create_key(NULL, dkeyblock, &dkey);
+    if (ret != 0)
+	goto cleanup;
+
+    /* Add the new entry to the list. */
+    memcpy(data, constant->data, constant->length);
+    dkent->dkey = dkey;
+    dkent->constant.data = data;
+    dkent->constant.length = constant->length;
+    dkent->next = key->derived;
+    key->derived = dkent;
+
+    /* Return a "copy" of the cached key. */
+    krb5_k_reference_key(NULL, dkey);
+    *cached_dkey = dkey;
+    return 0;
+
+cleanup:
+    free(dkent);
+    free(data);
+    return ENOMEM;
+}
+
+/*
+ * Compute a derived key into the keyblock outkey.  This variation on
+ * krb5_derive_key does not cache the result, as it is only used
+ * directly in situations which are not expected to be repeated with
+ * the same inkey and constant.
+ */
 krb5_error_code
 krb5_derive_keyblock(const struct krb5_enc_provider *enc,
 		     krb5_key inkey, krb5_keyblock *outkey,
@@ -111,22 +168,33 @@
 {
     krb5_keyblock keyblock;
     krb5_error_code ret;
+    krb5_key dkey;
 
     *outkey = NULL;
 
-    /* Set up a temporary keyblock. */
+    /* Check for a cached result. */
+    dkey = find_cached_dkey(inkey->derived, in_constant);
+    if (dkey != NULL) {
+	*outkey = dkey;
+	return 0;
+    }
+
+    /* Derive into a temporary keyblock. */
     keyblock.length = enc->keylength;
     keyblock.contents = malloc(keyblock.length);
     if (keyblock.contents == NULL)
 	return ENOMEM;
-
     ret = krb5_derive_keyblock(enc, inkey, &keyblock, in_constant);
     if (ret)
 	goto cleanup;
 
-    /* Convert the keyblock to a key. */
-    ret = krb5_k_create_key(NULL, &keyblock, outkey);
+    /* Cache the derived key. */
+    ret = add_cached_dkey(inkey, in_constant, &keyblock, &dkey);
+    if (ret != 0)
+	goto cleanup;
 
+    *outkey = dkey;
+
 cleanup:
     zapfree(keyblock.contents, keyblock.length);
     return ret;

Modified: branches/enc-perf/src/lib/crypto/krb/key.c
===================================================================
--- branches/enc-perf/src/lib/crypto/krb/key.c	2009-10-18 17:17:42 UTC (rev 22918)
+++ branches/enc-perf/src/lib/crypto/krb/key.c	2009-10-18 18:28:26 UTC (rev 22919)
@@ -50,6 +50,7 @@
 	goto cleanup;
 
     key->refcount = 1;
+    key->derived = NULL;
     *out = key;
     return 0;
 
@@ -68,8 +69,17 @@
 void KRB5_CALLCONV
 krb5_k_free_key(krb5_context context, krb5_key key)
 {
+    struct derived_key *dk;
+
     if (key == NULL || --key->refcount > 0)
 	return;
+
+    /* Free the derived key cache. */
+    while ((dk = key->derived) != NULL) {
+	key->derived = dk->next;
+	krb5_k_free_key(context, dk->dkey);
+	free(dk);
+    }
     krb5int_c_free_keyblock_contents(context, &key->keyblock);
 }
 




More information about the cvs-krb5 mailing list