plugins: remove dependency on ELL plugins

There has been a desire to remove the ELL plugin dependency from
IWD which is the only consumer of the plugin API. This removes
the dependency and prepares the tree for converting the existing
ofono plugin into a regular module.

sim_hardcoded was removed completely. This was originall implemented
before full ofono support purely to test the IWD side of EAP-SIM/AKA.
Since the ofono plugin (module-to-be) is now fully implemented there
really isn't a need for sim_hardcoded.
This commit is contained in:
James Prestwood 2020-09-16 12:39:40 -07:00 committed by Denis Kenzior
parent 2f51b51152
commit bbcfde8743
6 changed files with 1 additions and 428 deletions

View File

@ -185,7 +185,6 @@ if DAEMON
libexec_PROGRAMS += src/iwd
src_iwd_SOURCES = src/main.c linux/nl80211.h src/iwd.h src/missing.h \
src/plugin.h src/plugin.c \
src/netdev.h src/netdev.c \
src/wiphy.h src/wiphy.c \
src/device.c \
@ -235,14 +234,9 @@ src_iwd_SOURCES = src/main.c linux/nl80211.h src/iwd.h src/missing.h \
src_iwd_LDADD = $(ell_ldadd) -ldl
src_iwd_DEPENDENCIES = $(ell_dependencies)
if SIM_HARDCODED
builtin_modules += sim_hardcoded
builtin_sources += plugins/sim_hardcoded.c
endif
if OFONO
builtin_modules += ofono
builtin_sources += plugins/ofono.c
builtin_sources += src/ofono.c
endif
if DBUS_POLICY

View File

@ -13,6 +13,5 @@ fi
--enable-hwsim \
--enable-tools \
--enable-ofono \
--enable-sim-hardcoded \
--disable-dbus-policy \
--disable-systemd-service $*

View File

@ -291,11 +291,6 @@ AC_ARG_ENABLE([ofono], AC_HELP_STRING([--enable-ofono],
[enable_ofono=${enableval}])
AM_CONDITIONAL(OFONO, test "${enable_ofono}" = "yes")
AC_ARG_ENABLE([sim_hardcoded], AC_HELP_STRING([--enable-sim-hardcoded],
[enable hard coded SIM keys]),
[enable_sim_hardcoded=${enableval}])
AM_CONDITIONAL(SIM_HARDCODED, test "${enable_sim_hardcoded}" = "yes")
AC_CONFIG_FILES(Makefile)
AC_OUTPUT

View File

@ -1,399 +0,0 @@
/*
*
* Wireless daemon for Linux
*
* Copyright (C) 2017-2019 Intel Corporation. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <errno.h>
#include <ell/ell.h>
#include <ell/plugin.h>
#include "src/simauth.h"
struct hardcoded_sim {
char *identity;
uint8_t sim_supported;
uint8_t kc[NUM_RANDS_MAX][EAP_SIM_KC_LEN];
uint8_t sres[NUM_RANDS_MAX][EAP_SIM_SRES_LEN];
uint8_t aka_supported;
uint8_t ki[EAP_AKA_KI_LEN];
uint8_t opc[EAP_AKA_OPC_LEN];
uint8_t amf[EAP_AKA_AMF_LEN];
uint8_t sqn[EAP_AKA_SQN_LEN];
struct iwd_sim_auth *auth;
};
static struct hardcoded_sim *sim;
/*
* Helper to XOR an array
* to - result of XOR array
* a - array 1
* b - array 2
* len - size of array
*/
#define XOR(to, a, b, len) \
for (i = 0; i < len; i++) { \
to[i] = a[i] ^ b[i]; \
}
static int get_milenage(const uint8_t *opc, const uint8_t *k,
const uint8_t *rand, const uint8_t *sqn, const uint8_t *amf,
const uint8_t *autn_in, uint8_t *autn, uint8_t *ck, uint8_t *ik,
uint8_t *res, uint8_t *auts)
{
/* algorithm variables: TEMP, IN1, OUT1, OUT2, OUT5 (OUT3/4 == IK/CK) */
uint8_t temp[16];
uint8_t in1[16];
uint8_t out1[16], out2[16], out5[16];
/* other variables */
struct l_cipher *aes;
int i;
uint8_t tmp1[16];
uint8_t tmp2[16];
uint8_t sqn_autn[6];
aes = l_cipher_new(L_CIPHER_AES, k, 16);
/* temp = TEMP = E[RAND ^ OPc]k */
XOR(tmp1, rand, opc, 16);
l_cipher_encrypt(aes, tmp1, temp, 16);
/* IN1[0-47] = SQN[0-47] */
memcpy(in1, sqn, 6);
/* IN1[48-63] = AMF[0-15] */
memcpy(in1 + 6, amf, 2);
/* IN1[64-111] = SQN[0-47] */
memcpy(in1 + 8, sqn, 6);
/* IN1[112-127] = AMF[0-15] */
memcpy(in1 + 14, amf, 2);
/*
* f1 and f1* output OUT1
*/
/*
* tmp1 = rot(IN1 ^ OPc)r1
* r1 = 64 bits = 8 bytes
*/
for (i = 0; i < 16; i++)
tmp1[(i + 8) % 16] = in1[i] ^ opc[i];
/* tmp2 = TEMP ^ tmp1 */
XOR(tmp2, temp, tmp1, 16);
/* tmp2 = E[tmp2]k */
l_cipher_encrypt(aes, tmp2, tmp1, 16);
/* out1 = OUT1 = tmp1 ^ opc */
XOR(out1, tmp1, opc, 16);
/*
* f2 outputs OUT2 (RES | AK)
*
* r2 = 0 == no rotation
*/
/* tmp1 = rot(TEMP ^ OPc)r2 */
XOR(tmp1, temp, opc, 16);
/* tmp1 ^ c2. c2 at bit 127 == 1 */
tmp1[15] ^= 1;
l_cipher_encrypt(aes, tmp1, out2, 16);
/* get RES from OUT2 */
XOR(out2, out2, opc, 16);
memcpy(res, out2 + 8, 8);
/* check input autn (AUTN ^ AK = SQN)*/
XOR(sqn_autn, autn_in, out2, 6);
/* if SQN was not correct, generate AUTS */
if (memcmp(sqn_autn, sqn, 6)) {
/*
* f5* outputs AK' (OUT5)
*/
for (i = 0; i < 16; i++)
tmp1[(i + 4) % 16] = temp[i] ^ opc[i];
/* tmp1 ^ c5. c5 at bit 124 == 1 */
tmp1[15] ^= 1 << 3;
l_cipher_encrypt(aes, tmp1, out5, 16);
/* out5 ^ opc */
XOR(out5, out5, opc, 16);
XOR(auts, sqn, out5, 6);
/* run f1 with zero'd AMF to finish AUTS */
in1[6] = 0x00;
in1[7] = 0x00;
in1[14] = 0x00;
in1[15] = 0x00;
for (i = 0; i < 16; i++)
tmp1[(i + 8) % 16] = in1[i] ^ opc[i];
/* tmp2 = TEMP ^ tmp1 */
XOR(tmp2, temp, tmp1, 16);
/* tmp2 = E[tmp2]k */
l_cipher_encrypt(aes, tmp2, tmp1, 16);
/* out1 = OUT1 = tmp1 ^ opc */
XOR(out1, tmp1, opc, 16);
memcpy(auts + 6, in1 + 8, 8);
return -1;
}
/* AUTN = (SQN ^ AK) | AMF | MAC_A */
XOR(autn, sqn, out2, 6);
memcpy(autn + 6, amf, 2);
memcpy(autn + 8, out1, 8);
if (memcmp(autn, autn_in, 16))
return -2;
/*
* f3 outputs CK (OUT3)
*
* tmp1 = rot(TEMP ^ OPc)r3
*
* r3 = 32 bits = 4 bytes
*/
for (i = 0; i < 16; i++)
tmp1[(i + 12) % 16] = temp[i] ^ opc[i];
/* tmp1 ^ c3. c3 at bit 126 == 1 */
tmp1[15] ^= 1 << 1;
l_cipher_encrypt(aes, tmp1, ck, 16);
/* ck ^ opc */
XOR(ck, ck, opc, 16);
/*
* f4 outputs IK (OUT4)
*
* tmp1 = rot(TEMP ^ OPc)r4
*
* r4 = 64 bits = 8 bytes
*/
for (i = 0; i < 16; i++)
tmp1[(i + 8) % 16] = temp[i] ^ opc[i];
/* tmp1 ^ c4. c4 at bit 125 == 1 */
tmp1[15] ^= 1 << 2;
l_cipher_encrypt(aes, tmp1, ik, 16);
/* ik ^ opc */
XOR(ik, ik, opc, 16);
l_cipher_free(aes);
return 0;
}
static int check_milenage(struct iwd_sim_auth *auth, const uint8_t *rand,
const uint8_t *autn, sim_auth_check_milenage_cb_t cb,
void *data)
{
uint8_t res[8];
uint8_t ck[16];
uint8_t ik[16];
uint8_t _autn[16];
uint8_t auts[14];
int ret;
if (!sim->aka_supported)
return -ENOTSUP;
ret = get_milenage(sim->opc, sim->ki, rand, sim->sqn, sim->amf,
autn, _autn, ck, ik, res, auts);
/* ret == 0, success; ret == -1, sync failure; ret == -2, failure */
if (ret == 0)
cb(res, ck, ik, NULL, data);
else if (ret == -1)
cb(NULL, NULL, NULL, auts, data);
else
cb(NULL, NULL, NULL, NULL, data);
return 0;
}
static int run_gsm(struct iwd_sim_auth *auth, const uint8_t *rands,
int num_rands, sim_auth_run_gsm_cb_t cb, void *data)
{
if (!sim->sim_supported)
return -ENOTSUP;
cb((const uint8_t *)sim->sres, (const uint8_t *)sim->kc, data);
return 0;
}
static struct iwd_sim_auth_driver hardcoded_sim_driver = {
.name = "Hardcoded SIM driver",
.check_milenage = check_milenage,
.run_gsm = run_gsm
};
static int sim_hardcoded_init(void)
{
void *kc;
void *sres;
void *ki;
void *opc;
void *amf;
void *sqn;
const char *str;
size_t len;
struct l_settings *key_settings;
const char *config_path = getenv("IWD_SIM_KEYS");
if (!config_path) {
l_debug("IWD_SIM_KEYS not set in env");
return -ENOENT;
}
key_settings = l_settings_new();
if (!l_settings_load_from_file(key_settings, config_path)) {
l_error("No %s file found", config_path);
l_settings_free(key_settings);
return -ENOENT;
}
sim = l_new(struct hardcoded_sim, 1);
if (l_settings_has_group(key_settings, "SIM")) {
str = l_settings_get_value(key_settings, "SIM", "Kc");
if (!str) {
l_debug("Kc value must be present for SIM");
goto try_aka;
}
kc = l_util_from_hexstring(str, &len);
memcpy(sim->kc, kc, len);
l_free(kc);
str = l_settings_get_value(key_settings, "SIM", "SRES");
if (!str) {
l_debug("SRES value must be present for SIM");
goto try_aka;
}
sres = l_util_from_hexstring(str, &len);
memcpy(sim->sres, sres, NUM_RANDS_MAX * EAP_SIM_SRES_LEN);
l_free(sres);
str = l_settings_get_value(key_settings, "SIM", "Identity");
if (!str) {
l_debug("Identity setting must be present for SIM");
goto try_aka;
}
sim->identity = l_strdup(str);
sim->sim_supported = 1;
}
try_aka:
if (l_settings_has_group(key_settings, "AKA")) {
str = l_settings_get_value(key_settings, "AKA", "KI");
if (!str) {
l_debug("KI value must be present for AKA");
goto end;
}
ki = l_util_from_hexstring(str, &len);
memcpy(sim->ki, ki, EAP_AKA_KI_LEN);
l_free(ki);
str = l_settings_get_value(key_settings, "AKA", "OPC");
if (!str) {
l_debug("OPC value must be preset for AKA");
goto end;
}
opc = l_util_from_hexstring(str, &len);
memcpy(sim->opc, opc, EAP_AKA_OPC_LEN);
l_free(opc);
str = l_settings_get_value(key_settings, "AKA", "AMF");
if (!str) {
l_debug("AMF value must be present for AKA");
goto end;
}
amf = l_util_from_hexstring(str, &len);
memcpy(sim->amf, amf, EAP_AKA_AMF_LEN);
l_free(amf);
str = l_settings_get_value(key_settings, "AKA", "SQN");
if (!str) {
l_debug("SQN value must be present for AKA");
goto end;
}
sqn = l_util_from_hexstring(str, &len);
memcpy(sim->sqn, sqn, EAP_AKA_SQN_LEN);
l_free(sqn);
str = l_settings_get_value(key_settings, "AKA", "Identity");
if (!str) {
l_debug("Identity setting must be present for AKA");
goto end;
}
sim->identity = l_strdup(str);
sim->aka_supported = 1;
}
end:
l_settings_free(key_settings);
if (!sim->sim_supported && !sim->aka_supported) {
l_debug("error parsing config file, values missing");
return -EINVAL;
}
sim->auth = iwd_sim_auth_create(&hardcoded_sim_driver);
iwd_sim_auth_set_nai(sim->auth, sim->identity);
iwd_sim_auth_set_capabilities(sim->auth, sim->sim_supported,
sim->aka_supported);
iwd_sim_auth_register(sim->auth);
return 0;
}
static void sim_hardcoded_exit(void)
{
iwd_sim_auth_remove(sim->auth);
if (sim)
l_free(sim->identity);
l_free(sim);
}
L_PLUGIN_DEFINE(__iwd_builtin_sim_hardcoded, sim_hardcoded,
"Hardcoded SIM driver", "1.0", L_PLUGIN_PRIORITY_DEFAULT,
sim_hardcoded_init, sim_hardcoded_exit)

View File

@ -40,7 +40,6 @@
#include "src/eap.h"
#include "src/eapol.h"
#include "src/rfkill.h"
#include "src/plugin.h"
#include "src/storage.h"
#include "src/anqp.h"
@ -54,8 +53,6 @@ static const char *interfaces;
static const char *nointerfaces;
static const char *phys;
static const char *nophys;
static const char *plugins;
static const char *noplugins;
static const char *debugopt;
static bool terminating;
static bool nl80211_complete;
@ -140,8 +137,6 @@ static void usage(void)
"\t-I, --nointerfaces Interfaces to ignore\n"
"\t-p, --phys Phys to manage\n"
"\t-P, --nophys Phys to ignore\n"
"\t-l, --plugin Plugins to include\n"
"\t-L, --noplugin Plugins to exclude\n"
"\t-d, --debug Enable debug output\n"
"\t-v, --version Show version\n"
"\t-h, --help Show help options\n");
@ -154,8 +149,6 @@ static const struct option main_options[] = {
{ "nointerfaces", required_argument, NULL, 'I' },
{ "phys", required_argument, NULL, 'p' },
{ "nophys", required_argument, NULL, 'P' },
{ "plugin", required_argument, NULL, 'l' },
{ "noplugin", required_argument, NULL, 'L' },
{ "debug", optional_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ }
@ -179,8 +172,6 @@ static void nl80211_appeared(const struct l_genl_family_info *info,
l_main_quit();
return;
}
plugin_init(plugins, noplugins);
}
static void request_name_callback(struct l_dbus *dbus, bool success,
@ -393,12 +384,6 @@ int main(int argc, char *argv[])
case 'P':
nophys = optarg;
break;
case 'l':
plugins = optarg;
break;
case 'L':
noplugins = optarg;
break;
case 'd':
if (optarg)
debugopt = optarg;
@ -504,7 +489,6 @@ int main(int argc, char *argv[])
exit_status = l_main_run_with_signal(signal_handler, NULL);
plugin_exit();
iwd_modules_exit();
dbus_exit();
l_dbus_destroy(dbus);