]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Implement derived key caching. For now, omit the "nocache" flag, because it
authorGreg Hudson <ghudson@mit.edu>
Sun, 18 Oct 2009 18:28:26 +0000 (18:28 +0000)
committerGreg Hudson <ghudson@mit.edu>
Sun, 18 Oct 2009 18:28:26 +0000 (18:28 +0000)
would add code bulk without necessarily saving much work.

git-svn-id: svn://anonsvn.mit.edu/krb5/branches/enc-perf@22919 dc483132-0cff-0310-8789-dd5450dbe970

src/include/k5-int.h
src/lib/crypto/krb/dk/derive.c
src/lib/crypto/krb/key.c

index 34ce10d92182eda6622dcc897cb62b1e22b2b373..95398c0a34fa629fca2b6d06c81d069989a9d7a0 100644 (file)
@@ -635,10 +635,17 @@ krb5int_locate_server (krb5_context, const krb5_data *realm,
                       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 */
index ce55663107595964eac0091fa897244a0d0be862..c2638e804efb3ff025d6825674a036fb858789d4 100644 (file)
 #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,21 +168,32 @@ krb5_derive_key(const struct krb5_enc_provider *enc,
 {
     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);
index 1fb9bcc83757197f4026cf173dcba27eab7aafae..4ea72b478f02fa5df3c54967a9642bf2d1de7b98 100644 (file)
@@ -50,6 +50,7 @@ krb5_k_create_key(krb5_context context, const krb5_keyblock *key_data,
        goto cleanup;
 
     key->refcount = 1;
+    key->derived = NULL;
     *out = key;
     return 0;
 
@@ -68,8 +69,17 @@ krb5_k_reference_key(krb5_context context, krb5_key key)
 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);
 }