/* * Copyright (C) 2012 Reto Buerki * Copyright (C) 2012 Adrian-Ken Rueegsegger * HSR Hochschule fuer Technik Rapperswil * * 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; either version 2 of the License, or (at your * option) any later version. See . * * 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 #include #include #include #include "tkm_private_key.h" #include "tkm_cred.h" typedef struct private_tkm_cred_t private_tkm_cred_t; /** * Private data of a tkm_cred_t object. */ struct private_tkm_cred_t { /** * Public tkm_cred_t interface. */ tkm_cred_t public; /** * In-memory credential set. */ mem_cred_t *creds; /** * Key-id hashtable. */ hashtable_t *known_keys; /** * rwlock for hashtable. */ rwlock_t *lock; }; METHOD(credential_set_t, create_private_enumerator, enumerator_t*, private_tkm_cred_t *this, key_type_t type, identification_t *id) { identification_t *entry; if (!id) { return this->known_keys->create_enumerator(this->known_keys); } this->lock->write_lock(this->lock); entry = this->known_keys->get(this->known_keys, id); if (!entry) { identification_t *clone = id->clone(id); tkm_private_key_t *key = tkm_private_key_init(id); DBG1(DBG_CFG, "adding private key proxy for id '%Y'", clone); if (!key) { DBG1(DBG_CFG, "unable to create private key for id '%Y'", clone); this->lock->unlock(this->lock); return NULL; } this->creds->add_key(this->creds, (private_key_t *)key); entry = this->known_keys->put(this->known_keys, clone, clone); } this->lock->unlock(this->lock); return this->creds->set.create_private_enumerator(&this->creds->set, type, id); } METHOD(tkm_cred_t, destroy, void, private_tkm_cred_t *this) { enumerator_t *enumerator; identification_t *entry; enumerator = this->known_keys->create_enumerator(this->known_keys); while (enumerator->enumerate(enumerator, NULL, &entry)) { entry->destroy(entry); } enumerator->destroy(enumerator); this->known_keys->destroy(this->known_keys); this->creds->destroy(this->creds); this->lock->destroy(this->lock); free(this); } /** * Hashtable hash function. */ static u_int hash(identification_t *id) { return chunk_hash(id->get_encoding(id)); } /** * Hashtable equals function. */ static bool equals(identification_t *a, identification_t *b) { return a->equals(a, b); } /** * See header */ tkm_cred_t *tkm_cred_create() { private_tkm_cred_t *this; INIT(this, .public = { .set = { .create_shared_enumerator = (void*)return_null, .create_private_enumerator = _create_private_enumerator, .create_cert_enumerator = (void*)return_null, .create_cdp_enumerator = (void*)return_null, .cache_cert = (void*)nop, }, .destroy = _destroy, }, .creds = mem_cred_create(), .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), .known_keys = hashtable_create((hashtable_hash_t)hash, (hashtable_equals_t)equals, 4), ); return &this->public; }