18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / EAP-SIM database/authenticator gateway
304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Copyright (c) 2005-2010, 2012, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This is an example implementation of the EAP-SIM/AKA database/authentication
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * gateway interface that is using an external program as an SS7 gateway to
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * GSM/UMTS authentication center (HLR/AuC). hlr_auc_gw is an example
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * implementation of such a gateway program. This eap_sim_db.c takes care of
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-SIM/AKA pseudonyms and re-auth identities. It can be used with different
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * gateway implementations for HLR/AuC access. Alternatively, it can also be
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * completely replaced if the in-memory database of pseudonyms/re-auth
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * identities is not suitable for some cases.
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/un.h>
204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#include <sqlite3.h>
224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h"
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_sim_common.h"
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_server/eap_sim_db.h"
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h"
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_sim_pseudonym {
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_pseudonym *next;
324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *permanent; /* permanent username */
334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *pseudonym; /* pseudonym username */
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_sim_db_pending {
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *next;
384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char imsi[20];
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum { PENDING, SUCCESS, FAILURE } state;
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *cb_session_ctx;
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int aka;
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union {
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct {
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 kc[EAP_SIM_MAX_CHAL][EAP_SIM_KC_LEN];
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 sres[EAP_SIM_MAX_CHAL][EAP_SIM_SRES_LEN];
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 rand[EAP_SIM_MAX_CHAL][GSM_RAND_LEN];
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			int num_chal;
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} sim;
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct {
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 rand[EAP_AKA_RAND_LEN];
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 autn[EAP_AKA_AUTN_LEN];
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 ik[EAP_AKA_IK_LEN];
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 ck[EAP_AKA_CK_LEN];
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 res[EAP_AKA_RES_MAX_LEN];
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			size_t res_len;
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} aka;
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} u;
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_sim_db_data {
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int sock;
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *fname;
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *local_sock;
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void (*get_complete_cb)(void *ctx, void *session_ctx);
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *ctx;
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_pseudonym *pseudonyms;
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_reauth *reauths;
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *pending;
69d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	unsigned int eap_sim_db_timeout;
704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	sqlite3 *sqlite_db;
724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char db_tmp_identity[100];
734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char db_tmp_pseudonym_str[100];
744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	struct eap_sim_pseudonym db_tmp_pseudonym;
754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	struct eap_sim_reauth db_tmp_reauth;
764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
80d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic void eap_sim_db_del_timeout(void *eloop_ctx, void *user_ctx);
81d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic void eap_sim_db_query_timeout(void *eloop_ctx, void *user_ctx);
82d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
83d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int db_table_exists(sqlite3 *db, const char *name)
874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char cmd[128];
894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_snprintf(cmd, sizeof(cmd), "SELECT 1 FROM %s;", name);
904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return sqlite3_exec(db, cmd, NULL, NULL, NULL) == SQLITE_OK;
914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int db_table_create_pseudonym(sqlite3 *db)
954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *err = NULL;
974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	const char *sql =
984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"CREATE TABLE pseudonyms("
994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  permanent CHAR(21) PRIMARY KEY,"
1004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  pseudonym CHAR(21) NOT NULL"
1014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		");";
1024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Adding database table for "
1044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   "pseudonym information");
1054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) {
1064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_ERROR, "EAP-SIM DB: SQLite error: %s", err);
1074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_free(err);
1084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return -1;
1094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 0;
1124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
1134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int db_table_create_reauth(sqlite3 *db)
1164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
1174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *err = NULL;
1184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	const char *sql =
1194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"CREATE TABLE reauth("
1204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  permanent CHAR(21) PRIMARY KEY,"
1214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  reauth_id CHAR(21) NOT NULL,"
1224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  counter INTEGER,"
1234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  mk CHAR(40),"
1244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  k_encr CHAR(32),"
1254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  k_aut CHAR(64),"
1264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  k_re CHAR(64)"
1274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		");";
1284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Adding database table for "
1304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   "reauth information");
1314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) {
1324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_ERROR, "EAP-SIM DB: SQLite error: %s", err);
1334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_free(err);
1344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return -1;
1354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 0;
1384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
1394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic sqlite3 * db_open(const char *db_file)
1424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
1434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	sqlite3 *db;
1444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sqlite3_open(db_file, &db)) {
1464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_ERROR, "EAP-SIM DB: Failed to open database "
1474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   "%s: %s", db_file, sqlite3_errmsg(db));
1484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_close(db);
1494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
1504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!db_table_exists(db, "pseudonyms") &&
1534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    db_table_create_pseudonym(db) < 0) {
1544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_close(db);
1554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
1564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!db_table_exists(db, "reauth") &&
1594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    db_table_create_reauth(db) < 0) {
1604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_close(db);
1614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
1624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return db;
1654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
1664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int valid_db_string(const char *str)
1694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
1704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	const char *pos = str;
1714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	while (*pos) {
1724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if ((*pos < '0' || *pos > '9') &&
1734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    (*pos < 'a' || *pos > 'f'))
1744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			return 0;
1754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos++;
1764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 1;
1784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
1794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int db_add_pseudonym(struct eap_sim_db_data *data,
1824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			    const char *permanent, char *pseudonym)
1834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
1844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char cmd[128];
1854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *err = NULL;
1864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!valid_db_string(permanent) || !valid_db_string(pseudonym)) {
1884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		os_free(pseudonym);
1894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return -1;
1904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_snprintf(cmd, sizeof(cmd), "INSERT OR REPLACE INTO pseudonyms "
1934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    "(permanent, pseudonym) VALUES ('%s', '%s');",
1944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    permanent, pseudonym);
1954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_free(pseudonym);
1964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sqlite3_exec(data->sqlite_db, cmd, NULL, NULL, &err) != SQLITE_OK)
1974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	{
1984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_ERROR, "EAP-SIM DB: SQLite error: %s", err);
1994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_free(err);
2004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return -1;
2014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
2024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 0;
2044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
2054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int get_pseudonym_cb(void *ctx, int argc, char *argv[], char *col[])
2084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
2094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	struct eap_sim_db_data *data = ctx;
2104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	int i;
2114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	for (i = 0; i < argc; i++) {
2134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (os_strcmp(col[i], "permanent") == 0 && argv[i]) {
2144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			os_strlcpy(data->db_tmp_identity, argv[i],
2154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				   sizeof(data->db_tmp_identity));
2164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		}
2174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
2184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 0;
2204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
2214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic char *
2244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtdb_get_pseudonym(struct eap_sim_db_data *data, const char *pseudonym)
2254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
2264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char cmd[128];
2274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!valid_db_string(pseudonym))
2294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
2304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_memset(&data->db_tmp_identity, 0, sizeof(data->db_tmp_identity));
2314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_snprintf(cmd, sizeof(cmd),
2324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    "SELECT permanent FROM pseudonyms WHERE pseudonym='%s';",
2334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    pseudonym);
2344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sqlite3_exec(data->sqlite_db, cmd, get_pseudonym_cb, data, NULL) !=
2354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    SQLITE_OK)
2364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
2374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->db_tmp_identity[0] == '\0')
2384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
2394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return data->db_tmp_identity;
2404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
2414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int db_add_reauth(struct eap_sim_db_data *data, const char *permanent,
2444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			 char *reauth_id, u16 counter, const u8 *mk,
2454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			 const u8 *k_encr, const u8 *k_aut, const u8 *k_re)
2464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
2474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char cmd[2000], *pos, *end;
2484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *err = NULL;
2494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!valid_db_string(permanent) || !valid_db_string(reauth_id)) {
2514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		os_free(reauth_id);
2524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return -1;
2534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
2544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	pos = cmd;
2564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	end = pos + sizeof(cmd);
2574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	pos += os_snprintf(pos, end - pos, "INSERT OR REPLACE INTO reauth "
2584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   "(permanent, reauth_id, counter%s%s%s%s) "
2594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   "VALUES ('%s', '%s', %u",
2604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   mk ? ", mk" : "",
2614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   k_encr ? ", k_encr" : "",
2624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   k_aut ? ", k_aut" : "",
2634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   k_re ? ", k_re" : "",
2644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   permanent, reauth_id, counter);
2654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_free(reauth_id);
2664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (mk) {
2684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, ", '");
2694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += wpa_snprintf_hex(pos, end - pos, mk, EAP_SIM_MK_LEN);
2704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, "'");
2714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
2724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (k_encr) {
2744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, ", '");
2754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += wpa_snprintf_hex(pos, end - pos, k_encr,
2764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt					EAP_SIM_K_ENCR_LEN);
2774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, "'");
2784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
2794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (k_aut) {
2814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, ", '");
2824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += wpa_snprintf_hex(pos, end - pos, k_aut,
2834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt					EAP_AKA_PRIME_K_AUT_LEN);
2844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, "'");
2854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
2864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (k_re) {
2884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, ", '");
2894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += wpa_snprintf_hex(pos, end - pos, k_re,
2904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt					EAP_AKA_PRIME_K_RE_LEN);
2914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, "'");
2924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
2934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_snprintf(pos, end - pos, ");");
2954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sqlite3_exec(data->sqlite_db, cmd, NULL, NULL, &err) != SQLITE_OK)
2974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	{
2984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_ERROR, "EAP-SIM DB: SQLite error: %s", err);
2994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_free(err);
3004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return -1;
3014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
3024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 0;
3044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
3054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int get_reauth_cb(void *ctx, int argc, char *argv[], char *col[])
3084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
3094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	struct eap_sim_db_data *data = ctx;
3104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	int i;
3114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	struct eap_sim_reauth *reauth = &data->db_tmp_reauth;
3124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	for (i = 0; i < argc; i++) {
3144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (os_strcmp(col[i], "permanent") == 0 && argv[i]) {
3154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			os_strlcpy(data->db_tmp_identity, argv[i],
3164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				   sizeof(data->db_tmp_identity));
3174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			reauth->permanent = data->db_tmp_identity;
3184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		} else if (os_strcmp(col[i], "counter") == 0 && argv[i]) {
3194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			reauth->counter = atoi(argv[i]);
3204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		} else if (os_strcmp(col[i], "mk") == 0 && argv[i]) {
3214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			hexstr2bin(argv[i], reauth->mk, sizeof(reauth->mk));
3224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		} else if (os_strcmp(col[i], "k_encr") == 0 && argv[i]) {
3234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			hexstr2bin(argv[i], reauth->k_encr,
3244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				   sizeof(reauth->k_encr));
3254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		} else if (os_strcmp(col[i], "k_aut") == 0 && argv[i]) {
3264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			hexstr2bin(argv[i], reauth->k_aut,
3274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				   sizeof(reauth->k_aut));
3284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		} else if (os_strcmp(col[i], "k_re") == 0 && argv[i]) {
3294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			hexstr2bin(argv[i], reauth->k_re,
3304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				   sizeof(reauth->k_re));
3314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		}
3324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
3334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 0;
3354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
3364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic struct eap_sim_reauth *
3394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtdb_get_reauth(struct eap_sim_db_data *data, const char *reauth_id)
3404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
3414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char cmd[256];
3424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!valid_db_string(reauth_id))
3444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
3454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_memset(&data->db_tmp_reauth, 0, sizeof(data->db_tmp_reauth));
3464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_strlcpy(data->db_tmp_pseudonym_str, reauth_id,
3474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   sizeof(data->db_tmp_pseudonym_str));
3484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	data->db_tmp_reauth.reauth_id = data->db_tmp_pseudonym_str;
3494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_snprintf(cmd, sizeof(cmd),
3504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    "SELECT * FROM reauth WHERE reauth_id='%s';", reauth_id);
3514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sqlite3_exec(data->sqlite_db, cmd, get_reauth_cb, data, NULL) !=
3524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    SQLITE_OK)
3534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
3544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->db_tmp_reauth.permanent == NULL)
3554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
3564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return &data->db_tmp_reauth;
3574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
3584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic void db_remove_reauth(struct eap_sim_db_data *data,
3614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			     struct eap_sim_reauth *reauth)
3624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
3634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char cmd[256];
3644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!valid_db_string(reauth->permanent))
3664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return;
3674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_snprintf(cmd, sizeof(cmd),
3684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    "DELETE FROM reauth WHERE permanent='%s';",
3694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    reauth->permanent);
3704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	sqlite3_exec(data->sqlite_db, cmd, NULL, NULL, NULL);
3714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
3724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
3744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct eap_sim_db_pending *
3774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidteap_sim_db_get_pending(struct eap_sim_db_data *data, const char *imsi, int aka)
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *entry, *prev = NULL;
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry = data->pending;
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (entry) {
3834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (entry->aka == aka && os_strcmp(entry->imsi, imsi) == 0) {
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (prev)
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				prev->next = entry->next;
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				data->pending = entry->next;
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = entry;
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry = entry->next;
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return entry;
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_add_pending(struct eap_sim_db_data *data,
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   struct eap_sim_db_pending *entry)
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->next = data->pending;
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->pending = entry;
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
405d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic void eap_sim_db_free_pending(struct eap_sim_db_data *data,
406d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				    struct eap_sim_db_pending *entry)
407d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
408d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	eloop_cancel_timeout(eap_sim_db_query_timeout, data, entry);
409d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	eloop_cancel_timeout(eap_sim_db_del_timeout, data, entry);
410d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	os_free(entry);
411d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
412d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
413d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
414d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic void eap_sim_db_del_pending(struct eap_sim_db_data *data,
415d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				   struct eap_sim_db_pending *entry)
416d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
417d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct eap_sim_db_pending **pp = &data->pending;
418d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
419d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	while (*pp != NULL) {
420d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (*pp == entry) {
421d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			*pp = entry->next;
422d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			eap_sim_db_free_pending(data, entry);
423d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			return;
424d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		}
425d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		pp = &(*pp)->next;
426d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
427d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
428d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
429d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
430d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic void eap_sim_db_del_timeout(void *eloop_ctx, void *user_ctx)
431d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
432d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct eap_sim_db_data *data = eloop_ctx;
433d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct eap_sim_db_pending *entry = user_ctx;
434d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
435d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Delete query timeout for %p", entry);
436d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	eap_sim_db_del_pending(data, entry);
437d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
438d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
439d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
440d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic void eap_sim_db_query_timeout(void *eloop_ctx, void *user_ctx)
441d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
442d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct eap_sim_db_data *data = eloop_ctx;
443d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct eap_sim_db_pending *entry = user_ctx;
444d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
445d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	/*
446d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	 * Report failure and allow some time for EAP server to process it
447d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	 * before deleting the query.
448d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	 */
449d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Query timeout for %p", entry);
450d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	entry->state = FAILURE;
451d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	data->get_complete_cb(data->ctx, entry->cb_session_ctx);
452d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	eloop_register_timeout(1, 0, eap_sim_db_del_timeout, data, entry);
453d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
454d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
455d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_sim_resp_auth(struct eap_sim_db_data *data,
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const char *imsi, char *buf)
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *start, *end, *pos;
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *entry;
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int num_chal;
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * SIM-RESP-AUTH <IMSI> Kc(i):SRES(i):RAND(i) ...
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * SIM-RESP-AUTH <IMSI> FAILURE
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (IMSI = ASCII string, Kc/SRES/RAND = hex string)
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	entry = eap_sim_db_get_pending(data, imsi, 0);
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry == NULL) {
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: No pending entry for the "
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received message found");
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = buf;
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strncmp(start, "FAILURE", 7) == 0) {
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: External server reported "
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failure");
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry->state = FAILURE;
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sim_db_add_pending(data, entry);
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->get_complete_cb(data->ctx, entry->cb_session_ctx);
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_chal = 0;
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (num_chal < EAP_SIM_MAX_CHAL) {
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		end = os_strchr(start, ' ');
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (end)
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*end = '\0';
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = os_strchr(start, ':');
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos == NULL)
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto parse_fail;
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos = '\0';
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hexstr2bin(start, entry->u.sim.kc[num_chal],
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       EAP_SIM_KC_LEN))
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto parse_fail;
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		start = pos + 1;
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = os_strchr(start, ':');
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos == NULL)
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto parse_fail;
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos = '\0';
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hexstr2bin(start, entry->u.sim.sres[num_chal],
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       EAP_SIM_SRES_LEN))
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto parse_fail;
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		start = pos + 1;
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hexstr2bin(start, entry->u.sim.rand[num_chal],
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       GSM_RAND_LEN))
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto parse_fail;
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_chal++;
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (end == NULL)
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			start = end + 1;
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->u.sim.num_chal = num_chal;
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->state = SUCCESS;
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Authentication data parsed "
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "successfully - callback");
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sim_db_add_pending(data, entry);
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->get_complete_cb(data->ctx, entry->cb_session_ctx);
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtparse_fail:
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string");
531d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	eap_sim_db_free_pending(data, entry);
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_aka_resp_auth(struct eap_sim_db_data *data,
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const char *imsi, char *buf)
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *start, *end;
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *entry;
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES>
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * AKA-RESP-AUTH <IMSI> FAILURE
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (IMSI = ASCII string, RAND/AUTN/IK/CK/RES = hex string)
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	entry = eap_sim_db_get_pending(data, imsi, 1);
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry == NULL) {
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: No pending entry for the "
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received message found");
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = buf;
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strncmp(start, "FAILURE", 7) == 0) {
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: External server reported "
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failure");
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry->state = FAILURE;
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sim_db_add_pending(data, entry);
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->get_complete_cb(data->ctx, entry->cb_session_ctx);
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = os_strchr(start, ' ');
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end == NULL)
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*end = '\0';
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hexstr2bin(start, entry->u.aka.rand, EAP_AKA_RAND_LEN))
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = end + 1;
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = os_strchr(start, ' ');
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end == NULL)
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*end = '\0';
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hexstr2bin(start, entry->u.aka.autn, EAP_AKA_AUTN_LEN))
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = end + 1;
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = os_strchr(start, ' ');
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end == NULL)
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*end = '\0';
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hexstr2bin(start, entry->u.aka.ik, EAP_AKA_IK_LEN))
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = end + 1;
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = os_strchr(start, ' ');
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end == NULL)
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*end = '\0';
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hexstr2bin(start, entry->u.aka.ck, EAP_AKA_CK_LEN))
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = end + 1;
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = os_strchr(start, ' ');
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end)
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*end = '\0';
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		end = start;
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*end)
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end++;
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->u.aka.res_len = (end - start) / 2;
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry->u.aka.res_len > EAP_AKA_RES_MAX_LEN) {
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Too long RES");
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry->u.aka.res_len = 0;
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hexstr2bin(start, entry->u.aka.res, entry->u.aka.res_len))
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->state = SUCCESS;
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Authentication data parsed "
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "successfully - callback");
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sim_db_add_pending(data, entry);
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->get_complete_cb(data->ctx, entry->cb_session_ctx);
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtparse_fail:
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string");
622d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	eap_sim_db_free_pending(data, entry);
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_receive(int sock, void *eloop_ctx, void *sock_ctx)
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_data *data = eloop_ctx;
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[1000], *pos, *cmd, *imsi;
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
632fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	res = recv(sock, buf, sizeof(buf) - 1, 0);
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0)
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
635fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	buf[res] = '\0';
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-SIM DB: Received from an "
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      "external source", (u8 *) buf, res);
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res == 0)
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->get_complete_cb == NULL) {
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: No get_complete_cb "
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "registered");
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* <cmd> <IMSI> ... */
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmd = buf;
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = os_strchr(cmd, ' ');
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos == NULL)
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos = '\0';
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	imsi = pos + 1;
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = os_strchr(imsi, ' ');
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos == NULL)
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos = '\0';
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: External response=%s for IMSI %s",
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   cmd, imsi);
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strcmp(cmd, "SIM-RESP-AUTH") == 0)
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sim_db_sim_resp_auth(data, imsi, pos + 1);
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (os_strcmp(cmd, "AKA-RESP-AUTH") == 0)
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sim_db_aka_resp_auth(data, imsi, pos + 1);
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-SIM DB: Unknown external response "
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "'%s'", cmd);
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtparse_fail:
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string");
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sim_db_open_socket(struct eap_sim_db_data *data)
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sockaddr_un addr;
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	static int counter = 0;
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strncmp(data->fname, "unix:", 5) != 0)
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->sock = socket(PF_UNIX, SOCK_DGRAM, 0);
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->sock < 0) {
686cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		wpa_printf(MSG_INFO, "socket(eap_sim_db): %s", strerror(errno));
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&addr, 0, sizeof(addr));
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr.sun_family = AF_UNIX;
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(addr.sun_path, sizeof(addr.sun_path),
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    "/tmp/eap_sim_db_%d-%d", getpid(), counter++);
69461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_free(data->local_sock);
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->local_sock = os_strdup(addr.sun_path);
696bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt	if (data->local_sock == NULL) {
697bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt		close(data->sock);
698bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt		data->sock = -1;
699bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt		return -1;
700bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt	}
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bind(data->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
702cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		wpa_printf(MSG_INFO, "bind(eap_sim_db): %s", strerror(errno));
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(data->sock);
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->sock = -1;
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&addr, 0, sizeof(addr));
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr.sun_family = AF_UNIX;
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(addr.sun_path, data->fname + 5, sizeof(addr.sun_path));
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (connect(data->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
712cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		wpa_printf(MSG_INFO, "connect(eap_sim_db): %s",
713cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			   strerror(errno));
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_ascii(MSG_INFO, "HLR/AuC GW socket",
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  (u8 *) addr.sun_path,
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  os_strlen(addr.sun_path));
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(data->sock);
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->sock = -1;
719bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt		unlink(data->local_sock);
720bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt		os_free(data->local_sock);
721bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt		data->local_sock = NULL;
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_read_sock(data->sock, eap_sim_db_receive, data, NULL);
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_close_socket(struct eap_sim_db_data *data)
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->sock >= 0) {
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_unregister_read_sock(data->sock);
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(data->sock);
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->sock = -1;
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->local_sock) {
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unlink(data->local_sock);
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(data->local_sock);
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->local_sock = NULL;
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_init - Initialize EAP-SIM DB / authentication gateway interface
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Configuration data (e.g., file name)
749d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * @db_timeout: Database lookup timeout
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @get_complete_cb: Callback function for reporting availability of triplets
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ctx: Context pointer for get_complete_cb
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to a private data structure or %NULL on failure
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
7544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstruct eap_sim_db_data *
755d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidteap_sim_db_init(const char *config, unsigned int db_timeout,
7564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		void (*get_complete_cb)(void *ctx, void *session_ctx),
7574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		void *ctx)
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_data *data;
7604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *pos;
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data = os_zalloc(sizeof(*data));
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data == NULL)
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->sock = -1;
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->get_complete_cb = get_complete_cb;
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->ctx = ctx;
769d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	data->eap_sim_db_timeout = db_timeout;
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->fname = os_strdup(config);
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->fname == NULL)
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
7734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	pos = os_strstr(data->fname, " db=");
7744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (pos) {
7754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		*pos = '\0';
7764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
7774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += 4;
7784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		data->sqlite_db = db_open(pos);
7794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (data->sqlite_db == NULL)
7804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			goto fail;
7814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
7824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strncmp(data->fname, "unix:", 5) == 0) {
78561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (eap_sim_db_open_socket(data)) {
78661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-SIM DB: External database "
78761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   "connection not available - will retry "
78861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   "later");
78961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return data;
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail:
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sim_db_close_socket(data);
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(data->fname);
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(data);
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_free_pseudonym(struct eap_sim_pseudonym *p)
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_free(p->permanent);
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p->pseudonym);
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p);
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_free_reauth(struct eap_sim_reauth *r)
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_free(r->permanent);
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(r->reauth_id);
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(r);
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_deinit - Deinitialize EAP-SIM DB/authentication gw interface
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Private data pointer from eap_sim_db_init()
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_sim_db_deinit(void *priv)
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_data *data = priv;
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_pseudonym *p, *prev;
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_reauth *r, *prevr;
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *pending, *prev_pending;
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
8304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->sqlite_db) {
8314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_close(data->sqlite_db);
8324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		data->sqlite_db = NULL;
8334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
8344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
8354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sim_db_close_socket(data);
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(data->fname);
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p = data->pseudonyms;
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (p) {
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = p;
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p = p->next;
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sim_db_free_pseudonym(prev);
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	r = data->reauths;
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (r) {
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prevr = r;
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r = r->next;
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sim_db_free_reauth(prevr);
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pending = data->pending;
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pending) {
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev_pending = pending;
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pending = pending->next;
857d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		eap_sim_db_free_pending(data, prev_pending);
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(data);
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sim_db_send(struct eap_sim_db_data *data, const char *msg,
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   size_t len)
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int _errno = 0;
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (send(data->sock, msg, len, 0) < 0) {
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		_errno = errno;
871cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		wpa_printf(MSG_INFO, "send[EAP-SIM DB UNIX]: %s",
872cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			   strerror(errno));
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL ||
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    _errno == ECONNREFUSED) {
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Try to reconnect */
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sim_db_close_socket(data);
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_sim_db_open_socket(data) < 0)
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Reconnected to the "
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "external server");
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (send(data->sock, msg, len, 0) < 0) {
884cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			wpa_printf(MSG_INFO, "send[EAP-SIM DB UNIX]: %s",
885cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt				   strerror(errno));
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
894d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic void eap_sim_db_expire_pending(struct eap_sim_db_data *data,
895d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				      struct eap_sim_db_pending *entry)
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
897d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	eloop_register_timeout(data->eap_sim_db_timeout, 0,
898d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			       eap_sim_db_query_timeout, data, entry);
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_gsm_triplets - Get GSM triplets
9044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
9054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @username: Permanent username (prefix | IMSI)
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @max_chal: Maximum number of triplets
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @_rand: Buffer for RAND values
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @kc: Buffer for Kc values
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sres: Buffer for SRES values
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cb_session_ctx: Session callback context for get_complete_cb()
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of triplets received (has to be less than or equal to
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * max_chal), -1 (EAP_SIM_DB_FAILURE) on error (e.g., user not found), or
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * -2 (EAP_SIM_DB_PENDING) if results are not yet available. In this case, the
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * callback function registered with eap_sim_db_init() will be called once the
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * results become available.
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * When using an external server for GSM triplets, this function can always
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * start a request and return EAP_SIM_DB_PENDING immediately if authentication
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * triplets are not available. Once the triplets are received, callback
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * function registered with eap_sim_db_init() is called to notify EAP state
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * machine to reprocess the message. This eap_sim_db_get_gsm_triplets()
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * function will then be called again and the newly received triplets will then
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * be given to the caller.
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
9254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint eap_sim_db_get_gsm_triplets(struct eap_sim_db_data *data,
9264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				const char *username, int max_chal,
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				u8 *_rand, u8 *kc, u8 *sres,
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				void *cb_session_ctx)
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *entry;
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len, ret;
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char msg[40];
9334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	const char *imsi;
9344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	size_t imsi_len;
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (username == NULL || username[0] != EAP_SIM_PERMANENT_PREFIX ||
9374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    username[1] == '\0' || os_strlen(username) > sizeof(entry->imsi)) {
9384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: unexpected username '%s'",
9394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   username);
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	imsi = username + 1;
9434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Get GSM triplets for IMSI '%s'",
9444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   imsi);
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	entry = eap_sim_db_get_pending(data, imsi, 0);
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry) {
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int num_chal;
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (entry->state == FAILURE) {
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> "
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "failure");
952d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			eap_sim_db_free_pending(data, entry);
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EAP_SIM_DB_FAILURE;
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (entry->state == PENDING) {
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> "
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "still pending");
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_sim_db_add_pending(data, entry);
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EAP_SIM_DB_PENDING;
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> "
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "%d challenges", entry->u.sim.num_chal);
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_chal = entry->u.sim.num_chal;
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (num_chal > max_chal)
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			num_chal = max_chal;
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(_rand, entry->u.sim.rand, num_chal * GSM_RAND_LEN);
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(sres, entry->u.sim.sres,
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  num_chal * EAP_SIM_SRES_LEN);
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(kc, entry->u.sim.kc, num_chal * EAP_SIM_KC_LEN);
972d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		eap_sim_db_free_pending(data, entry);
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return num_chal;
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->sock < 0) {
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_sim_db_open_socket(data) < 0)
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EAP_SIM_DB_FAILURE;
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	imsi_len = os_strlen(imsi);
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = os_snprintf(msg, sizeof(msg), "SIM-REQ-AUTH ");
983fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	if (os_snprintf_error(sizeof(msg), len) ||
984fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	    len + imsi_len >= sizeof(msg))
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
9864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_memcpy(msg + len, imsi, imsi_len);
9874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	len += imsi_len;
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = os_snprintf(msg + len, sizeof(msg) - len, " %d", max_chal);
989fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	if (os_snprintf_error(sizeof(msg) - len, ret))
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len += ret;
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: requesting SIM authentication "
9944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   "data for IMSI '%s'", imsi);
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_sim_db_send(data, msg, len) < 0)
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry = os_zalloc(sizeof(*entry));
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry == NULL)
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_strlcpy(entry->imsi, imsi, sizeof(entry->imsi));
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->cb_session_ctx = cb_session_ctx;
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->state = PENDING;
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sim_db_add_pending(data, entry);
1006d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	eap_sim_db_expire_pending(data, entry);
1007d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Added query %p", entry);
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return EAP_SIM_DB_PENDING;
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * eap_sim_db_get_next(struct eap_sim_db_data *data, char prefix)
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *id, *pos, *end;
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 buf[10];
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (random_get_bytes(buf, sizeof(buf)))
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	id = os_malloc(sizeof(buf) * 2 + 2);
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (id == NULL)
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = id;
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = id + sizeof(buf) * 2 + 2;
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = prefix;
1027fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	wpa_snprintf_hex(pos, end - pos, buf, sizeof(buf));
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return id;
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_next_pseudonym - EAP-SIM DB: Get next pseudonym
10354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
103604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * @method: EAP method (SIM/AKA/AKA')
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Next pseudonym (allocated string) or %NULL on failure
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to generate a pseudonym for EAP-SIM. The returned
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pseudonym is not added to database at this point; it will need to be added
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * with eap_sim_db_add_pseudonym() once the authentication has been completed
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * successfully. Caller is responsible for freeing the returned buffer.
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
10444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtchar * eap_sim_db_get_next_pseudonym(struct eap_sim_db_data *data,
10454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				     enum eap_sim_db_method method)
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
104704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	char prefix = EAP_SIM_REAUTH_ID_PREFIX;
104804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
104904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	switch (method) {
105004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SIM_DB_SIM:
105104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		prefix = EAP_SIM_PSEUDONYM_PREFIX;
105204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
105304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SIM_DB_AKA:
105404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		prefix = EAP_AKA_PSEUDONYM_PREFIX;
105504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
105604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SIM_DB_AKA_PRIME:
105704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		prefix = EAP_AKA_PRIME_PSEUDONYM_PREFIX;
105804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
105904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
106004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
106104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return eap_sim_db_get_next(data, prefix);
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_next_reauth_id - EAP-SIM DB: Get next reauth_id
10674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
106804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * @method: EAP method (SIM/AKA/AKA')
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Next reauth_id (allocated string) or %NULL on failure
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to generate a fast re-authentication identity for
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-SIM. The returned reauth_id is not added to database at this point; it
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * will need to be added with eap_sim_db_add_reauth() once the authentication
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * has been completed successfully. Caller is responsible for freeing the
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * returned buffer.
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
10774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtchar * eap_sim_db_get_next_reauth_id(struct eap_sim_db_data *data,
10784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				     enum eap_sim_db_method method)
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
108004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	char prefix = EAP_SIM_REAUTH_ID_PREFIX;
108104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
108204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	switch (method) {
108304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SIM_DB_SIM:
108404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		prefix = EAP_SIM_REAUTH_ID_PREFIX;
108504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
108604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SIM_DB_AKA:
108704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		prefix = EAP_AKA_REAUTH_ID_PREFIX;
108804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
108904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SIM_DB_AKA_PRIME:
109004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		prefix = EAP_AKA_PRIME_REAUTH_ID_PREFIX;
109104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
109204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
109304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
109404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return eap_sim_db_get_next(data, prefix);
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_add_pseudonym - EAP-SIM DB: Add new pseudonym
11004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
11014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @permanent: Permanent username
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pseudonym: Pseudonym for this user. This needs to be an allocated buffer,
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * e.g., return value from eap_sim_db_get_next_pseudonym(). Caller must not
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * free it.
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function adds a new pseudonym for EAP-SIM user. EAP-SIM DB is
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * responsible of freeing pseudonym buffer once it is not needed anymore.
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
11104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint eap_sim_db_add_pseudonym(struct eap_sim_db_data *data,
11114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			     const char *permanent, char *pseudonym)
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_pseudonym *p;
11144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Add pseudonym '%s' for permanent "
11154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   "username '%s'", pseudonym, permanent);
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: could store last two pseudonyms */
11184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
11194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->sqlite_db)
11204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return db_add_pseudonym(data, permanent, pseudonym);
11214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
11224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	for (p = data->pseudonyms; p; p = p->next) {
11234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (os_strcmp(permanent, p->permanent) == 0)
11244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			break;
11254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p) {
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Replacing previous "
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "pseudonym: %s", p->pseudonym);
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p->pseudonym);
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p->pseudonym = pseudonym;
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p = os_zalloc(sizeof(*p));
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p == NULL) {
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(pseudonym);
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p->next = data->pseudonyms;
11414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	p->permanent = os_strdup(permanent);
11424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (p->permanent == NULL) {
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p);
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(pseudonym);
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p->pseudonym = pseudonym;
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->pseudonyms = p;
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Added new pseudonym entry");
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct eap_sim_reauth *
11564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidteap_sim_db_add_reauth_data(struct eap_sim_db_data *data,
11574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   const char *permanent,
11584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   char *reauth_id, u16 counter)
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_reauth *r;
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	for (r = data->reauths; r; r = r->next) {
11634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (os_strcmp(r->permanent, permanent) == 0)
11644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			break;
11654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (r) {
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Replacing previous "
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "reauth_id: %s", r->reauth_id);
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(r->reauth_id);
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r->reauth_id = reauth_id;
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r = os_zalloc(sizeof(*r));
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (r == NULL) {
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(reauth_id);
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r->next = data->reauths;
11804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		r->permanent = os_strdup(permanent);
11814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (r->permanent == NULL) {
11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(r);
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(reauth_id);
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r->reauth_id = reauth_id;
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->reauths = r;
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Added new reauth entry");
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	r->counter = counter;
11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return r;
11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_add_reauth - EAP-SIM DB: Add new re-authentication entry
11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Private data pointer from eap_sim_db_init()
12004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @permanent: Permanent username
12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @identity_len: Length of identity
12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @reauth_id: reauth_id for this user. This needs to be an allocated buffer,
12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * e.g., return value from eap_sim_db_get_next_reauth_id(). Caller must not
12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * free it.
12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @counter: AT_COUNTER value for fast re-authentication
12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mk: 16-byte MK from the previous full authentication or %NULL
12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function adds a new re-authentication entry for an EAP-SIM user.
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-SIM DB is responsible of freeing reauth_id buffer once it is not needed
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * anymore.
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
12134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint eap_sim_db_add_reauth(struct eap_sim_db_data *data, const char *permanent,
12144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			  char *reauth_id, u16 counter, const u8 *mk)
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_reauth *r;
12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Add reauth_id '%s' for permanent "
12194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   "identity '%s'", reauth_id, permanent);
12204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
12214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
12224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->sqlite_db)
12234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return db_add_reauth(data, permanent, reauth_id, counter, mk,
12244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				     NULL, NULL, NULL);
12254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
12264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	r = eap_sim_db_add_reauth_data(data, permanent, reauth_id, counter);
12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (r == NULL)
12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(r->mk, mk, EAP_SIM_MK_LEN);
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_AKA_PRIME
12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_add_reauth_prime - EAP-AKA' DB: Add new re-authentication entry
12394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
12404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @permanent: Permanent username
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @reauth_id: reauth_id for this user. This needs to be an allocated buffer,
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * e.g., return value from eap_sim_db_get_next_reauth_id(). Caller must not
12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * free it.
12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @counter: AT_COUNTER value for fast re-authentication
12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @k_encr: K_encr from the previous full authentication
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @k_aut: K_aut from the previous full authentication
12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @k_re: 32-byte K_re from the previous full authentication
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function adds a new re-authentication entry for an EAP-AKA' user.
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-SIM DB is responsible of freeing reauth_id buffer once it is not needed
12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * anymore.
12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
12544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint eap_sim_db_add_reauth_prime(struct eap_sim_db_data *data,
12554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				const char *permanent, char *reauth_id,
12564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				u16 counter, const u8 *k_encr,
12574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				const u8 *k_aut, const u8 *k_re)
12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_reauth *r;
12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Add reauth_id '%s' for permanent "
12624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   "identity '%s'", reauth_id, permanent);
12634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
12644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
12654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->sqlite_db)
12664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return db_add_reauth(data, permanent, reauth_id, counter, NULL,
12674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				     k_encr, k_aut, k_re);
12684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
12694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	r = eap_sim_db_add_reauth_data(data, permanent, reauth_id, counter);
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (r == NULL)
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(r->k_encr, k_encr, EAP_SIM_K_ENCR_LEN);
12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(r->k_aut, k_aut, EAP_AKA_PRIME_K_AUT_LEN);
12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(r->k_re, k_re, EAP_AKA_PRIME_K_RE_LEN);
12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_AKA_PRIME */
12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_permanent - EAP-SIM DB: Get permanent identity
12844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
12854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @pseudonym: Pseudonym username
12864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * Returns: Pointer to permanent username or %NULL if not found
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
12884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtconst char *
12894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidteap_sim_db_get_permanent(struct eap_sim_db_data *data, const char *pseudonym)
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_pseudonym *p;
12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
12944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->sqlite_db)
12954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return db_get_pseudonym(data, pseudonym);
12964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	p = data->pseudonyms;
12994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	while (p) {
13004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (os_strcmp(p->pseudonym, pseudonym) == 0)
13014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			return p->permanent;
13024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		p = p->next;
13034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return NULL;
13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_reauth_entry - EAP-SIM DB: Get re-authentication entry
13114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
13124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @reauth_id: Fast re-authentication username
13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the re-auth entry, or %NULL if not found
13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_sim_reauth *
13164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidteap_sim_db_get_reauth_entry(struct eap_sim_db_data *data,
13174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			    const char *reauth_id)
13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_reauth *r;
13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
13224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->sqlite_db)
13234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return db_get_reauth(data, reauth_id);
13244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
13254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
13264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	r = data->reauths;
13274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	while (r) {
13284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (os_strcmp(r->reauth_id, reauth_id) == 0)
13294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			break;
13304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		r = r->next;
13314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
13324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return r;
13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_remove_reauth - EAP-SIM DB: Remove re-authentication entry
13394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @reauth: Pointer to re-authentication entry from
13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_reauth_entry()
13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
13434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtvoid eap_sim_db_remove_reauth(struct eap_sim_db_data *data,
13444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			      struct eap_sim_reauth *reauth)
13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_reauth *r, *prev = NULL;
13474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
13484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->sqlite_db) {
13494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		db_remove_reauth(data, reauth);
13504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return;
13514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
13524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	r = data->reauths;
13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (r) {
13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (r == reauth) {
13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (prev)
13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				prev->next = r->next;
13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				data->reauths = r->next;
13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_sim_db_free_reauth(r);
13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = r;
13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r = r->next;
13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_aka_auth - Get AKA authentication values
13714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
13724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @username: Permanent username (prefix | IMSI)
13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @_rand: Buffer for RAND value
13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @autn: Buffer for AUTN value
13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ik: Buffer for IK value
13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ck: Buffer for CK value
13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @res: Buffer for RES value
13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @res_len: Buffer for RES length
13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cb_session_ctx: Session callback context for get_complete_cb()
13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 (EAP_SIM_DB_FAILURE) on error (e.g., user not
13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * found), or -2 (EAP_SIM_DB_PENDING) if results are not yet available. In this
13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * case, the callback function registered with eap_sim_db_init() will be
13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * called once the results become available.
13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * When using an external server for AKA authentication, this function can
13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * always start a request and return EAP_SIM_DB_PENDING immediately if
13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * authentication triplets are not available. Once the authentication data are
13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * received, callback function registered with eap_sim_db_init() is called to
13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * notify EAP state machine to reprocess the message. This
13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_aka_auth() function will then be called again and the newly
13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * received triplets will then be given to the caller.
13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
13934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint eap_sim_db_get_aka_auth(struct eap_sim_db_data *data, const char *username,
13944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			    u8 *_rand, u8 *autn, u8 *ik, u8 *ck,
13954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			    u8 *res, size_t *res_len, void *cb_session_ctx)
13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *entry;
13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len;
13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char msg[40];
14004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	const char *imsi;
14014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	size_t imsi_len;
14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (username == NULL ||
14044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    (username[0] != EAP_AKA_PERMANENT_PREFIX &&
14054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	     username[0] != EAP_AKA_PRIME_PERMANENT_PREFIX) ||
14064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    username[1] == '\0' || os_strlen(username) > sizeof(entry->imsi)) {
14074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: unexpected username '%s'",
14084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   username);
14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	imsi = username + 1;
14124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Get AKA auth for IMSI '%s'",
14134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   imsi);
14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	entry = eap_sim_db_get_pending(data, imsi, 1);
14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry) {
14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (entry->state == FAILURE) {
1418d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			eap_sim_db_free_pending(data, entry);
14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failure");
14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EAP_SIM_DB_FAILURE;
14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (entry->state == PENDING) {
14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_sim_db_add_pending(data, entry);
14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending");
14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EAP_SIM_DB_PENDING;
14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Returning successfully "
14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received authentication data");
14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(_rand, entry->u.aka.rand, EAP_AKA_RAND_LEN);
14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(autn, entry->u.aka.autn, EAP_AKA_AUTN_LEN);
14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(ik, entry->u.aka.ik, EAP_AKA_IK_LEN);
14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(ck, entry->u.aka.ck, EAP_AKA_CK_LEN);
14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(res, entry->u.aka.res, EAP_AKA_RES_MAX_LEN);
14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*res_len = entry->u.aka.res_len;
1437d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		eap_sim_db_free_pending(data, entry);
14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->sock < 0) {
14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_sim_db_open_socket(data) < 0)
14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EAP_SIM_DB_FAILURE;
14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	imsi_len = os_strlen(imsi);
14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = os_snprintf(msg, sizeof(msg), "AKA-REQ-AUTH ");
1448fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	if (os_snprintf_error(sizeof(msg), len) ||
1449fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	    len + imsi_len >= sizeof(msg))
14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
14514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_memcpy(msg + len, imsi, imsi_len);
14524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	len += imsi_len;
14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: requesting AKA authentication "
14554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    "data for IMSI '%s'", imsi);
14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_sim_db_send(data, msg, len) < 0)
14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry = os_zalloc(sizeof(*entry));
14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry == NULL)
14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->aka = 1;
14644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_strlcpy(entry->imsi, imsi, sizeof(entry->imsi));
14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->cb_session_ctx = cb_session_ctx;
14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->state = PENDING;
14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sim_db_add_pending(data, entry);
1468d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	eap_sim_db_expire_pending(data, entry);
1469d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Added query %p", entry);
14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return EAP_SIM_DB_PENDING;
14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_resynchronize - Resynchronize AKA AUTN
14774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
14784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @username: Permanent username
14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @auts: AUTS value from the peer
14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @_rand: RAND value used in the rejected message
14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called when the peer reports synchronization failure in the
14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AUTN value by sending AUTS. The AUTS and RAND values should be sent to
14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * HLR/AuC to allow it to resynchronize with the peer. After this,
14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_aka_auth() will be called again to to fetch updated
14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RAND/AUTN values for the next challenge.
14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
14894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint eap_sim_db_resynchronize(struct eap_sim_db_data *data,
14904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			     const char *username,
14914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			     const u8 *auts, const u8 *_rand)
14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	const char *imsi;
14944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	size_t imsi_len;
14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (username == NULL ||
14974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    (username[0] != EAP_AKA_PERMANENT_PREFIX &&
14984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	     username[0] != EAP_AKA_PRIME_PERMANENT_PREFIX) ||
14994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    username[1] == '\0' || os_strlen(username) > 20) {
15004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: unexpected username '%s'",
15014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   username);
15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	imsi = username + 1;
15054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Get AKA auth for IMSI '%s'",
15064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   imsi);
15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->sock >= 0) {
15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char msg[100];
15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int len, ret;
15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		imsi_len = os_strlen(imsi);
15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = os_snprintf(msg, sizeof(msg), "AKA-AUTS ");
1514fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		if (os_snprintf_error(sizeof(msg), len) ||
1515fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		    len + imsi_len >= sizeof(msg))
15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
15174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		os_memcpy(msg + len, imsi, imsi_len);
15184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		len += imsi_len;
15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(msg + len, sizeof(msg) - len, " ");
1521fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		if (os_snprintf_error(sizeof(msg) - len, ret))
15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len += ret;
15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len += wpa_snprintf_hex(msg + len, sizeof(msg) - len,
15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					auts, EAP_AKA_AUTS_LEN);
15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(msg + len, sizeof(msg) - len, " ");
1527fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		if (os_snprintf_error(sizeof(msg) - len, ret))
15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len += ret;
15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len += wpa_snprintf_hex(msg + len, sizeof(msg) - len,
15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					_rand, EAP_AKA_RAND_LEN);
15324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: reporting AKA AUTS for "
15334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   "IMSI '%s'", imsi);
15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_sim_db_send(data, msg, len) < 0)
15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
15414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
15424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt/**
15434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * sim_get_username - Extract username from SIM identity
15444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @identity: Identity
15454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @identity_len: Identity length
15464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * Returns: Allocated buffer with the username part of the identity
15474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt *
15484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * Caller is responsible for freeing the returned buffer with os_free().
15494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt */
15504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtchar * sim_get_username(const u8 *identity, size_t identity_len)
15514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
15524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	size_t pos;
15534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
15544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (identity == NULL)
15554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
15564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
15574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	for (pos = 0; pos < identity_len; pos++) {
15584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (identity[pos] == '@' || identity[pos] == '\0')
15594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			break;
15604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
15614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
15624b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	return dup_binstr(identity, pos);
15634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
1564