added a facility to hand out fingerprinting/key encoding to the pkcs1/pgp/... plugins
This commit is contained in:
@@ -24,6 +24,7 @@ crypto/diffie_hellman.c crypto/diffie_hellman.h \
|
|||||||
crypto/transform.c crypto/transform.h \
|
crypto/transform.c crypto/transform.h \
|
||||||
credentials/credential_factory.c credentials/credential_factory.h \
|
credentials/credential_factory.c credentials/credential_factory.h \
|
||||||
credentials/builder.c credentials/builder.h \
|
credentials/builder.c credentials/builder.h \
|
||||||
|
credentials/keys/key_encoding.c credentials/keys/key_encoding.h \
|
||||||
credentials/keys/private_key.c credentials/keys/private_key.h \
|
credentials/keys/private_key.c credentials/keys/private_key.h \
|
||||||
credentials/keys/public_key.c credentials/keys/public_key.h \
|
credentials/keys/public_key.c credentials/keys/public_key.h \
|
||||||
credentials/keys/shared_key.c credentials/keys/shared_key.h \
|
credentials/keys/shared_key.c credentials/keys/shared_key.h \
|
||||||
|
|||||||
@@ -0,0 +1,256 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009 Martin Willi
|
||||||
|
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* 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 "key_encoding.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <utils/linked_list.h>
|
||||||
|
#include <utils/hashtable.h>
|
||||||
|
#include <utils/mutex.h>
|
||||||
|
|
||||||
|
typedef struct private_key_encoding_t private_key_encoding_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private data of an key_encoding_t object.
|
||||||
|
*/
|
||||||
|
struct private_key_encoding_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public key_encoding_t interface.
|
||||||
|
*/
|
||||||
|
key_encoding_t public;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cached encodings, a table for each encoding_type_t, containing chunk_t*
|
||||||
|
*/
|
||||||
|
hashtable_t *cache[KEY_ENCODING_MAX];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registered encoding fuctions, key_encoder_t
|
||||||
|
*/
|
||||||
|
linked_list_t *encoders;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lock to access cache/encoders
|
||||||
|
*/
|
||||||
|
rwlock_t *lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See header.
|
||||||
|
*/
|
||||||
|
bool key_encoding_args(va_list args, ...)
|
||||||
|
{
|
||||||
|
va_list parts, copy;
|
||||||
|
bool failed = FALSE;
|
||||||
|
|
||||||
|
va_start(parts, args);
|
||||||
|
|
||||||
|
while (!failed)
|
||||||
|
{
|
||||||
|
key_encoding_part_t current, target;
|
||||||
|
chunk_t *out, data;
|
||||||
|
|
||||||
|
/* get the part we are looking for */
|
||||||
|
target = va_arg(parts, key_encoding_part_t);
|
||||||
|
if (target == KEY_PART_END)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
out = va_arg(parts, chunk_t*);
|
||||||
|
|
||||||
|
va_copy(copy, args);
|
||||||
|
while (!failed)
|
||||||
|
{
|
||||||
|
current = va_arg(copy, key_encoding_part_t);
|
||||||
|
if (current == KEY_PART_END)
|
||||||
|
{
|
||||||
|
failed = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
data = va_arg(copy, chunk_t);
|
||||||
|
if (current == target)
|
||||||
|
{
|
||||||
|
*out = data;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
va_end(copy);
|
||||||
|
}
|
||||||
|
va_end(parts);
|
||||||
|
return !failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hashtable hash() function
|
||||||
|
*/
|
||||||
|
static u_int hash(void *key)
|
||||||
|
{
|
||||||
|
return (uintptr_t)key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hashtable equals() function
|
||||||
|
*/
|
||||||
|
static bool equals(void *key1, void *key2)
|
||||||
|
{
|
||||||
|
return key1 == key2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of key_encoding_t.encode
|
||||||
|
*/
|
||||||
|
static bool encode(private_key_encoding_t *this, key_encoding_type_t type,
|
||||||
|
void *cache, chunk_t *encoding, ...)
|
||||||
|
{
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
va_list args, copy;
|
||||||
|
key_encoder_t encode;
|
||||||
|
bool success = FALSE;
|
||||||
|
chunk_t *chunk;
|
||||||
|
|
||||||
|
if (type >= KEY_ENCODING_MAX || type < 0)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
this->lock->read_lock(this->lock);
|
||||||
|
if (cache)
|
||||||
|
{
|
||||||
|
chunk = this->cache[type]->get(this->cache[type], cache);
|
||||||
|
if (chunk)
|
||||||
|
{
|
||||||
|
*encoding = *chunk;
|
||||||
|
this->lock->unlock(this->lock);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
va_start(args, encoding);
|
||||||
|
enumerator = this->encoders->create_enumerator(this->encoders);
|
||||||
|
while (enumerator->enumerate(enumerator, &encode))
|
||||||
|
{
|
||||||
|
va_copy(copy, args);
|
||||||
|
success = encode(type, encoding, copy);
|
||||||
|
va_end(copy);
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
if (cache)
|
||||||
|
{
|
||||||
|
chunk = malloc_thing(chunk_t);
|
||||||
|
*chunk = *encoding;
|
||||||
|
this->lock->unlock(this->lock);
|
||||||
|
this->lock->write_lock(this->lock);
|
||||||
|
this->cache[type]->put(this->cache[type], cache, chunk);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
va_end(args);
|
||||||
|
this->lock->unlock(this->lock);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of key_encoding_t.clear_cache
|
||||||
|
*/
|
||||||
|
static void clear_cache(private_key_encoding_t *this, void *cache)
|
||||||
|
{
|
||||||
|
key_encoding_type_t type;
|
||||||
|
chunk_t *chunk;
|
||||||
|
|
||||||
|
this->lock->write_lock(this->lock);
|
||||||
|
for (type = 0; type < KEY_ENCODING_MAX; type++)
|
||||||
|
{
|
||||||
|
chunk = this->cache[type]->remove(this->cache[type], cache);
|
||||||
|
if (chunk)
|
||||||
|
{
|
||||||
|
chunk_free(chunk);
|
||||||
|
free(chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->lock->unlock(this->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of key_encoding_t.add_encoder
|
||||||
|
*/
|
||||||
|
static void add_encoder(private_key_encoding_t *this, key_encoder_t encoder)
|
||||||
|
{
|
||||||
|
this->lock->write_lock(this->lock);
|
||||||
|
this->encoders->insert_last(this->encoders, encoder);
|
||||||
|
this->lock->unlock(this->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of key_encoding_t.remove_encoder
|
||||||
|
*/
|
||||||
|
static void remove_encoder(private_key_encoding_t *this, key_encoder_t encoder)
|
||||||
|
{
|
||||||
|
this->lock->write_lock(this->lock);
|
||||||
|
this->encoders->remove(this->encoders, encoder, NULL);
|
||||||
|
this->lock->unlock(this->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of key_encoder_t.destroy.
|
||||||
|
*/
|
||||||
|
static void destroy(private_key_encoding_t *this)
|
||||||
|
{
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
key_encoding_type_t type;
|
||||||
|
chunk_t *chunk;
|
||||||
|
void *key;
|
||||||
|
|
||||||
|
for (type = 0; type < KEY_ENCODING_MAX; type++)
|
||||||
|
{
|
||||||
|
enumerator = this->cache[type]->create_enumerator(this->cache[type]);
|
||||||
|
while (enumerator->enumerate(enumerator, &key, &chunk))
|
||||||
|
{
|
||||||
|
chunk_free(chunk);
|
||||||
|
free(chunk);
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
this->cache[type]->destroy(this->cache[type]);
|
||||||
|
}
|
||||||
|
this->encoders->destroy(this->encoders);
|
||||||
|
this->lock->destroy(this->lock);
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See header
|
||||||
|
*/
|
||||||
|
key_encoding_t *key_encoding_create()
|
||||||
|
{
|
||||||
|
private_key_encoding_t *this = malloc_thing(private_key_encoding_t);
|
||||||
|
key_encoding_type_t type;
|
||||||
|
|
||||||
|
this->public.encode = (bool(*)(key_encoding_t*, key_encoding_type_t type, void *cache, chunk_t *encoding, ...))encode;
|
||||||
|
this->public.clear_cache = (void(*)(key_encoding_t*, void *cache))clear_cache;
|
||||||
|
this->public.add_encoder = (void(*)(key_encoding_t*, key_encoder_t encoder))add_encoder;
|
||||||
|
this->public.remove_encoder = (void(*)(key_encoding_t*, key_encoder_t encoder))remove_encoder;
|
||||||
|
this->public.destroy = (void(*)(key_encoding_t*))destroy;
|
||||||
|
|
||||||
|
for (type = 0; type < KEY_ENCODING_MAX; type++)
|
||||||
|
{
|
||||||
|
this->cache[type] = hashtable_create(hash, equals, 8);
|
||||||
|
}
|
||||||
|
this->encoders = linked_list_create();
|
||||||
|
this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
|
||||||
|
|
||||||
|
return &this->public;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009 Martin Willi
|
||||||
|
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup key_encoding key_encoding
|
||||||
|
* @{ @ingroup keys
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KEY_ENCODING_H_
|
||||||
|
#define KEY_ENCODING_H_
|
||||||
|
|
||||||
|
typedef struct key_encoding_t key_encoding_t;
|
||||||
|
typedef enum key_encoding_type_t key_encoding_type_t;
|
||||||
|
typedef enum key_encoding_part_t key_encoding_part_t;
|
||||||
|
|
||||||
|
#include <library.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key encoder function implementing encoding/fingerprinting.
|
||||||
|
*
|
||||||
|
* The variable argument list takes key_encoding_part_t, followed by part
|
||||||
|
* specific arguments, terminated by KEY_PART_END.
|
||||||
|
*
|
||||||
|
* @param type format to encode the key to
|
||||||
|
* @param args list of (key_encoding_part_t, data)
|
||||||
|
* @param encoding encoding result, allocated
|
||||||
|
* @return TRUE if encoding successful
|
||||||
|
*/
|
||||||
|
typedef bool (*key_encoder_t)(key_encoding_type_t type, chunk_t *encoding,
|
||||||
|
va_list args);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for key_encoder_t implementations to parse argument list.
|
||||||
|
*
|
||||||
|
* Key encoder functions get a variable argument list to parse. To simplify
|
||||||
|
* the job, this function reads the arguments and returns chunks for each
|
||||||
|
* part.
|
||||||
|
* The argument list of this function takes a key_encoding_part_t, followed
|
||||||
|
* by a data pointer receiving the value, terminated by KEY_PART_END.
|
||||||
|
*
|
||||||
|
* @param args argument list passed to key encoder function
|
||||||
|
* @param ... list of (key_encoding_part_t, data*)
|
||||||
|
* @return TRUE if all parts found, FALSE otherwise
|
||||||
|
*/
|
||||||
|
bool key_encoding_args(va_list args, ...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encoding type of a fingerprint/private-/public-key.
|
||||||
|
*
|
||||||
|
* Fingerprints have have the KEY_ID_*, public keys the KEY_PUB_* and
|
||||||
|
* private keys the KEY_PRIV_* prefix.
|
||||||
|
*/
|
||||||
|
enum key_encoding_type_t {
|
||||||
|
/** SHA1 fingerprint over subjectPublicKeyInfo */
|
||||||
|
KEY_ID_PUBKEY_INFO_SHA1 = 0,
|
||||||
|
/** SHA1 fingerprint over subjectPublicKey */
|
||||||
|
KEY_ID_PUBKEY_SHA1,
|
||||||
|
/** PGPv3 fingerprint */
|
||||||
|
KEY_ID_PGPV3,
|
||||||
|
/** PGPv4 fingerprint */
|
||||||
|
KEY_ID_PGPV4,
|
||||||
|
|
||||||
|
/** PKCS#1/ASN.1 key encoding */
|
||||||
|
KEY_PUB_ASN1_DER,
|
||||||
|
KEY_PRIV_ASN1_DER,
|
||||||
|
/** PGP key encoding */
|
||||||
|
KEY_PUB_PGP,
|
||||||
|
KEY_PRIV_PGP,
|
||||||
|
|
||||||
|
KEY_ENCODING_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parts of a key to encode.
|
||||||
|
*/
|
||||||
|
enum key_encoding_part_t {
|
||||||
|
/** modulus of a RSA key, n */
|
||||||
|
KEY_PART_RSA_MODULUS,
|
||||||
|
/** public exponent of a RSA key, e */
|
||||||
|
KEY_PART_RSA_PUB_EXP,
|
||||||
|
/** private exponent of a RSA key, d */
|
||||||
|
KEY_PART_RSA_PRIV_EXP,
|
||||||
|
/** prime1 a RSA key, p */
|
||||||
|
KEY_PART_RSA_PRIME1,
|
||||||
|
/** prime2 a RSA key, q */
|
||||||
|
KEY_PART_RSA_PRIME2,
|
||||||
|
/** exponent1 a RSA key, exp1 */
|
||||||
|
KEY_PART_RSA_EXP1,
|
||||||
|
/** exponent1 a RSA key, exp2 */
|
||||||
|
KEY_PART_RSA_EXP2,
|
||||||
|
/** coefficient of RSA key, coeff */
|
||||||
|
KEY_PART_RSA_COEFF,
|
||||||
|
|
||||||
|
KEY_PART_END,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private/Public key encoding and fingerprinting facility.
|
||||||
|
*/
|
||||||
|
struct key_encoding_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a key into a format using several key parts, optional caching.
|
||||||
|
*
|
||||||
|
* The variable argument list takes key_encoding_part_t, followed by part
|
||||||
|
* specific arguments, terminated by KEY_PART_END.
|
||||||
|
* If a cache key is given, the returned encoding points to internal data:
|
||||||
|
* do not free or modify. If no cache key is given, the encoding is
|
||||||
|
* allocated and must be freed by the caller.
|
||||||
|
*
|
||||||
|
* @param type format the key should be encoded to
|
||||||
|
* @param cache key to use for caching, NULL to not cache
|
||||||
|
* @param encoding encoding result, allocated if caching disabled
|
||||||
|
* @param ... list of (key_encoding_part_t, data)
|
||||||
|
* @return TRUE if encoding successful
|
||||||
|
*/
|
||||||
|
bool (*encode)(key_encoding_t *this, key_encoding_type_t type, void *cache,
|
||||||
|
chunk_t *encoding, ...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all cached encodings of a given cache key.
|
||||||
|
*
|
||||||
|
* @param cache key used in encode() for caching
|
||||||
|
*/
|
||||||
|
void (*clear_cache)(key_encoding_t *this, void *cache);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a key encoder function.
|
||||||
|
*
|
||||||
|
* @param encoder key encoder function to add
|
||||||
|
*/
|
||||||
|
void (*add_encoder)(key_encoding_t *this, key_encoder_t encoder);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister a previously registered key encoder function.
|
||||||
|
*
|
||||||
|
* @param encoder key encoder function to remove
|
||||||
|
*/
|
||||||
|
void (*remove_encoder)(key_encoding_t *this, key_encoder_t encoder);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy a key_encoding_t.
|
||||||
|
*/
|
||||||
|
void (*destroy)(key_encoding_t *this);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a key_encoding instance.
|
||||||
|
*/
|
||||||
|
key_encoding_t *key_encoding_create();
|
||||||
|
|
||||||
|
#endif /* KEY_ENCODING_ @}*/
|
||||||
@@ -64,6 +64,7 @@ void library_deinit()
|
|||||||
this->public.plugins->destroy(this->public.plugins);
|
this->public.plugins->destroy(this->public.plugins);
|
||||||
this->public.settings->destroy(this->public.settings);
|
this->public.settings->destroy(this->public.settings);
|
||||||
this->public.creds->destroy(this->public.creds);
|
this->public.creds->destroy(this->public.creds);
|
||||||
|
this->public.encoding->destroy(this->public.encoding);
|
||||||
this->public.crypto->destroy(this->public.crypto);
|
this->public.crypto->destroy(this->public.crypto);
|
||||||
this->public.fetcher->destroy(this->public.fetcher);
|
this->public.fetcher->destroy(this->public.fetcher);
|
||||||
this->public.db->destroy(this->public.db);
|
this->public.db->destroy(this->public.db);
|
||||||
@@ -123,6 +124,7 @@ bool library_init(char *settings)
|
|||||||
this->public.settings = settings_create(settings);
|
this->public.settings = settings_create(settings);
|
||||||
this->public.crypto = crypto_factory_create();
|
this->public.crypto = crypto_factory_create();
|
||||||
this->public.creds = credential_factory_create();
|
this->public.creds = credential_factory_create();
|
||||||
|
this->public.encoding = key_encoding_create();
|
||||||
this->public.fetcher = fetcher_manager_create();
|
this->public.fetcher = fetcher_manager_create();
|
||||||
this->public.db = database_factory_create();
|
this->public.db = database_factory_create();
|
||||||
this->public.plugins = plugin_loader_create();
|
this->public.plugins = plugin_loader_create();
|
||||||
|
|||||||
@@ -62,6 +62,7 @@
|
|||||||
#include <fetcher/fetcher_manager.h>
|
#include <fetcher/fetcher_manager.h>
|
||||||
#include <database/database_factory.h>
|
#include <database/database_factory.h>
|
||||||
#include <credentials/credential_factory.h>
|
#include <credentials/credential_factory.h>
|
||||||
|
#include <credentials/keys/key_encoding.h>
|
||||||
|
|
||||||
typedef struct library_t library_t;
|
typedef struct library_t library_t;
|
||||||
|
|
||||||
@@ -85,6 +86,11 @@ struct library_t {
|
|||||||
*/
|
*/
|
||||||
credential_factory_t *creds;
|
credential_factory_t *creds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* key encoding registry and factory
|
||||||
|
*/
|
||||||
|
key_encoding_t *encoding;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* URL fetching facility
|
* URL fetching facility
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user