Created SILC GIT repository.
[silc.git] / lib / silcskr / silcskr.c
diff --git a/lib/silcskr/silcskr.c b/lib/silcskr/silcskr.c
deleted file mode 100644 (file)
index 7459d43..0000000
+++ /dev/null
@@ -1,990 +0,0 @@
-/*
-
-  silcskr.c
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2005 - 2007 Pekka Riikonen
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; version 2 of the License.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-*/
-
-#include "silc.h"
-#include "silcskr.h"
-
-/************************** Types and definitions ***************************/
-
-/* Search constraints */
-typedef enum {
-  SILC_SKR_FIND_PKCS_TYPE,
-  SILC_SKR_FIND_USERNAME,
-  SILC_SKR_FIND_HOST,
-  SILC_SKR_FIND_REALNAME,
-  SILC_SKR_FIND_EMAIL,
-  SILC_SKR_FIND_ORG,
-  SILC_SKR_FIND_COUNTRY,
-  SILC_SKR_FIND_PUBLIC_KEY,
-  SILC_SKR_FIND_CONTEXT,
-  SILC_SKR_FIND_USAGE,         /* Never added as key specific */
-} SilcSKRFindType;
-
-/* Hash table key context */
-typedef struct {
-  SilcSKRFindType type;                /* Type of key */
-  void *data;                  /* Hash table key */
-} *SilcSKREntry, SilcSKREntryStruct;
-
-/* Foreach user context when finding entries from hash table */
-typedef struct {
-  SilcDList list;
-  void *key_context;
-  SilcSKRKeyUsage usage;
-} SilcSKRFindForeach;
-
-#if defined(SILC_DEBUG)
-static const char *find_name[] = {
-  "PKCS TYPE ",
-  "USERNAME  ",
-  "HOST      ",
-  "REALNAME  ",
-  "EMAIL     ",
-  "ORG       ",
-  "COUNTRY   ",
-  "PUBLIC KEY",
-  "CONTEXT   ",
-  "USAGE     ",
-  NULL
-};
-#endif /* SILC_DEBUG */
-
-/************************ Static utility functions **************************/
-
-#if defined(SILC_DEBUG)
-
-/* Returns search constraint string */
-
-static void silc_skr_type_string(SilcSKRFindType type, void *data,
-                                char *retbuf, SilcUInt32 retbuf_size)
-{
-  switch (type) {
-  case SILC_SKR_FIND_PKCS_TYPE:
-  case SILC_SKR_FIND_USAGE:
-    silc_snprintf(retbuf, retbuf_size, "[%s] [%d]", find_name[type],
-                 (int)SILC_PTR_TO_32(data));
-    break;
-
-  case SILC_SKR_FIND_PUBLIC_KEY:
-  case SILC_SKR_FIND_CONTEXT:
-    silc_snprintf(retbuf, retbuf_size, "[%s] [%p]", find_name[type], data);
-    break;
-
-  default:
-    silc_snprintf(retbuf, retbuf_size, "[%s] [%s]", find_name[type],
-                 (char *)data);
-  }
-}
-#endif /* SILC_DEBUG */
-
-/* Hash table destructor for search constraints */
-
-static void silc_skr_find_destructor(void *key, void *context,
-                                    void *user_context)
-{
-  SilcSKRFindType type = SILC_PTR_TO_32(key);
-  SilcPKCSType pkcs_type = SILC_PTR_TO_32(user_context);
-
-  switch (type) {
-  case SILC_SKR_FIND_PKCS_TYPE:
-  case SILC_SKR_FIND_USAGE:
-  case SILC_SKR_FIND_CONTEXT:
-    break;
-
-  case SILC_SKR_FIND_PUBLIC_KEY:
-    silc_pkcs_public_key_free(context);
-    break;
-
-  default:
-    /* In SILC Public key all entries are referenced from the public key
-       so don't free them.  This test is valid only when removing key
-       from the repository. */
-    if (pkcs_type == SILC_PKCS_SILC)
-      break;
-
-    silc_free(context);
-  }
-}
-
-/* Hash table destructor for key entries */
-
-static void silc_skr_destructor(void *key, void *context, void *user_context)
-{
-  SilcSKREntry type = key;
-  SilcSKRKeyInternal entry = context;
-  SilcPKCSType pkcs_type = silc_pkcs_get_type(entry->key.key);
-
-  /* Destroy search data, except for SILC_SKR_FIND_PUBLIC_KEY because it
-     shares same context with the key entry. */
-  if (SILC_PTR_TO_32(type->type) != SILC_SKR_FIND_PUBLIC_KEY)
-    silc_skr_find_destructor(SILC_32_TO_PTR(type->type), type->data,
-                            SILC_32_TO_PTR(pkcs_type));
-  silc_free(type);
-
-  /* Destroy key */
-  entry->refcnt--;
-  if (entry->refcnt > 0)
-    return;
-
-  SILC_LOG_DEBUG(("Freeing public key %p", entry->key.key));
-
-  silc_pkcs_public_key_free(entry->key.key);
-  silc_free(entry);
-}
-
-/* Hash table hash function for key entries */
-
-static SilcUInt32 silc_skr_hash(void *key, void *user_context)
-{
-  SilcSKREntry type = key;
-
-  switch (type->type) {
-  case SILC_SKR_FIND_PKCS_TYPE:
-  case SILC_SKR_FIND_CONTEXT:
-    return type->type + (type->type ^ SILC_PTR_TO_32(type->data));
-    break;
-
-  case SILC_SKR_FIND_PUBLIC_KEY:
-    return type->type + silc_hash_public_key(type->data, user_context);
-    break;
-
-  default:
-    break;
-  }
-
-  return type->type + silc_hash_string_case(type->data, user_context);
-}
-
-/* Hash table comparison function for key entries */
-
-static SilcBool silc_skr_compare(void *key1, void *key2, void *user_context)
-{
-  SilcSKREntry type1 = key1;
-  SilcSKREntry type2 = key2;
-
-  if (type1->type != type2->type)
-    return FALSE;
-
-  switch (type1->type) {
-  case SILC_SKR_FIND_PKCS_TYPE:
-  case SILC_SKR_FIND_CONTEXT:
-    return type1->data == type2->data;
-    break;
-
-  case SILC_SKR_FIND_PUBLIC_KEY:
-    return silc_hash_public_key_compare(type1->data, type2->data,
-                                       user_context);
-    break;
-
-  default:
-    break;
-  }
-
-  return silc_utf8_strcasecmp((const char *)type1->data,
-                             (const char *)type2->data);
-}
-
-/* Foreach function for finding entries in the repository */
-
-static void silc_skr_find_foreach(void *key, void *context,
-                                 void *user_context)
-{
-  SilcSKRFindForeach *f = user_context;
-  SilcSKRKeyInternal k = context;
-
-  if (k) {
-    /* If key context is present, it must match the context in the key.
-       This is used only internally when adding keys, to check if the key
-       is added with same context. */
-    if (f->key_context && f->key_context != k->key.key_context)
-      return;
-
-    /* Check for usage bits.  At least one usage bit must be set. */
-    if (f->usage && k->key.usage && (f->usage & k->key.usage) == 0)
-      return;
-
-    silc_dlist_add(f->list, k);
-  }
-}
-
-/* Finds entry from repository by search constraint type and data */
-
-static SilcBool silc_skr_find_entry(SilcSKR skr,
-                                   SilcSKRStatus *status,
-                                   SilcSKRFindType type,
-                                   void *type_data,
-                                   SilcDList *results,
-                                   void *key_context,
-                                   SilcSKRKeyUsage usage)
-{
-  SilcSKREntryStruct find;
-  SilcSKRFindForeach f;
-
-  f.list = silc_dlist_init();
-  if (!f.list) {
-    *status |= SILC_SKR_NO_MEMORY;
-    return FALSE;
-  }
-  f.key_context = key_context;
-  f.usage = usage;
-
-  find.type = type;
-  find.data = type_data;
-
-  silc_hash_table_find_foreach(skr->keys, (void *)&find,
-                              silc_skr_find_foreach, &f);
-
-  if (!silc_dlist_count(f.list)) {
-    *status |= SILC_SKR_NOT_FOUND;
-    silc_dlist_uninit(f.list);
-    return FALSE;
-  }
-
-  if (results)
-    *results = f.list;
-  else
-    silc_dlist_uninit(f.list);
-
-  return TRUE;
-}
-
-/* Add a key by search constraint type to repository */
-
-static SilcBool silc_skr_add_entry(SilcSKR skr, SilcSKRFindType type,
-                                  void *type_data, SilcSKRKeyInternal key)
-{
-  SilcSKREntry entry;
-
-#if defined(SILC_DEBUG)
-  char tmp[256];
-  memset(tmp, 0, sizeof(tmp));
-  silc_skr_type_string(type, type_data, tmp, sizeof(tmp) - 1);
-  SILC_LOG_DEBUG(("Search constraint %s", tmp));
-#endif /* SILC_DEBUG */
-
-  entry = silc_calloc(1, sizeof(*entry));
-  if (!entry)
-    return FALSE;
-
-  entry->type = type;
-  entry->data = type_data;
-
-  return silc_hash_table_add(skr->keys, entry, key);
-}
-
-/* Delete a key by search constraint type from repository */
-
-static SilcBool silc_skr_del_entry(SilcSKR skr, SilcSKRFindType type,
-                                  void *type_data, SilcSKRKeyInternal key)
-{
-  SilcSKREntryStruct entry;
-
-  if (!type_data)
-    return FALSE;
-
-  entry.type = type;
-  entry.data = type_data;
-
-  return silc_hash_table_del_by_context(skr->keys, &entry, key);
-}
-
-/* This performs AND operation.  Any entry already in `results' that is not
-   in `list' will be removed from `results'. */
-
-static SilcBool silc_skr_results_and(SilcDList list, SilcSKRStatus *status,
-                                    SilcDList *results)
-{
-  SilcSKRKeyInternal entry, r;
-
-  if (*results == NULL) {
-    *results = silc_dlist_init();
-    if (*results == NULL) {
-      *status |= SILC_SKR_NO_MEMORY;
-      return FALSE;
-    }
-  }
-
-  /* If results is empty, just add all entries from list to results */
-  if (!silc_dlist_count(*results)) {
-    silc_dlist_start(list);
-    while ((entry = silc_dlist_get(list)) != SILC_LIST_END)
-      silc_dlist_add(*results, entry);
-
-    return TRUE;
-  }
-
-  silc_dlist_start(*results);
-  while ((entry = silc_dlist_get(*results)) != SILC_LIST_END) {
-
-    /* Check if this entry is in list  */
-    silc_dlist_start(list);
-    while ((r = silc_dlist_get(list)) != SILC_LIST_END) {
-      if (r == entry)
-       break;
-    }
-    if (r != SILC_LIST_END)
-      continue;
-
-    /* Remove from results */
-    silc_dlist_del(*results, entry);
-  }
-
-  /* If results became empty, we did not find any key */
-  if (!silc_dlist_count(*results)) {
-    SILC_LOG_DEBUG(("Not all search constraints found"));
-    *status |= SILC_SKR_NOT_FOUND;
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
-
-/***************************** SILC Public Key ******************************/
-
-/* Add SILC style public key to repository */
-
-static SilcSKRStatus silc_skr_add_silc(SilcSKR skr,
-                                      SilcPublicKey public_key,
-                                      SilcSKRKeyUsage usage,
-                                      void *key_context,
-                                      SilcSKRKey *return_key)
-{
-  SilcSKRKeyInternal key;
-  SilcSKRStatus status = SILC_SKR_ERROR;
-  SilcPublicKeyIdentifier ident;
-  SilcSILCPublicKey silc_pubkey;
-#if defined(SILC_DEBUG)
-  char tmp[256];
-#endif /* SILC_DEBUG */
-
-  /* Get the SILC public key */
-  silc_pubkey = silc_pkcs_public_key_get_pkcs(SILC_PKCS_SILC, public_key);
-  ident = &silc_pubkey->identifier;
-
-  SILC_LOG_DEBUG(("Adding SILC public key %p [%s], context %p",
-                 public_key, ident->username, key_context));
-
-  silc_mutex_lock(skr->lock);
-
-  /* Check that this key hasn't been added already */
-  if (silc_skr_find_entry(skr, &status, SILC_SKR_FIND_PUBLIC_KEY,
-                         public_key, NULL, key_context, 0)) {
-    silc_mutex_unlock(skr->lock);
-    SILC_LOG_DEBUG(("Key already added"));
-    return status | SILC_SKR_ALREADY_EXIST;
-  }
-
-  /* Allocate key entry */
-  key = silc_calloc(1, sizeof(*key));
-  if (!key) {
-    silc_mutex_unlock(skr->lock);
-    return status | SILC_SKR_NO_MEMORY;
-  }
-
-  key->key.usage = usage;
-  key->key.key = public_key;
-  key->key.key_context = key_context;
-
-#if defined(SILC_DEBUG)
-  silc_skr_type_string(SILC_SKR_FIND_USAGE, SILC_32_TO_PTR(usage),
-                      tmp, sizeof(tmp) - 1);
-  SILC_LOG_DEBUG((" Search constraint %s", tmp));
-#endif /* SILC_DEBUG */
-
-  /* Add key specifics */
-
-  if (!silc_skr_add_entry(skr, SILC_SKR_FIND_PUBLIC_KEY,
-                         public_key, key))
-    goto err;
-  key->refcnt++;
-
-  if (!silc_skr_add_entry(skr, SILC_SKR_FIND_PKCS_TYPE,
-                         SILC_32_TO_PTR(SILC_PKCS_SILC), key))
-    goto err;
-  key->refcnt++;
-
-  if (ident->username) {
-    if (!silc_skr_add_entry(skr, SILC_SKR_FIND_USERNAME,
-                           ident->username, key))
-      goto err;
-    key->refcnt++;
-  }
-
-  if (ident->host) {
-    if (!silc_skr_add_entry(skr, SILC_SKR_FIND_HOST,
-                           ident->host, key))
-      goto err;
-    key->refcnt++;
-  }
-
-  if (ident->realname) {
-    if (!silc_skr_add_entry(skr, SILC_SKR_FIND_REALNAME,
-                           ident->realname, key))
-      goto err;
-    key->refcnt++;
-  }
-
-  if (ident->email) {
-    if (!silc_skr_add_entry(skr, SILC_SKR_FIND_EMAIL,
-                           ident->email, key))
-      goto err;
-    key->refcnt++;
-  }
-
-  if (ident->org) {
-    if (!silc_skr_add_entry(skr, SILC_SKR_FIND_ORG,
-                           ident->org, key))
-      goto err;
-    key->refcnt++;
-  }
-
-  if (ident->country) {
-    if (!silc_skr_add_entry(skr, SILC_SKR_FIND_COUNTRY,
-                           ident->country, key))
-      goto err;
-    key->refcnt++;
-  }
-
-  if (key_context) {
-    if (!silc_skr_add_entry(skr, SILC_SKR_FIND_CONTEXT,
-                           key_context, key))
-      goto err;
-    key->refcnt++;
-  }
-
-  silc_mutex_unlock(skr->lock);
-
-  if (return_key)
-    *return_key = (SilcSKRKey)key;
-
-  return SILC_SKR_OK;
-
- err:
-  silc_mutex_unlock(skr->lock);
-  return status;
-}
-
-/* Add SILC style public key to repository, and only the public key, not
-   other details from the key. */
-
-static SilcSKRStatus silc_skr_add_silc_simple(SilcSKR skr,
-                                             SilcPublicKey public_key,
-                                             SilcSKRKeyUsage usage,
-                                             void *key_context,
-                                             SilcSKRKey *return_key)
-{
-  SilcSKRKeyInternal key;
-  SilcSKRStatus status = SILC_SKR_ERROR;
-#if defined(SILC_DEBUG)
-  char tmp[256];
-#endif /* SILC_DEBUG */
-
-  SILC_LOG_DEBUG(("Adding SILC public key"));
-
-  silc_mutex_lock(skr->lock);
-
-  /* Check that this key hasn't been added already */
-  if (silc_skr_find_entry(skr, &status, SILC_SKR_FIND_PUBLIC_KEY,
-                         public_key, NULL, key_context, 0)) {
-    silc_mutex_unlock(skr->lock);
-    SILC_LOG_DEBUG(("Key already added"));
-    return status | SILC_SKR_ALREADY_EXIST;
-  }
-
-  /* Allocate key entry */
-  key = silc_calloc(1, sizeof(*key));
-  if (!key) {
-    silc_mutex_unlock(skr->lock);
-    return status | SILC_SKR_NO_MEMORY;
-  }
-
-  key->key.usage = usage;
-  key->key.key = public_key;
-  key->key.key_context = key_context;
-
-#if defined(SILC_DEBUG)
-  silc_skr_type_string(SILC_SKR_FIND_USAGE, SILC_32_TO_PTR(usage),
-                      tmp, sizeof(tmp) - 1);
-  SILC_LOG_DEBUG(("Search cons %s", tmp));
-#endif /* SILC_DEBUG */
-
-  /* Add key specifics */
-
-  if (!silc_skr_add_entry(skr, SILC_SKR_FIND_PUBLIC_KEY,
-                         public_key, key))
-    goto err;
-  key->refcnt++;
-
-  if (key_context) {
-    if (!silc_skr_add_entry(skr, SILC_SKR_FIND_CONTEXT,
-                           key_context, key))
-      goto err;
-    key->refcnt++;
-  }
-
-  silc_mutex_unlock(skr->lock);
-
-  if (return_key)
-    *return_key = (SilcSKRKey)key;
-
-  return SILC_SKR_OK;
-
- err:
-  silc_mutex_unlock(skr->lock);
-  return status;
-}
-
-/* Deletes SILC public key from repository */
-
-static SilcSKRStatus silc_skr_del_silc_public_key(SilcSKR skr,
-                                                 SilcPublicKey public_key,
-                                                 void *key_context)
-{
-  SilcSKRStatus status = SILC_SKR_ERROR;
-  SilcPublicKeyIdentifier ident;
-  SilcSILCPublicKey silc_pubkey;
-  SilcSKRKeyInternal key;
-  SilcDList entry;
-
-  /* Get the SILC public key */
-  silc_pubkey = silc_pkcs_public_key_get_pkcs(SILC_PKCS_SILC, public_key);
-  ident = &silc_pubkey->identifier;
-
-  SILC_LOG_DEBUG(("Deleting SILC public key [%s]", ident->username));
-
-  silc_mutex_lock(skr->lock);
-
-  /* Check that this key exists */
-  if (!silc_skr_find_entry(skr, &status, SILC_SKR_FIND_PUBLIC_KEY,
-                          public_key, &entry, key_context, 0)) {
-    silc_mutex_unlock(skr->lock);
-    SILC_LOG_DEBUG(("Key does not exist"));
-    return status | SILC_SKR_NOT_FOUND;
-  }
-
-  silc_dlist_start(entry);
-  key = silc_dlist_get(entry);
-  silc_dlist_uninit(entry);
-
-  silc_skr_del_entry(skr, SILC_SKR_FIND_PUBLIC_KEY, public_key, key);
-  silc_skr_del_entry(skr, SILC_SKR_FIND_PKCS_TYPE,
-                    SILC_32_TO_PTR(SILC_PKCS_SILC), key);
-  silc_skr_del_entry(skr, SILC_SKR_FIND_USERNAME, ident->username, key);
-  silc_skr_del_entry(skr, SILC_SKR_FIND_HOST, ident->host, key);
-  silc_skr_del_entry(skr, SILC_SKR_FIND_REALNAME, ident->realname, key);
-  silc_skr_del_entry(skr, SILC_SKR_FIND_EMAIL, ident->email, key);
-  silc_skr_del_entry(skr, SILC_SKR_FIND_ORG, ident->org, key);
-  silc_skr_del_entry(skr, SILC_SKR_FIND_COUNTRY, ident->country, key);
-  silc_skr_del_entry(skr, SILC_SKR_FIND_CONTEXT, key_context, key);
-
-  silc_mutex_unlock(skr->lock);
-
-  return SILC_SKR_OK;
-}
-
-
-/**************************** Key Repository API ****************************/
-
-/* Allocate key repository */
-
-SilcSKR silc_skr_alloc(void)
-{
-  SilcSKR skr;
-
-  skr = silc_calloc(1, sizeof(*skr));
-  if (!skr)
-    return NULL;
-
-  if (!silc_skr_init(skr)) {
-    silc_skr_free(skr);
-    return NULL;
-  }
-
-  return skr;
-}
-
-/* Free key repository */
-
-void silc_skr_free(SilcSKR skr)
-{
-  silc_skr_uninit(skr);
-  silc_free(skr);
-}
-
-/* Initializes key repository */
-
-SilcBool silc_skr_init(SilcSKR skr)
-{
-  if (!silc_mutex_alloc(&skr->lock))
-    return FALSE;
-
-  skr->keys = silc_hash_table_alloc(NULL, 0, silc_skr_hash, NULL,
-                                   silc_skr_compare, NULL,
-                                   silc_skr_destructor, NULL, TRUE);
-  if (!skr->keys)
-    return FALSE;
-
-  return TRUE;
-}
-
-/* Uninitializes key repository */
-
-void silc_skr_uninit(SilcSKR skr)
-{
-  if (skr->keys)
-    silc_hash_table_free(skr->keys);
-  silc_mutex_free(skr->lock);
-}
-
-/* Adds public key to key repository */
-
-SilcSKRStatus silc_skr_add_public_key(SilcSKR skr,
-                                     SilcPublicKey public_key,
-                                     SilcSKRKeyUsage usage,
-                                     void *key_context,
-                                     SilcSKRKey *return_key)
-{
-  SilcPKCSType type;
-
-  if (!public_key)
-    return SILC_SKR_ERROR;
-
-  type = silc_pkcs_get_type(public_key);
-
-  SILC_LOG_DEBUG(("Adding public key %p to repository", public_key));
-
-  switch (type) {
-
-  case SILC_PKCS_SILC:
-    return silc_skr_add_silc(skr, public_key, usage, key_context, return_key);
-    break;
-
-  default:
-    break;
-  }
-
-  return SILC_SKR_ERROR;
-}
-
-/* Adds public key to repository. */
-
-SilcSKRStatus silc_skr_add_public_key_simple(SilcSKR skr,
-                                            SilcPublicKey public_key,
-                                            SilcSKRKeyUsage usage,
-                                            void *key_context,
-                                            SilcSKRKey *return_key)
-{
-  SilcPKCSType type;
-
-  if (!public_key)
-    return SILC_SKR_ERROR;
-
-  type = silc_pkcs_get_type(public_key);
-
-  SILC_LOG_DEBUG(("Adding public key %p to repository", public_key));
-
-  switch (type) {
-
-  case SILC_PKCS_SILC:
-    return silc_skr_add_silc_simple(skr, public_key, usage, key_context,
-                                   return_key);
-    break;
-
-  default:
-    break;
-  }
-
-  return SILC_SKR_ERROR;
-}
-
-/* Remove key from repository */
-
-SilcSKRStatus silc_skr_del_public_key(SilcSKR skr,
-                                     SilcPublicKey public_key,
-                                     void *key_context)
-{
-  SilcPKCSType type;
-
-  if (!public_key)
-    return SILC_SKR_ERROR;
-
-  type = silc_pkcs_get_type(public_key);
-
-  SILC_LOG_DEBUG(("Deleting public key %p from repository", public_key));
-
-  switch (type) {
-
-  case SILC_PKCS_SILC:
-    return silc_skr_del_silc_public_key(skr, public_key, key_context);
-    break;
-
-  default:
-    break;
-  }
-
-  return SILC_SKR_ERROR;
-}
-
-/* Reference key */
-
-void silc_skr_ref_public_key(SilcSKR skr, SilcSKRKey key)
-{
-  SilcSKRKeyInternal k = (SilcSKRKeyInternal)key;
-
-  silc_mutex_lock(skr->lock);
-  SILC_LOG_DEBUG(("SKR key %p ref %d -> %d", k->refcnt, k->refcnt + 1));
-  k->refcnt++;
-  silc_mutex_unlock(skr->lock);
-}
-
-/* Release key reference. */
-
-void silc_skr_unref_public_key(SilcSKR skr, SilcSKRKey key)
-{
-  SilcSKRKeyInternal k = (SilcSKRKeyInternal)key;
-
-  silc_mutex_lock(skr->lock);
-
-  SILC_LOG_DEBUG(("SKR key %p ref %d -> %d", k->refcnt, k->refcnt - 1));
-  k->refcnt--;
-
-  if (k->refcnt == 0) {
-    /* If reference is zero, the key has been removed from the repository
-       already.  Just destroy the public key. */
-    silc_pkcs_public_key_free(key->key);
-    silc_free(key);
-  }
-
-  silc_mutex_unlock(skr->lock);
-}
-
-
-/************************** Search Constraints API **************************/
-
-/* Allocate search constraints */
-
-SilcSKRFind silc_skr_find_alloc(void)
-{
-  SilcSKRFind find;
-
-  find = silc_calloc(1, sizeof(*find));
-  if (!find)
-    return NULL;
-
-  find->constr = silc_hash_table_alloc(NULL, 0, silc_hash_uint,
-                                      NULL, NULL, NULL,
-                                      silc_skr_find_destructor, NULL, TRUE);
-  if (!find->constr) {
-    silc_skr_find_free(find);
-    return NULL;
-  }
-
-  return find;
-}
-
-/* Free search constraints */
-
-void silc_skr_find_free(SilcSKRFind find)
-{
-  if (find->constr)
-    silc_hash_table_free(find->constr);
-  silc_free(find);
-}
-
-SilcBool silc_skr_find_set_pkcs_type(SilcSKRFind find, SilcPKCSType type)
-{
-  return silc_hash_table_add(find->constr,
-                            SILC_32_TO_PTR(SILC_SKR_FIND_PKCS_TYPE),
-                            SILC_32_TO_PTR(type));
-}
-
-SilcBool silc_skr_find_set_username(SilcSKRFind find, const char *username)
-{
-  void *c = silc_memdup(username, strlen(username));
-  if (!c)
-    return FALSE;
-  return silc_hash_table_add(find->constr,
-                            SILC_32_TO_PTR(SILC_SKR_FIND_USERNAME), c);
-}
-
-SilcBool silc_skr_find_set_host(SilcSKRFind find, const char *host)
-{
-  void *c = silc_memdup(host, strlen(host));
-  if (!c)
-    return FALSE;
-  return silc_hash_table_add(find->constr,
-                            SILC_32_TO_PTR(SILC_SKR_FIND_HOST), c);
-}
-
-SilcBool silc_skr_find_set_realname(SilcSKRFind find, const char *realname)
-{
-  void *c = silc_memdup(realname, strlen(realname));
-  if (!c)
-    return FALSE;
-  return silc_hash_table_add(find->constr,
-                            SILC_32_TO_PTR(SILC_SKR_FIND_REALNAME), c);
-}
-
-SilcBool silc_skr_find_set_email(SilcSKRFind find, const char *email)
-{
-  void *c = silc_memdup(email, strlen(email));
-  if (!c)
-    return FALSE;
-  return silc_hash_table_add(find->constr,
-                            SILC_32_TO_PTR(SILC_SKR_FIND_EMAIL), c);
-}
-
-SilcBool silc_skr_find_set_org(SilcSKRFind find, const char *org)
-{
-  void *c = silc_memdup(org, strlen(org));
-  if (!c)
-    return FALSE;
-  return silc_hash_table_add(find->constr,
-                            SILC_32_TO_PTR(SILC_SKR_FIND_ORG), c);
-}
-
-SilcBool silc_skr_find_set_country(SilcSKRFind find, const char *country)
-{
-  void *c = silc_memdup(country, strlen(country));
-  if (!c)
-    return FALSE;
-  return silc_hash_table_add(find->constr,
-                            SILC_32_TO_PTR(SILC_SKR_FIND_COUNTRY), c);
-}
-
-SilcBool silc_skr_find_set_public_key(SilcSKRFind find,
-                                     SilcPublicKey public_key)
-{
-  SilcPublicKey pk = silc_pkcs_public_key_copy(public_key);
-  if (!pk)
-    return FALSE;
-  return silc_hash_table_add(find->constr,
-                            SILC_32_TO_PTR(SILC_SKR_FIND_PUBLIC_KEY), pk);
-}
-
-SilcBool silc_skr_find_set_context(SilcSKRFind find, void *context)
-{
-  if (!context)
-    return TRUE;
-  return silc_hash_table_add(find->constr,
-                            SILC_32_TO_PTR(SILC_SKR_FIND_CONTEXT), context);
-}
-
-SilcBool silc_skr_find_set_usage(SilcSKRFind find, SilcSKRKeyUsage usage)
-{
-  if (!usage)
-    return TRUE;
-  return silc_hash_table_add(find->constr,
-                            SILC_32_TO_PTR(SILC_SKR_FIND_USAGE),
-                            SILC_32_TO_PTR(usage));
-}
-
-/******************************** Search API ********************************/
-
-/* Finds key(s) by the set search constraints.  The callback will be called
-   once keys has been found. */
-/* This is now synchronous function but may later change async */
-
-SilcAsyncOperation silc_skr_find(SilcSKR skr, SilcSchedule schedule,
-                                SilcSKRFind find,
-                                SilcSKRFindCallback callback,
-                                void *callback_context)
-{
-  SilcSKRStatus status = SILC_SKR_ERROR;
-  SilcHashTableList htl;
-  SilcDList list, results = NULL;
-  void *type, *ctx, *usage = NULL;
-#if defined(SILC_DEBUG)
-  char tmp[256];
-#endif /* SILC_DEBUG */
-
-  SILC_LOG_DEBUG(("Finding key from repository"));
-
-  if (!find || !callback)
-    return NULL;
-
-  silc_mutex_lock(skr->lock);
-
-  /* Get usage bits, if searching by them */
-  silc_hash_table_find(find->constr, SILC_32_TO_PTR(SILC_SKR_FIND_USAGE),
-                      NULL, &usage);
-
-#if defined(SILC_DEBUG)
-  if (usage) {
-    memset(tmp, 0, sizeof(tmp));
-    silc_skr_type_string(SILC_SKR_FIND_USAGE, usage, tmp, sizeof(tmp) - 1);
-    SILC_LOG_DEBUG(("Finding key by %s", tmp));
-  }
-#endif /* SILC_DEBUG */
-
-  silc_hash_table_list(find->constr, &htl);
-  while (silc_hash_table_get(&htl, &type, &ctx)) {
-
-    /* SILC_SKR_FIND_USAGE is handled separately while searching the keys. */
-    if ((SilcSKRFindType)SILC_32_TO_PTR(type) == SILC_SKR_FIND_USAGE)
-      continue;
-
-#if defined(SILC_DEBUG)
-    memset(tmp, 0, sizeof(tmp));
-    silc_skr_type_string((SilcSKRFindType)SILC_32_TO_PTR(type),
-                        ctx, tmp, sizeof(tmp) - 1);
-    SILC_LOG_DEBUG(("Finding key by %s", tmp));
-#endif /* SILC_DEBUG */
-
-    /* Find entries by this search constraint */
-    if (!silc_skr_find_entry(skr, &status,
-                            (SilcSKRFindType)SILC_32_TO_PTR(type),
-                            ctx, &list, NULL, SILC_PTR_TO_32(usage))) {
-      SILC_LOG_DEBUG(("Not found"));
-      if (results) {
-       silc_dlist_uninit(results);
-       results = NULL;
-      }
-      break;
-    }
-
-    /* For now, our logic rule is AND.  All constraints must be found
-       to find the key.  Later OR might be added also. */
-    if (!silc_skr_results_and(list, &status, &results)) {
-      SILC_LOG_DEBUG(("Not found"));
-      if (results) {
-       silc_dlist_uninit(results);
-       results = NULL;
-      }
-      silc_dlist_uninit(list);
-      break;
-    }
-
-    silc_dlist_uninit(list);
-  }
-  silc_hash_table_list_reset(&htl);
-
-  silc_mutex_unlock(skr->lock);
-
-  /* Return results */
-  if (!results) {
-    callback(skr, find, status, NULL, callback_context);
-  } else {
-    silc_dlist_start(results);
-    callback(skr, find, SILC_SKR_OK, results, callback_context);
-  }
-
-  return NULL;
-}