/* * Copyright (C) 2012-2015 Tobias Brunner * Copyright (C) 2016-2019 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * Copyright (C) 2011 Martin Willi * Copyright (C) 2011 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 . * * 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. */ #define _GNU_SOURCE #include #include "plugin_feature.h" #include ENUM(plugin_feature_names, FEATURE_NONE, FEATURE_CUSTOM, "NONE", "CRYPTER", "AEAD", "SIGNER", "HASHER", "PRF", "XOF", "DRBG", "DH", "RNG", "NONCE_GEN", "PRIVKEY", "PRIVKEY_GEN", "PRIVKEY_SIGN", "PRIVKEY_DECRYPT", "PUBKEY", "PUBKEY_VERIFY", "PUBKEY_ENCRYPT", "CERT_DECODE", "CERT_ENCODE", "CONTAINER_DECODE", "CONTAINER_ENCODE", "EAP_SERVER", "EAP_CLIENT", "XAUTH_SERVER", "XAUTH_CLIENT", "DATABASE", "FETCHER", "RESOLVER", "CUSTOM", ); /** * See header. */ uint32_t plugin_feature_hash(plugin_feature_t *feature) { chunk_t data = chunk_empty; switch (feature->type) { case FEATURE_NONE: case FEATURE_RNG: case FEATURE_NONCE_GEN: case FEATURE_DATABASE: case FEATURE_FETCHER: case FEATURE_RESOLVER: /* put these special cases in their (type-specific) buckets */ data = chunk_empty; break; case FEATURE_CRYPTER: data = chunk_from_thing(feature->arg.crypter); break; case FEATURE_AEAD: data = chunk_from_thing(feature->arg.aead); break; case FEATURE_SIGNER: data = chunk_from_thing(feature->arg.signer); break; case FEATURE_HASHER: data = chunk_from_thing(feature->arg.hasher); break; case FEATURE_PRF: data = chunk_from_thing(feature->arg.prf); break; case FEATURE_XOF: data = chunk_from_thing(feature->arg.xof); break; case FEATURE_DRBG: data = chunk_from_thing(feature->arg.drbg); break; case FEATURE_DH: data = chunk_from_thing(feature->arg.dh_group); break; case FEATURE_PRIVKEY: data = chunk_from_thing(feature->arg.privkey); break; case FEATURE_PRIVKEY_GEN: data = chunk_from_thing(feature->arg.privkey_gen); break; case FEATURE_PUBKEY: data = chunk_from_thing(feature->arg.pubkey); break; case FEATURE_PRIVKEY_SIGN: data = chunk_from_thing(feature->arg.privkey_sign); break; case FEATURE_PUBKEY_VERIFY: data = chunk_from_thing(feature->arg.pubkey_verify); break; case FEATURE_PRIVKEY_DECRYPT: data = chunk_from_thing(feature->arg.privkey_decrypt); break; case FEATURE_PUBKEY_ENCRYPT: data = chunk_from_thing(feature->arg.pubkey_encrypt); break; case FEATURE_CERT_DECODE: case FEATURE_CERT_ENCODE: data = chunk_from_thing(feature->arg.cert); break; case FEATURE_CONTAINER_DECODE: case FEATURE_CONTAINER_ENCODE: data = chunk_from_thing(feature->arg.container); break; case FEATURE_EAP_SERVER: case FEATURE_EAP_PEER: data = chunk_from_thing(feature->arg.eap); break; case FEATURE_CUSTOM: data = chunk_create(feature->arg.custom, strlen(feature->arg.custom)); break; case FEATURE_XAUTH_SERVER: case FEATURE_XAUTH_PEER: data = chunk_create(feature->arg.xauth, strlen(feature->arg.xauth)); break; } return chunk_hash_inc(chunk_from_thing(feature->type), chunk_hash(data)); } /** * See header. */ bool plugin_feature_matches(plugin_feature_t *a, plugin_feature_t *b) { if (a->type == b->type) { switch (a->type) { case FEATURE_NONE: return FALSE; case FEATURE_CRYPTER: return a->arg.crypter.alg == b->arg.crypter.alg && a->arg.crypter.key_size == b->arg.crypter.key_size; case FEATURE_AEAD: return a->arg.aead.alg == b->arg.aead.alg && a->arg.aead.key_size == b->arg.aead.key_size; case FEATURE_SIGNER: return a->arg.signer == b->arg.signer; case FEATURE_HASHER: return a->arg.hasher == b->arg.hasher; case FEATURE_PRF: return a->arg.prf == b->arg.prf; case FEATURE_XOF: return a->arg.xof == b->arg.xof; case FEATURE_DRBG: return a->arg.drbg == b->arg.drbg; case FEATURE_DH: return a->arg.dh_group == b->arg.dh_group; case FEATURE_RNG: return a->arg.rng_quality <= b->arg.rng_quality; case FEATURE_NONCE_GEN: case FEATURE_RESOLVER: return TRUE; case FEATURE_PRIVKEY: case FEATURE_PRIVKEY_GEN: case FEATURE_PUBKEY: return a->arg.privkey == b->arg.privkey; case FEATURE_PRIVKEY_SIGN: case FEATURE_PUBKEY_VERIFY: return a->arg.privkey_sign == b->arg.privkey_sign; case FEATURE_PRIVKEY_DECRYPT: case FEATURE_PUBKEY_ENCRYPT: return a->arg.privkey_decrypt == b->arg.privkey_decrypt; case FEATURE_CERT_DECODE: case FEATURE_CERT_ENCODE: return a->arg.cert == b->arg.cert; case FEATURE_CONTAINER_DECODE: case FEATURE_CONTAINER_ENCODE: return a->arg.container == b->arg.container; case FEATURE_EAP_SERVER: case FEATURE_EAP_PEER: return a->arg.eap.vendor == b->arg.eap.vendor && a->arg.eap.type == b->arg.eap.type; case FEATURE_DATABASE: return a->arg.database == DB_ANY || a->arg.database == b->arg.database; case FEATURE_FETCHER: return a->arg.fetcher == NULL || streq(a->arg.fetcher, b->arg.fetcher); case FEATURE_CUSTOM: return streq(a->arg.custom, b->arg.custom); case FEATURE_XAUTH_SERVER: case FEATURE_XAUTH_PEER: return streq(a->arg.xauth, b->arg.xauth); } } return FALSE; } /** * See header. */ bool plugin_feature_equals(plugin_feature_t *a, plugin_feature_t *b) { if (a->type == b->type) { switch (a->type) { case FEATURE_NONE: case FEATURE_CRYPTER: case FEATURE_AEAD: case FEATURE_SIGNER: case FEATURE_HASHER: case FEATURE_PRF: case FEATURE_XOF: case FEATURE_DRBG: case FEATURE_DH: case FEATURE_NONCE_GEN: case FEATURE_RESOLVER: case FEATURE_PRIVKEY: case FEATURE_PRIVKEY_GEN: case FEATURE_PUBKEY: case FEATURE_PRIVKEY_SIGN: case FEATURE_PUBKEY_VERIFY: case FEATURE_PRIVKEY_DECRYPT: case FEATURE_PUBKEY_ENCRYPT: case FEATURE_CERT_DECODE: case FEATURE_CERT_ENCODE: case FEATURE_CONTAINER_DECODE: case FEATURE_CONTAINER_ENCODE: case FEATURE_EAP_SERVER: case FEATURE_EAP_PEER: case FEATURE_CUSTOM: case FEATURE_XAUTH_SERVER: case FEATURE_XAUTH_PEER: return plugin_feature_matches(a, b); case FEATURE_RNG: return a->arg.rng_quality == b->arg.rng_quality; case FEATURE_DATABASE: return a->arg.database == b->arg.database; case FEATURE_FETCHER: if (a->arg.fetcher && b->arg.fetcher) { return streq(a->arg.fetcher, b->arg.fetcher); } return !a->arg.fetcher && !b->arg.fetcher; } } return FALSE; } /** * See header. */ char* plugin_feature_get_string(plugin_feature_t *feature) { char *str = NULL; if (feature->kind == FEATURE_REGISTER) { return strdup("(register function)"); } switch (feature->type) { case FEATURE_NONE: return strdup("NONE"); case FEATURE_CRYPTER: if (asprintf(&str, "%N:%N-%d", plugin_feature_names, feature->type, encryption_algorithm_names, feature->arg.crypter.alg, feature->arg.crypter.key_size) > 0) { return str; } break; case FEATURE_AEAD: if (asprintf(&str, "%N:%N-%d", plugin_feature_names, feature->type, encryption_algorithm_names, feature->arg.aead.alg, feature->arg.aead.key_size) > 0) { return str; } break; case FEATURE_SIGNER: if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type, integrity_algorithm_names, feature->arg.signer) > 0) { return str; } break; case FEATURE_HASHER: if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type, hash_algorithm_names, feature->arg.hasher) > 0) { return str; } break; case FEATURE_PRF: if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type, pseudo_random_function_names, feature->arg.prf) > 0) { return str; } break; case FEATURE_XOF: if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type, ext_out_function_names, feature->arg.xof) > 0) { return str; } break; case FEATURE_DRBG: if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type, drbg_type_names, feature->arg.drbg) > 0) { return str; } break; case FEATURE_DH: if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type, diffie_hellman_group_names, feature->arg.dh_group) > 0) { return str; } break; case FEATURE_RNG: if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type, rng_quality_names, feature->arg.rng_quality) > 0) { return str; } break; case FEATURE_NONCE_GEN: case FEATURE_RESOLVER: if (asprintf(&str, "%N", plugin_feature_names, feature->type) > 0) { return str; } break; case FEATURE_PRIVKEY: case FEATURE_PRIVKEY_GEN: case FEATURE_PUBKEY: if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type, key_type_names, feature->arg.privkey) > 0) { return str; } break; case FEATURE_PRIVKEY_SIGN: case FEATURE_PUBKEY_VERIFY: if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type, signature_scheme_names, feature->arg.privkey_sign) > 0) { return str; } break; case FEATURE_PRIVKEY_DECRYPT: case FEATURE_PUBKEY_ENCRYPT: if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type, encryption_scheme_names, feature->arg.privkey_decrypt) > 0) { return str; } break; case FEATURE_CERT_DECODE: case FEATURE_CERT_ENCODE: if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type, certificate_type_names, feature->arg.cert) > 0) { return str; } break; case FEATURE_CONTAINER_DECODE: case FEATURE_CONTAINER_ENCODE: if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type, container_type_names, feature->arg.container) > 0) { return str; } break; case FEATURE_EAP_SERVER: case FEATURE_EAP_PEER: if (feature->arg.eap.vendor && asprintf(&str, "%N:%d-%d", plugin_feature_names, feature->type, feature->arg.eap.type, feature->arg.eap.vendor) > 0) { return str; } else if (!feature->arg.eap.vendor && asprintf(&str, "%N:%N", plugin_feature_names, feature->type, eap_type_short_names, feature->arg.eap.type) > 0) { return str; } break; case FEATURE_DATABASE: if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type, db_driver_names, feature->arg.database) > 0) { return str; } break; case FEATURE_FETCHER: if (asprintf(&str, "%N:%s", plugin_feature_names, feature->type, feature->arg.fetcher) > 0) { return str; } break; case FEATURE_CUSTOM: if (asprintf(&str, "%N:%s", plugin_feature_names, feature->type, feature->arg.custom) > 0) { return str; } break; case FEATURE_XAUTH_SERVER: case FEATURE_XAUTH_PEER: if (asprintf(&str, "%N:%s", plugin_feature_names, feature->type, feature->arg.xauth) > 0) { return str; } break; } if (!str) { str = strdup("(invalid)"); } return str; } /** * See header. */ bool plugin_feature_load(plugin_t *plugin, plugin_feature_t *feature, plugin_feature_t *reg) { char *name; if (!reg) { /* noting to do for this feature */ return TRUE; } if (reg->kind == FEATURE_CALLBACK) { if (!reg->arg.cb.f || reg->arg.cb.f(plugin, feature, TRUE, reg->arg.cb.data)) { return TRUE; } return FALSE; } name = plugin->get_name(plugin); switch (feature->type) { case FEATURE_CRYPTER: lib->crypto->add_crypter(lib->crypto, feature->arg.crypter.alg, feature->arg.crypter.key_size, name, reg->arg.reg.f); break; case FEATURE_AEAD: lib->crypto->add_aead(lib->crypto, feature->arg.aead.alg, feature->arg.aead.key_size, name, reg->arg.reg.f); break; case FEATURE_SIGNER: lib->crypto->add_signer(lib->crypto, feature->arg.signer, name, reg->arg.reg.f); break; case FEATURE_HASHER: lib->crypto->add_hasher(lib->crypto, feature->arg.hasher, name, reg->arg.reg.f); break; case FEATURE_PRF: lib->crypto->add_prf(lib->crypto, feature->arg.prf, name, reg->arg.reg.f); break; case FEATURE_XOF: lib->crypto->add_xof(lib->crypto, feature->arg.xof, name, reg->arg.reg.f); break; case FEATURE_DRBG: lib->crypto->add_drbg(lib->crypto, feature->arg.drbg, name, reg->arg.reg.f); break; case FEATURE_DH: lib->crypto->add_dh(lib->crypto, feature->arg.dh_group, name, reg->arg.reg.f); break; case FEATURE_RNG: lib->crypto->add_rng(lib->crypto, feature->arg.rng_quality, name, reg->arg.reg.f); break; case FEATURE_NONCE_GEN: lib->crypto->add_nonce_gen(lib->crypto, name, reg->arg.reg.f); break; case FEATURE_PRIVKEY: case FEATURE_PRIVKEY_GEN: lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, feature->arg.privkey, reg->arg.reg.final, name, reg->arg.reg.f); break; case FEATURE_PUBKEY: lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, feature->arg.pubkey, reg->arg.reg.final, name, reg->arg.reg.f); break; case FEATURE_CERT_DECODE: case FEATURE_CERT_ENCODE: lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, feature->arg.cert, reg->arg.reg.final, name, reg->arg.reg.f); break; case FEATURE_CONTAINER_DECODE: case FEATURE_CONTAINER_ENCODE: lib->creds->add_builder(lib->creds, CRED_CONTAINER, feature->arg.container, reg->arg.reg.final, name, reg->arg.reg.f); break; case FEATURE_DATABASE: lib->db->add_database(lib->db, reg->arg.reg.f); break; case FEATURE_FETCHER: lib->fetcher->add_fetcher(lib->fetcher, reg->arg.reg.f, feature->arg.fetcher); break; case FEATURE_RESOLVER: lib->resolver->add_resolver(lib->resolver, reg->arg.reg.f); break; default: break; } return TRUE; } /** * See header. */ bool plugin_feature_unload(plugin_t *plugin, plugin_feature_t *feature, plugin_feature_t *reg) { if (!reg) { /* noting to do for this feature */ return TRUE; } if (reg->kind == FEATURE_CALLBACK) { if (!reg->arg.cb.f || reg->arg.cb.f(plugin, feature, FALSE, reg->arg.cb.data)) { return TRUE; } return FALSE; } switch (feature->type) { case FEATURE_CRYPTER: lib->crypto->remove_crypter(lib->crypto, reg->arg.reg.f); break; case FEATURE_AEAD: lib->crypto->remove_aead(lib->crypto, reg->arg.reg.f); break; case FEATURE_SIGNER: lib->crypto->remove_signer(lib->crypto, reg->arg.reg.f); break; case FEATURE_HASHER: lib->crypto->remove_hasher(lib->crypto, reg->arg.reg.f); break; case FEATURE_PRF: lib->crypto->remove_prf(lib->crypto, reg->arg.reg.f); break; case FEATURE_XOF: lib->crypto->remove_xof(lib->crypto, reg->arg.reg.f); break; case FEATURE_DRBG: lib->crypto->remove_drbg(lib->crypto, reg->arg.reg.f); break; case FEATURE_DH: lib->crypto->remove_dh(lib->crypto, reg->arg.reg.f); break; case FEATURE_RNG: lib->crypto->remove_rng(lib->crypto, reg->arg.reg.f); break; case FEATURE_NONCE_GEN: lib->crypto->remove_nonce_gen(lib->crypto, reg->arg.reg.f); break; case FEATURE_PRIVKEY: case FEATURE_PRIVKEY_GEN: lib->creds->remove_builder(lib->creds, reg->arg.reg.f); break; case FEATURE_PUBKEY: lib->creds->remove_builder(lib->creds, reg->arg.reg.f); break; case FEATURE_CERT_DECODE: case FEATURE_CERT_ENCODE: lib->creds->remove_builder(lib->creds, reg->arg.reg.f); break; case FEATURE_CONTAINER_DECODE: case FEATURE_CONTAINER_ENCODE: lib->creds->remove_builder(lib->creds, reg->arg.reg.f); break; case FEATURE_DATABASE: lib->db->remove_database(lib->db, reg->arg.reg.f); break; case FEATURE_FETCHER: lib->fetcher->remove_fetcher(lib->fetcher, reg->arg.reg.f); break; case FEATURE_RESOLVER: lib->resolver->remove_resolver(lib->resolver, reg->arg.reg.f); break; default: break; } return TRUE; }