diff options
Diffstat (limited to 'src/libstrongswan')
-rw-r--r-- | src/libstrongswan/plugins/af_alg/Makefile.am | 1 | ||||
-rw-r--r-- | src/libstrongswan/plugins/af_alg/af_alg_plugin.c | 18 | ||||
-rw-r--r-- | src/libstrongswan/plugins/af_alg/af_alg_prf.c | 187 | ||||
-rw-r--r-- | src/libstrongswan/plugins/af_alg/af_alg_prf.h | 47 |
4 files changed, 253 insertions, 0 deletions
diff --git a/src/libstrongswan/plugins/af_alg/Makefile.am b/src/libstrongswan/plugins/af_alg/Makefile.am index f258d2422..a33fd30b6 100644 --- a/src/libstrongswan/plugins/af_alg/Makefile.am +++ b/src/libstrongswan/plugins/af_alg/Makefile.am @@ -14,6 +14,7 @@ libstrongswan_af_alg_la_SOURCES = \ af_alg_ops.h af_alg_ops.c \ af_alg_hasher.h af_alg_hasher.c \ af_alg_signer.h af_alg_signer.c \ + af_alg_prf.h af_alg_prf.c \ af_alg_crypter.h af_alg_crypter.c libstrongswan_af_alg_la_LDFLAGS = -module -avoid-version diff --git a/src/libstrongswan/plugins/af_alg/af_alg_plugin.c b/src/libstrongswan/plugins/af_alg/af_alg_plugin.c index 8fbf2f7b5..01031d7a1 100644 --- a/src/libstrongswan/plugins/af_alg/af_alg_plugin.c +++ b/src/libstrongswan/plugins/af_alg/af_alg_plugin.c @@ -19,6 +19,7 @@ #include "af_alg_hasher.h" #include "af_alg_signer.h" +#include "af_alg_prf.h" #include "af_alg_crypter.h" typedef struct private_af_alg_plugin_t private_af_alg_plugin_t; @@ -41,6 +42,8 @@ METHOD(plugin_t, destroy, void, (hasher_constructor_t)af_alg_hasher_create); lib->crypto->remove_signer(lib->crypto, (signer_constructor_t)af_alg_signer_create); + lib->crypto->remove_prf(lib->crypto, + (prf_constructor_t)af_alg_prf_create); lib->crypto->remove_crypter(lib->crypto, (crypter_constructor_t)af_alg_crypter_create); @@ -104,6 +107,21 @@ plugin_t *af_alg_plugin_create() lib->crypto->add_signer(lib->crypto, AUTH_CAMELLIA_XCBC_96, (signer_constructor_t)af_alg_signer_create); + lib->crypto->add_prf(lib->crypto, PRF_HMAC_MD5, + (prf_constructor_t)af_alg_prf_create); + lib->crypto->add_prf(lib->crypto, PRF_HMAC_SHA1, + (prf_constructor_t)af_alg_prf_create); + lib->crypto->add_prf(lib->crypto, PRF_HMAC_SHA2_256, + (prf_constructor_t)af_alg_prf_create); + lib->crypto->add_prf(lib->crypto, PRF_HMAC_SHA2_384, + (prf_constructor_t)af_alg_prf_create); + lib->crypto->add_prf(lib->crypto, PRF_HMAC_SHA2_512, + (prf_constructor_t)af_alg_prf_create); + lib->crypto->add_prf(lib->crypto, PRF_AES128_XCBC, + (prf_constructor_t)af_alg_prf_create); + lib->crypto->add_prf(lib->crypto, PRF_CAMELLIA128_XCBC, + (prf_constructor_t)af_alg_prf_create); + lib->crypto->add_crypter(lib->crypto, ENCR_DES, (crypter_constructor_t)af_alg_crypter_create); lib->crypto->add_crypter(lib->crypto, ENCR_3DES, diff --git a/src/libstrongswan/plugins/af_alg/af_alg_prf.c b/src/libstrongswan/plugins/af_alg/af_alg_prf.c new file mode 100644 index 000000000..8912e2457 --- /dev/null +++ b/src/libstrongswan/plugins/af_alg/af_alg_prf.c @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 "af_alg_prf.h" +#include "af_alg_ops.h" + +typedef struct private_af_alg_prf_t private_af_alg_prf_t; + +/** + * Private data of a af_alg_prf_t object. + */ +struct private_af_alg_prf_t { + + /** + * Public af_alg_prf_t interface. + */ + af_alg_prf_t public; + + /** + * AF_ALG operations + */ + af_alg_ops_t *ops; + + /** + * Size of the PRF output + */ + size_t block_size; + + /** + * Default key size + */ + size_t key_size; + + /** + * Using an XCBC algorithm? + */ + bool xcbc; +}; + +/** + * Get the kernel algorithm string and block size for our identifier + */ +static size_t lookup_alg(integrity_algorithm_t algo, char **name, bool *xcbc) +{ + static struct { + integrity_algorithm_t id; + char *name; + size_t block_size; + bool xcbc; + } algs[] = { + {PRF_HMAC_MD5, "hmac(md5)", 16, FALSE, }, + {PRF_HMAC_SHA1, "hmac(sha1)", 20, FALSE, }, + {PRF_HMAC_SHA2_256, "hmac(sha256)", 32, FALSE, }, + {PRF_HMAC_SHA2_384, "hmac(sha384)", 48, FALSE, }, + {PRF_HMAC_SHA2_512, "hmac(sha512)", 64, FALSE, }, + {PRF_AES128_XCBC, "xcbc(aes)", 16, TRUE, }, + {PRF_CAMELLIA128_XCBC, "xcbc(camellia)", 16, TRUE, }, + }; + int i; + + for (i = 0; i < countof(algs); i++) + { + if (algs[i].id == algo) + { + *name = algs[i].name; + *xcbc = algs[i].xcbc; + return algs[i].block_size; + } + } + return 0; +} + +METHOD(prf_t, get_bytes, void, + private_af_alg_prf_t *this, chunk_t seed, u_int8_t *buffer) +{ + this->ops->hash(this->ops, seed, buffer, this->block_size); +} + +METHOD(prf_t, allocate_bytes, void, + private_af_alg_prf_t *this, chunk_t seed, chunk_t *chunk) +{ + if (chunk) + { + *chunk = chunk_alloc(this->block_size); + get_bytes(this, seed, chunk->ptr); + } + else + { + get_bytes(this, seed, NULL); + } +} + +METHOD(prf_t, get_block_size, size_t, + private_af_alg_prf_t *this) +{ + return this->block_size; +} + +METHOD(prf_t, get_key_size, size_t, + private_af_alg_prf_t *this) +{ + return this->block_size; +} + +METHOD(prf_t, set_key, void, + private_af_alg_prf_t *this, chunk_t key) +{ + char buf[this->block_size]; + + if (this->xcbc) + { + /* The kernel currently does not support variable length XCBC keys, + * do RFC4434 key padding/reduction manually. */ + if (key.len < this->block_size) + { + memset(buf, 0, this->block_size); + memcpy(buf, key.ptr, key.len); + key = chunk_from_thing(buf); + } + else if (key.len > this->block_size) + { + memset(buf, 0, this->block_size); + this->ops->set_key(this->ops, chunk_from_thing(buf)); + this->ops->hash(this->ops, key, buf, this->block_size); + key = chunk_from_thing(buf); + } + } + this->ops->set_key(this->ops, key); +} + +METHOD(prf_t, destroy, void, + private_af_alg_prf_t *this) +{ + this->ops->destroy(this->ops); + free(this); +} + +/* + * Described in header. + */ +af_alg_prf_t *af_alg_prf_create(pseudo_random_function_t algo) +{ + private_af_alg_prf_t *this; + size_t block_size; + bool xcbc; + char *name; + + block_size = lookup_alg(algo, &name, &xcbc); + if (!block_size) + { /* not supported by kernel */ + return NULL; + } + + INIT(this, + .public = { + .prf = { + .get_bytes = _get_bytes, + .allocate_bytes = _allocate_bytes, + .get_block_size = _get_block_size, + .get_key_size = _get_key_size, + .set_key = _set_key, + .destroy = _destroy, + }, + }, + .ops = af_alg_ops_create("hash", name), + .block_size = block_size, + .xcbc = xcbc, + ); + if (!this->ops) + { + free(this); + return NULL; + } + return &this->public; +} diff --git a/src/libstrongswan/plugins/af_alg/af_alg_prf.h b/src/libstrongswan/plugins/af_alg/af_alg_prf.h new file mode 100644 index 000000000..01e0e857d --- /dev/null +++ b/src/libstrongswan/plugins/af_alg/af_alg_prf.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * 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 af_alg_prf af_alg_prf + * @{ @ingroup af_alg + */ + +#ifndef AF_ALG_PRF_H_ +#define AF_ALG_PRF_H_ + +typedef struct af_alg_prf_t af_alg_prf_t; + +#include <crypto/prfs/prf.h> + +/** + * Implementation of PRFs using AF_ALG. + */ +struct af_alg_prf_t { + + /** + * Implements prf_t interface. + */ + prf_t prf; +}; + +/** + * Creates a new af_alg_prf_t object. + * + * @param algo algorithm to implement + * @return af_alg_prf_t object, NULL if hash not supported + */ +af_alg_prf_t *af_alg_prf_create(pseudo_random_function_t algo); + +#endif /** AF_ALG_PRF_H_ @}*/ |