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	struct os_time timestamp;
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int aka;
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	union {
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct {
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 kc[EAP_SIM_MAX_CHAL][EAP_SIM_KC_LEN];
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 sres[EAP_SIM_MAX_CHAL][EAP_SIM_SRES_LEN];
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 rand[EAP_SIM_MAX_CHAL][GSM_RAND_LEN];
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			int num_chal;
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} sim;
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct {
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 rand[EAP_AKA_RAND_LEN];
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 autn[EAP_AKA_AUTN_LEN];
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 ik[EAP_AKA_IK_LEN];
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 ck[EAP_AKA_CK_LEN];
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 res[EAP_AKA_RES_MAX_LEN];
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			size_t res_len;
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} aka;
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} u;
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_sim_db_data {
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int sock;
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *fname;
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *local_sock;
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void (*get_complete_cb)(void *ctx, void *session_ctx);
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *ctx;
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_pseudonym *pseudonyms;
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_reauth *reauths;
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *pending;
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
804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int db_table_exists(sqlite3 *db, const char *name)
834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char cmd[128];
854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_snprintf(cmd, sizeof(cmd), "SELECT 1 FROM %s;", name);
864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return sqlite3_exec(db, cmd, NULL, NULL, NULL) == SQLITE_OK;
874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int db_table_create_pseudonym(sqlite3 *db)
914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *err = NULL;
934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	const char *sql =
944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"CREATE TABLE pseudonyms("
954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  permanent CHAR(21) PRIMARY KEY,"
964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  pseudonym CHAR(21) NOT NULL"
974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		");";
984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Adding database table for "
1004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   "pseudonym information");
1014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) {
1024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_ERROR, "EAP-SIM DB: SQLite error: %s", err);
1034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_free(err);
1044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return -1;
1054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 0;
1084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
1094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int db_table_create_reauth(sqlite3 *db)
1124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
1134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *err = NULL;
1144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	const char *sql =
1154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"CREATE TABLE reauth("
1164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  permanent CHAR(21) PRIMARY KEY,"
1174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  reauth_id CHAR(21) NOT NULL,"
1184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  counter INTEGER,"
1194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  mk CHAR(40),"
1204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  k_encr CHAR(32),"
1214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  k_aut CHAR(64),"
1224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		"  k_re CHAR(64)"
1234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		");";
1244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Adding database table for "
1264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   "reauth information");
1274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) {
1284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_ERROR, "EAP-SIM DB: SQLite error: %s", err);
1294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_free(err);
1304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return -1;
1314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 0;
1344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
1354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic sqlite3 * db_open(const char *db_file)
1384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
1394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	sqlite3 *db;
1404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sqlite3_open(db_file, &db)) {
1424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_ERROR, "EAP-SIM DB: Failed to open database "
1434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   "%s: %s", db_file, sqlite3_errmsg(db));
1444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_close(db);
1454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
1464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!db_table_exists(db, "pseudonyms") &&
1494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    db_table_create_pseudonym(db) < 0) {
1504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_close(db);
1514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
1524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!db_table_exists(db, "reauth") &&
1554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    db_table_create_reauth(db) < 0) {
1564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_close(db);
1574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
1584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return db;
1614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
1624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int valid_db_string(const char *str)
1654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
1664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	const char *pos = str;
1674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	while (*pos) {
1684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if ((*pos < '0' || *pos > '9') &&
1694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    (*pos < 'a' || *pos > 'f'))
1704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			return 0;
1714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos++;
1724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 1;
1744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
1754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int db_add_pseudonym(struct eap_sim_db_data *data,
1784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			    const char *permanent, char *pseudonym)
1794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
1804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char cmd[128];
1814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *err = NULL;
1824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!valid_db_string(permanent) || !valid_db_string(pseudonym)) {
1844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		os_free(pseudonym);
1854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return -1;
1864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_snprintf(cmd, sizeof(cmd), "INSERT OR REPLACE INTO pseudonyms "
1894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    "(permanent, pseudonym) VALUES ('%s', '%s');",
1904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    permanent, pseudonym);
1914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_free(pseudonym);
1924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sqlite3_exec(data->sqlite_db, cmd, NULL, NULL, &err) != SQLITE_OK)
1934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	{
1944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_ERROR, "EAP-SIM DB: SQLite error: %s", err);
1954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_free(err);
1964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return -1;
1974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
1984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
1994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 0;
2004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
2014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int get_pseudonym_cb(void *ctx, int argc, char *argv[], char *col[])
2044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
2054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	struct eap_sim_db_data *data = ctx;
2064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	int i;
2074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	for (i = 0; i < argc; i++) {
2094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (os_strcmp(col[i], "permanent") == 0 && argv[i]) {
2104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			os_strlcpy(data->db_tmp_identity, argv[i],
2114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				   sizeof(data->db_tmp_identity));
2124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		}
2134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
2144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 0;
2164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
2174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic char *
2204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtdb_get_pseudonym(struct eap_sim_db_data *data, const char *pseudonym)
2214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
2224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char cmd[128];
2234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!valid_db_string(pseudonym))
2254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
2264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_memset(&data->db_tmp_identity, 0, sizeof(data->db_tmp_identity));
2274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_snprintf(cmd, sizeof(cmd),
2284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    "SELECT permanent FROM pseudonyms WHERE pseudonym='%s';",
2294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    pseudonym);
2304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sqlite3_exec(data->sqlite_db, cmd, get_pseudonym_cb, data, NULL) !=
2314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    SQLITE_OK)
2324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
2334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->db_tmp_identity[0] == '\0')
2344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
2354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return data->db_tmp_identity;
2364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
2374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int db_add_reauth(struct eap_sim_db_data *data, const char *permanent,
2404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			 char *reauth_id, u16 counter, const u8 *mk,
2414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			 const u8 *k_encr, const u8 *k_aut, const u8 *k_re)
2424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
2434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char cmd[2000], *pos, *end;
2444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *err = NULL;
2454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!valid_db_string(permanent) || !valid_db_string(reauth_id)) {
2474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		os_free(reauth_id);
2484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return -1;
2494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
2504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	pos = cmd;
2524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	end = pos + sizeof(cmd);
2534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	pos += os_snprintf(pos, end - pos, "INSERT OR REPLACE INTO reauth "
2544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   "(permanent, reauth_id, counter%s%s%s%s) "
2554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   "VALUES ('%s', '%s', %u",
2564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   mk ? ", mk" : "",
2574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   k_encr ? ", k_encr" : "",
2584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   k_aut ? ", k_aut" : "",
2594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   k_re ? ", k_re" : "",
2604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   permanent, reauth_id, counter);
2614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_free(reauth_id);
2624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (mk) {
2644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, ", '");
2654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += wpa_snprintf_hex(pos, end - pos, mk, EAP_SIM_MK_LEN);
2664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, "'");
2674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
2684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (k_encr) {
2704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, ", '");
2714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += wpa_snprintf_hex(pos, end - pos, k_encr,
2724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt					EAP_SIM_K_ENCR_LEN);
2734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, "'");
2744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
2754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (k_aut) {
2774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, ", '");
2784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += wpa_snprintf_hex(pos, end - pos, k_aut,
2794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt					EAP_AKA_PRIME_K_AUT_LEN);
2804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, "'");
2814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
2824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (k_re) {
2844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, ", '");
2854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += wpa_snprintf_hex(pos, end - pos, k_re,
2864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt					EAP_AKA_PRIME_K_RE_LEN);
2874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += os_snprintf(pos, end - pos, "'");
2884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
2894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_snprintf(pos, end - pos, ");");
2914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sqlite3_exec(data->sqlite_db, cmd, NULL, NULL, &err) != SQLITE_OK)
2934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	{
2944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_ERROR, "EAP-SIM DB: SQLite error: %s", err);
2954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_free(err);
2964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return -1;
2974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
2984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
2994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 0;
3004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
3014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int get_reauth_cb(void *ctx, int argc, char *argv[], char *col[])
3044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
3054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	struct eap_sim_db_data *data = ctx;
3064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	int i;
3074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	struct eap_sim_reauth *reauth = &data->db_tmp_reauth;
3084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	for (i = 0; i < argc; i++) {
3104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (os_strcmp(col[i], "permanent") == 0 && argv[i]) {
3114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			os_strlcpy(data->db_tmp_identity, argv[i],
3124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				   sizeof(data->db_tmp_identity));
3134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			reauth->permanent = data->db_tmp_identity;
3144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		} else if (os_strcmp(col[i], "counter") == 0 && argv[i]) {
3154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			reauth->counter = atoi(argv[i]);
3164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		} else if (os_strcmp(col[i], "mk") == 0 && argv[i]) {
3174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			hexstr2bin(argv[i], reauth->mk, sizeof(reauth->mk));
3184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		} else if (os_strcmp(col[i], "k_encr") == 0 && argv[i]) {
3194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			hexstr2bin(argv[i], reauth->k_encr,
3204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				   sizeof(reauth->k_encr));
3214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		} else if (os_strcmp(col[i], "k_aut") == 0 && argv[i]) {
3224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			hexstr2bin(argv[i], reauth->k_aut,
3234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				   sizeof(reauth->k_aut));
3244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		} else if (os_strcmp(col[i], "k_re") == 0 && argv[i]) {
3254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			hexstr2bin(argv[i], reauth->k_re,
3264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				   sizeof(reauth->k_re));
3274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		}
3284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
3294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 0;
3314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
3324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic struct eap_sim_reauth *
3354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtdb_get_reauth(struct eap_sim_db_data *data, const char *reauth_id)
3364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
3374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char cmd[256];
3384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!valid_db_string(reauth_id))
3404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
3414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_memset(&data->db_tmp_reauth, 0, sizeof(data->db_tmp_reauth));
3424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_strlcpy(data->db_tmp_pseudonym_str, reauth_id,
3434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   sizeof(data->db_tmp_pseudonym_str));
3444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	data->db_tmp_reauth.reauth_id = data->db_tmp_pseudonym_str;
3454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_snprintf(cmd, sizeof(cmd),
3464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    "SELECT * FROM reauth WHERE reauth_id='%s';", reauth_id);
3474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sqlite3_exec(data->sqlite_db, cmd, get_reauth_cb, data, NULL) !=
3484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    SQLITE_OK)
3494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
3504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->db_tmp_reauth.permanent == NULL)
3514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
3524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return &data->db_tmp_reauth;
3534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
3544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic void db_remove_reauth(struct eap_sim_db_data *data,
3574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			     struct eap_sim_reauth *reauth)
3584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
3594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char cmd[256];
3604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!valid_db_string(reauth->permanent))
3624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return;
3634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_snprintf(cmd, sizeof(cmd),
3644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    "DELETE FROM reauth WHERE permanent='%s';",
3654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    reauth->permanent);
3664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	sqlite3_exec(data->sqlite_db, cmd, NULL, NULL, NULL);
3674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
3684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
3704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct eap_sim_db_pending *
3734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidteap_sim_db_get_pending(struct eap_sim_db_data *data, const char *imsi, int aka)
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *entry, *prev = NULL;
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry = data->pending;
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (entry) {
3794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (entry->aka == aka && os_strcmp(entry->imsi, imsi) == 0) {
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (prev)
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				prev->next = entry->next;
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				data->pending = entry->next;
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = entry;
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry = entry->next;
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return entry;
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_add_pending(struct eap_sim_db_data *data,
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   struct eap_sim_db_pending *entry)
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->next = data->pending;
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->pending = entry;
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_sim_resp_auth(struct eap_sim_db_data *data,
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const char *imsi, char *buf)
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *start, *end, *pos;
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *entry;
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int num_chal;
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * SIM-RESP-AUTH <IMSI> Kc(i):SRES(i):RAND(i) ...
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * SIM-RESP-AUTH <IMSI> FAILURE
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (IMSI = ASCII string, Kc/SRES/RAND = hex string)
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	entry = eap_sim_db_get_pending(data, imsi, 0);
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry == NULL) {
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: No pending entry for the "
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received message found");
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = buf;
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strncmp(start, "FAILURE", 7) == 0) {
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: External server reported "
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failure");
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry->state = FAILURE;
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sim_db_add_pending(data, entry);
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->get_complete_cb(data->ctx, entry->cb_session_ctx);
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_chal = 0;
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (num_chal < EAP_SIM_MAX_CHAL) {
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		end = os_strchr(start, ' ');
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (end)
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*end = '\0';
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = os_strchr(start, ':');
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos == NULL)
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto parse_fail;
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos = '\0';
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hexstr2bin(start, entry->u.sim.kc[num_chal],
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       EAP_SIM_KC_LEN))
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto parse_fail;
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		start = pos + 1;
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = os_strchr(start, ':');
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos == NULL)
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto parse_fail;
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos = '\0';
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hexstr2bin(start, entry->u.sim.sres[num_chal],
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       EAP_SIM_SRES_LEN))
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto parse_fail;
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		start = pos + 1;
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hexstr2bin(start, entry->u.sim.rand[num_chal],
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       GSM_RAND_LEN))
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto parse_fail;
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_chal++;
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (end == NULL)
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			start = end + 1;
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->u.sim.num_chal = num_chal;
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->state = SUCCESS;
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Authentication data parsed "
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "successfully - callback");
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sim_db_add_pending(data, entry);
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->get_complete_cb(data->ctx, entry->cb_session_ctx);
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtparse_fail:
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string");
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(entry);
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_aka_resp_auth(struct eap_sim_db_data *data,
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const char *imsi, char *buf)
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *start, *end;
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *entry;
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES>
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * AKA-RESP-AUTH <IMSI> FAILURE
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (IMSI = ASCII string, RAND/AUTN/IK/CK/RES = hex string)
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	entry = eap_sim_db_get_pending(data, imsi, 1);
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry == NULL) {
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: No pending entry for the "
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received message found");
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = buf;
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strncmp(start, "FAILURE", 7) == 0) {
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: External server reported "
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failure");
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry->state = FAILURE;
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sim_db_add_pending(data, entry);
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->get_complete_cb(data->ctx, entry->cb_session_ctx);
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = os_strchr(start, ' ');
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end == NULL)
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*end = '\0';
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hexstr2bin(start, entry->u.aka.rand, EAP_AKA_RAND_LEN))
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = end + 1;
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = os_strchr(start, ' ');
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end == NULL)
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*end = '\0';
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hexstr2bin(start, entry->u.aka.autn, EAP_AKA_AUTN_LEN))
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = end + 1;
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = os_strchr(start, ' ');
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end == NULL)
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*end = '\0';
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hexstr2bin(start, entry->u.aka.ik, EAP_AKA_IK_LEN))
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = end + 1;
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = os_strchr(start, ' ');
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end == NULL)
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*end = '\0';
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hexstr2bin(start, entry->u.aka.ck, EAP_AKA_CK_LEN))
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = end + 1;
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = os_strchr(start, ' ');
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end)
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*end = '\0';
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		end = start;
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (*end)
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			end++;
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->u.aka.res_len = (end - start) / 2;
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry->u.aka.res_len > EAP_AKA_RES_MAX_LEN) {
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Too long RES");
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entry->u.aka.res_len = 0;
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hexstr2bin(start, entry->u.aka.res, entry->u.aka.res_len))
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->state = SUCCESS;
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Authentication data parsed "
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "successfully - callback");
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sim_db_add_pending(data, entry);
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->get_complete_cb(data->ctx, entry->cb_session_ctx);
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtparse_fail:
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string");
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(entry);
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_receive(int sock, void *eloop_ctx, void *sock_ctx)
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_data *data = eloop_ctx;
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[1000], *pos, *cmd, *imsi;
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = recv(sock, buf, sizeof(buf), 0);
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0)
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-SIM DB: Received from an "
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      "external source", (u8 *) buf, res);
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res == 0)
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res >= (int) sizeof(buf))
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = sizeof(buf) - 1;
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf[res] = '\0';
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->get_complete_cb == NULL) {
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: No get_complete_cb "
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "registered");
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* <cmd> <IMSI> ... */
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmd = buf;
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = os_strchr(cmd, ' ');
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos == NULL)
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos = '\0';
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	imsi = pos + 1;
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = os_strchr(imsi, ' ');
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos == NULL)
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto parse_fail;
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos = '\0';
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: External response=%s for IMSI %s",
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   cmd, imsi);
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strcmp(cmd, "SIM-RESP-AUTH") == 0)
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sim_db_sim_resp_auth(data, imsi, pos + 1);
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (os_strcmp(cmd, "AKA-RESP-AUTH") == 0)
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sim_db_aka_resp_auth(data, imsi, pos + 1);
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-SIM DB: Unknown external response "
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "'%s'", cmd);
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtparse_fail:
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string");
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sim_db_open_socket(struct eap_sim_db_data *data)
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sockaddr_un addr;
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	static int counter = 0;
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strncmp(data->fname, "unix:", 5) != 0)
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->sock = socket(PF_UNIX, SOCK_DGRAM, 0);
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->sock < 0) {
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		perror("socket(eap_sim_db)");
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&addr, 0, sizeof(addr));
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr.sun_family = AF_UNIX;
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(addr.sun_path, sizeof(addr.sun_path),
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    "/tmp/eap_sim_db_%d-%d", getpid(), counter++);
64161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_free(data->local_sock);
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->local_sock = os_strdup(addr.sun_path);
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bind(data->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		perror("bind(eap_sim_db)");
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(data->sock);
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->sock = -1;
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&addr, 0, sizeof(addr));
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	addr.sun_family = AF_UNIX;
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(addr.sun_path, data->fname + 5, sizeof(addr.sun_path));
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (connect(data->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		perror("connect(eap_sim_db)");
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_ascii(MSG_INFO, "HLR/AuC GW socket",
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  (u8 *) addr.sun_path,
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  os_strlen(addr.sun_path));
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(data->sock);
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->sock = -1;
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_read_sock(data->sock, eap_sim_db_receive, data, NULL);
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_close_socket(struct eap_sim_db_data *data)
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->sock >= 0) {
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_unregister_read_sock(data->sock);
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(data->sock);
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->sock = -1;
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->local_sock) {
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		unlink(data->local_sock);
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(data->local_sock);
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->local_sock = NULL;
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_init - Initialize EAP-SIM DB / authentication gateway interface
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Configuration data (e.g., file name)
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @get_complete_cb: Callback function for reporting availability of triplets
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ctx: Context pointer for get_complete_cb
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to a private data structure or %NULL on failure
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
6914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstruct eap_sim_db_data *
6924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidteap_sim_db_init(const char *config,
6934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		void (*get_complete_cb)(void *ctx, void *session_ctx),
6944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		void *ctx)
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_data *data;
6974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *pos;
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data = os_zalloc(sizeof(*data));
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data == NULL)
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->sock = -1;
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->get_complete_cb = get_complete_cb;
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->ctx = ctx;
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->fname = os_strdup(config);
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->fname == NULL)
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
7094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	pos = os_strstr(data->fname, " db=");
7104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (pos) {
7114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		*pos = '\0';
7124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
7134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		pos += 4;
7144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		data->sqlite_db = db_open(pos);
7154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (data->sqlite_db == NULL)
7164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			goto fail;
7174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
7184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strncmp(data->fname, "unix:", 5) == 0) {
72161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (eap_sim_db_open_socket(data)) {
72261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-SIM DB: External database "
72361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   "connection not available - will retry "
72461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   "later");
72561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return data;
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail:
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sim_db_close_socket(data);
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(data->fname);
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(data);
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_free_pseudonym(struct eap_sim_pseudonym *p)
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_free(p->permanent);
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p->pseudonym);
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(p);
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_free_reauth(struct eap_sim_reauth *r)
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_free(r->permanent);
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(r->reauth_id);
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(r);
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_deinit - Deinitialize EAP-SIM DB/authentication gw interface
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Private data pointer from eap_sim_db_init()
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_sim_db_deinit(void *priv)
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_data *data = priv;
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_pseudonym *p, *prev;
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_reauth *r, *prevr;
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *pending, *prev_pending;
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
7664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->sqlite_db) {
7674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		sqlite3_close(data->sqlite_db);
7684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		data->sqlite_db = NULL;
7694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
7704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
7714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sim_db_close_socket(data);
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(data->fname);
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p = data->pseudonyms;
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (p) {
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = p;
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p = p->next;
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sim_db_free_pseudonym(prev);
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	r = data->reauths;
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (r) {
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prevr = r;
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r = r->next;
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sim_db_free_reauth(prevr);
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pending = data->pending;
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pending) {
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev_pending = pending;
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pending = pending->next;
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(prev_pending);
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(data);
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sim_db_send(struct eap_sim_db_data *data, const char *msg,
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   size_t len)
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int _errno = 0;
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (send(data->sock, msg, len, 0) < 0) {
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		_errno = errno;
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		perror("send[EAP-SIM DB UNIX]");
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL ||
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    _errno == ECONNREFUSED) {
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Try to reconnect */
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_sim_db_close_socket(data);
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_sim_db_open_socket(data) < 0)
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Reconnected to the "
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "external server");
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (send(data->sock, msg, len, 0) < 0) {
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			perror("send[EAP-SIM DB UNIX]");
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_db_expire_pending(struct eap_sim_db_data *data)
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: add limit for maximum length for pending list; remove latest
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (i.e., last) entry from the list if the limit is reached; could also
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * use timeout to expire pending entries */
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_gsm_triplets - Get GSM triplets
8384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
8394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @username: Permanent username (prefix | IMSI)
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @max_chal: Maximum number of triplets
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @_rand: Buffer for RAND values
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @kc: Buffer for Kc values
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sres: Buffer for SRES values
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cb_session_ctx: Session callback context for get_complete_cb()
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of triplets received (has to be less than or equal to
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * max_chal), -1 (EAP_SIM_DB_FAILURE) on error (e.g., user not found), or
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * -2 (EAP_SIM_DB_PENDING) if results are not yet available. In this case, the
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * callback function registered with eap_sim_db_init() will be called once the
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * results become available.
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * When using an external server for GSM triplets, this function can always
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * start a request and return EAP_SIM_DB_PENDING immediately if authentication
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * triplets are not available. Once the triplets are received, callback
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * function registered with eap_sim_db_init() is called to notify EAP state
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * machine to reprocess the message. This eap_sim_db_get_gsm_triplets()
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * function will then be called again and the newly received triplets will then
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * be given to the caller.
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
8594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint eap_sim_db_get_gsm_triplets(struct eap_sim_db_data *data,
8604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				const char *username, int max_chal,
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				u8 *_rand, u8 *kc, u8 *sres,
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				void *cb_session_ctx)
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *entry;
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len, ret;
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char msg[40];
8674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	const char *imsi;
8684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	size_t imsi_len;
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (username == NULL || username[0] != EAP_SIM_PERMANENT_PREFIX ||
8714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    username[1] == '\0' || os_strlen(username) > sizeof(entry->imsi)) {
8724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: unexpected username '%s'",
8734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   username);
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	imsi = username + 1;
8774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Get GSM triplets for IMSI '%s'",
8784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   imsi);
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	entry = eap_sim_db_get_pending(data, imsi, 0);
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry) {
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int num_chal;
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (entry->state == FAILURE) {
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> "
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "failure");
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(entry);
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EAP_SIM_DB_FAILURE;
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (entry->state == PENDING) {
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> "
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "still pending");
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_sim_db_add_pending(data, entry);
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EAP_SIM_DB_PENDING;
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> "
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "%d challenges", entry->u.sim.num_chal);
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num_chal = entry->u.sim.num_chal;
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (num_chal > max_chal)
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			num_chal = max_chal;
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(_rand, entry->u.sim.rand, num_chal * GSM_RAND_LEN);
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(sres, entry->u.sim.sres,
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  num_chal * EAP_SIM_SRES_LEN);
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(kc, entry->u.sim.kc, num_chal * EAP_SIM_KC_LEN);
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(entry);
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return num_chal;
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->sock < 0) {
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_sim_db_open_socket(data) < 0)
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EAP_SIM_DB_FAILURE;
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	imsi_len = os_strlen(imsi);
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = os_snprintf(msg, sizeof(msg), "SIM-REQ-AUTH ");
9174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (len < 0 || len + imsi_len >= sizeof(msg))
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
9194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_memcpy(msg + len, imsi, imsi_len);
9204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	len += imsi_len;
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = os_snprintf(msg + len, sizeof(msg) - len, " %d", max_chal);
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret < 0 || (size_t) ret >= sizeof(msg) - len)
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len += ret;
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: requesting SIM authentication "
9274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   "data for IMSI '%s'", imsi);
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_sim_db_send(data, msg, len) < 0)
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry = os_zalloc(sizeof(*entry));
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry == NULL)
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&entry->timestamp);
9364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_strlcpy(entry->imsi, imsi, sizeof(entry->imsi));
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->cb_session_ctx = cb_session_ctx;
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->state = PENDING;
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sim_db_add_pending(data, entry);
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sim_db_expire_pending(data);
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return EAP_SIM_DB_PENDING;
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * eap_sim_db_get_next(struct eap_sim_db_data *data, char prefix)
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *id, *pos, *end;
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 buf[10];
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (random_get_bytes(buf, sizeof(buf)))
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	id = os_malloc(sizeof(buf) * 2 + 2);
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (id == NULL)
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = id;
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = id + sizeof(buf) * 2 + 2;
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = prefix;
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += wpa_snprintf_hex(pos, end - pos, buf, sizeof(buf));
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return id;
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_next_pseudonym - EAP-SIM DB: Get next pseudonym
9684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
96904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * @method: EAP method (SIM/AKA/AKA')
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Next pseudonym (allocated string) or %NULL on failure
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to generate a pseudonym for EAP-SIM. The returned
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pseudonym is not added to database at this point; it will need to be added
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * with eap_sim_db_add_pseudonym() once the authentication has been completed
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * successfully. Caller is responsible for freeing the returned buffer.
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
9774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtchar * eap_sim_db_get_next_pseudonym(struct eap_sim_db_data *data,
9784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				     enum eap_sim_db_method method)
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
98004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	char prefix = EAP_SIM_REAUTH_ID_PREFIX;
98104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
98204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	switch (method) {
98304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SIM_DB_SIM:
98404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		prefix = EAP_SIM_PSEUDONYM_PREFIX;
98504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
98604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SIM_DB_AKA:
98704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		prefix = EAP_AKA_PSEUDONYM_PREFIX;
98804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
98904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SIM_DB_AKA_PRIME:
99004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		prefix = EAP_AKA_PRIME_PSEUDONYM_PREFIX;
99104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
99204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
99304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
99404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return eap_sim_db_get_next(data, prefix);
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_next_reauth_id - EAP-SIM DB: Get next reauth_id
10004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
100104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * @method: EAP method (SIM/AKA/AKA')
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Next reauth_id (allocated string) or %NULL on failure
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to generate a fast re-authentication identity for
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-SIM. The returned reauth_id is not added to database at this point; it
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * will need to be added with eap_sim_db_add_reauth() once the authentication
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * has been completed successfully. Caller is responsible for freeing the
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * returned buffer.
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
10104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtchar * eap_sim_db_get_next_reauth_id(struct eap_sim_db_data *data,
10114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				     enum eap_sim_db_method method)
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
101304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	char prefix = EAP_SIM_REAUTH_ID_PREFIX;
101404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
101504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	switch (method) {
101604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SIM_DB_SIM:
101704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		prefix = EAP_SIM_REAUTH_ID_PREFIX;
101804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
101904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SIM_DB_AKA:
102004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		prefix = EAP_AKA_REAUTH_ID_PREFIX;
102104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
102204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EAP_SIM_DB_AKA_PRIME:
102304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		prefix = EAP_AKA_PRIME_REAUTH_ID_PREFIX;
102404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
102504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
102604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
102704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return eap_sim_db_get_next(data, prefix);
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_add_pseudonym - EAP-SIM DB: Add new pseudonym
10334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
10344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @permanent: Permanent username
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pseudonym: Pseudonym for this user. This needs to be an allocated buffer,
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * e.g., return value from eap_sim_db_get_next_pseudonym(). Caller must not
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * free it.
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function adds a new pseudonym for EAP-SIM user. EAP-SIM DB is
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * responsible of freeing pseudonym buffer once it is not needed anymore.
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
10434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint eap_sim_db_add_pseudonym(struct eap_sim_db_data *data,
10444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			     const char *permanent, char *pseudonym)
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_pseudonym *p;
10474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Add pseudonym '%s' for permanent "
10484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   "username '%s'", pseudonym, permanent);
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: could store last two pseudonyms */
10514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
10524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->sqlite_db)
10534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return db_add_pseudonym(data, permanent, pseudonym);
10544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
10554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	for (p = data->pseudonyms; p; p = p->next) {
10564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (os_strcmp(permanent, p->permanent) == 0)
10574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			break;
10584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p) {
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Replacing previous "
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "pseudonym: %s", p->pseudonym);
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p->pseudonym);
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p->pseudonym = pseudonym;
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p = os_zalloc(sizeof(*p));
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p == NULL) {
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(pseudonym);
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p->next = data->pseudonyms;
10744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	p->permanent = os_strdup(permanent);
10754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (p->permanent == NULL) {
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(p);
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(pseudonym);
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p->pseudonym = pseudonym;
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->pseudonyms = p;
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Added new pseudonym entry");
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct eap_sim_reauth *
10894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidteap_sim_db_add_reauth_data(struct eap_sim_db_data *data,
10904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   const char *permanent,
10914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   char *reauth_id, u16 counter)
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_reauth *r;
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	for (r = data->reauths; r; r = r->next) {
10964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (os_strcmp(r->permanent, permanent) == 0)
10974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			break;
10984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (r) {
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Replacing previous "
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "reauth_id: %s", r->reauth_id);
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(r->reauth_id);
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r->reauth_id = reauth_id;
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r = os_zalloc(sizeof(*r));
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (r == NULL) {
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(reauth_id);
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r->next = data->reauths;
11134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		r->permanent = os_strdup(permanent);
11144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (r->permanent == NULL) {
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(r);
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(reauth_id);
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r->reauth_id = reauth_id;
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->reauths = r;
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Added new reauth entry");
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	r->counter = counter;
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return r;
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_add_reauth - EAP-SIM DB: Add new re-authentication entry
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Private data pointer from eap_sim_db_init()
11334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @permanent: Permanent username
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @identity_len: Length of identity
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @reauth_id: reauth_id for this user. This needs to be an allocated buffer,
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * e.g., return value from eap_sim_db_get_next_reauth_id(). Caller must not
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * free it.
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @counter: AT_COUNTER value for fast re-authentication
11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mk: 16-byte MK from the previous full authentication or %NULL
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function adds a new re-authentication entry for an EAP-SIM user.
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-SIM DB is responsible of freeing reauth_id buffer once it is not needed
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * anymore.
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
11464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint eap_sim_db_add_reauth(struct eap_sim_db_data *data, const char *permanent,
11474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			  char *reauth_id, u16 counter, const u8 *mk)
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_reauth *r;
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Add reauth_id '%s' for permanent "
11524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   "identity '%s'", reauth_id, permanent);
11534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
11544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
11554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->sqlite_db)
11564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return db_add_reauth(data, permanent, reauth_id, counter, mk,
11574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				     NULL, NULL, NULL);
11584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
11594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	r = eap_sim_db_add_reauth_data(data, permanent, reauth_id, counter);
11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (r == NULL)
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(r->mk, mk, EAP_SIM_MK_LEN);
11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_AKA_PRIME
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_add_reauth_prime - EAP-AKA' DB: Add new re-authentication entry
11724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
11734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @permanent: Permanent username
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @reauth_id: reauth_id for this user. This needs to be an allocated buffer,
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * e.g., return value from eap_sim_db_get_next_reauth_id(). Caller must not
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * free it.
11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @counter: AT_COUNTER value for fast re-authentication
11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @k_encr: K_encr from the previous full authentication
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @k_aut: K_aut from the previous full authentication
11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @k_re: 32-byte K_re from the previous full authentication
11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function adds a new re-authentication entry for an EAP-AKA' user.
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-SIM DB is responsible of freeing reauth_id buffer once it is not needed
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * anymore.
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
11874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint eap_sim_db_add_reauth_prime(struct eap_sim_db_data *data,
11884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				const char *permanent, char *reauth_id,
11894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				u16 counter, const u8 *k_encr,
11904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				const u8 *k_aut, const u8 *k_re)
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_reauth *r;
11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Add reauth_id '%s' for permanent "
11954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   "identity '%s'", reauth_id, permanent);
11964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
11974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
11984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->sqlite_db)
11994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return db_add_reauth(data, permanent, reauth_id, counter, NULL,
12004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				     k_encr, k_aut, k_re);
12014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
12024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	r = eap_sim_db_add_reauth_data(data, permanent, reauth_id, counter);
12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (r == NULL)
12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(r->k_encr, k_encr, EAP_SIM_K_ENCR_LEN);
12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(r->k_aut, k_aut, EAP_AKA_PRIME_K_AUT_LEN);
12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(r->k_re, k_re, EAP_AKA_PRIME_K_RE_LEN);
12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_AKA_PRIME */
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_permanent - EAP-SIM DB: Get permanent identity
12174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
12184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @pseudonym: Pseudonym username
12194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * Returns: Pointer to permanent username or %NULL if not found
12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
12214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtconst char *
12224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidteap_sim_db_get_permanent(struct eap_sim_db_data *data, const char *pseudonym)
12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_pseudonym *p;
12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
12274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->sqlite_db)
12284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return db_get_pseudonym(data, pseudonym);
12294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	p = data->pseudonyms;
12324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	while (p) {
12334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (os_strcmp(p->pseudonym, pseudonym) == 0)
12344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			return p->permanent;
12354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		p = p->next;
12364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return NULL;
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_reauth_entry - EAP-SIM DB: Get re-authentication entry
12444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
12454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @reauth_id: Fast re-authentication username
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the re-auth entry, or %NULL if not found
12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_sim_reauth *
12494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidteap_sim_db_get_reauth_entry(struct eap_sim_db_data *data,
12504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			    const char *reauth_id)
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_reauth *r;
12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
12554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->sqlite_db)
12564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return db_get_reauth(data, reauth_id);
12574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
12584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
12594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	r = data->reauths;
12604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	while (r) {
12614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (os_strcmp(r->reauth_id, reauth_id) == 0)
12624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			break;
12634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		r = r->next;
12644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
12654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return r;
12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_remove_reauth - EAP-SIM DB: Remove re-authentication entry
12724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @reauth: Pointer to re-authentication entry from
12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_reauth_entry()
12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
12764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtvoid eap_sim_db_remove_reauth(struct eap_sim_db_data *data,
12774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			      struct eap_sim_reauth *reauth)
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_reauth *r, *prev = NULL;
12804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifdef CONFIG_SQLITE
12814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (data->sqlite_db) {
12824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		db_remove_reauth(data, reauth);
12834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return;
12844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
12854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_SQLITE */
12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	r = data->reauths;
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (r) {
12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (r == reauth) {
12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (prev)
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				prev->next = r->next;
12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				data->reauths = r->next;
12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_sim_db_free_reauth(r);
12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = r;
12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		r = r->next;
12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_aka_auth - Get AKA authentication values
13044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
13054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @username: Permanent username (prefix | IMSI)
13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @_rand: Buffer for RAND value
13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @autn: Buffer for AUTN value
13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ik: Buffer for IK value
13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ck: Buffer for CK value
13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @res: Buffer for RES value
13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @res_len: Buffer for RES length
13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cb_session_ctx: Session callback context for get_complete_cb()
13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 (EAP_SIM_DB_FAILURE) on error (e.g., user not
13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * found), or -2 (EAP_SIM_DB_PENDING) if results are not yet available. In this
13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * case, the callback function registered with eap_sim_db_init() will be
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * called once the results become available.
13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * When using an external server for AKA authentication, this function can
13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * always start a request and return EAP_SIM_DB_PENDING immediately if
13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * authentication triplets are not available. Once the authentication data are
13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * received, callback function registered with eap_sim_db_init() is called to
13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * notify EAP state machine to reprocess the message. This
13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_aka_auth() function will then be called again and the newly
13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * received triplets will then be given to the caller.
13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
13264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint eap_sim_db_get_aka_auth(struct eap_sim_db_data *data, const char *username,
13274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			    u8 *_rand, u8 *autn, u8 *ik, u8 *ck,
13284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			    u8 *res, size_t *res_len, void *cb_session_ctx)
13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_sim_db_pending *entry;
13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len;
13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char msg[40];
13334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	const char *imsi;
13344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	size_t imsi_len;
13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (username == NULL ||
13374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    (username[0] != EAP_AKA_PERMANENT_PREFIX &&
13384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	     username[0] != EAP_AKA_PRIME_PERMANENT_PREFIX) ||
13394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    username[1] == '\0' || os_strlen(username) > sizeof(entry->imsi)) {
13404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: unexpected username '%s'",
13414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   username);
13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	imsi = username + 1;
13454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Get AKA auth for IMSI '%s'",
13464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   imsi);
13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	entry = eap_sim_db_get_pending(data, imsi, 1);
13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry) {
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (entry->state == FAILURE) {
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(entry);
13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failure");
13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EAP_SIM_DB_FAILURE;
13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (entry->state == PENDING) {
13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap_sim_db_add_pending(data, entry);
13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending");
13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EAP_SIM_DB_PENDING;
13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: Returning successfully "
13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received authentication data");
13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(_rand, entry->u.aka.rand, EAP_AKA_RAND_LEN);
13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(autn, entry->u.aka.autn, EAP_AKA_AUTN_LEN);
13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(ik, entry->u.aka.ik, EAP_AKA_IK_LEN);
13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(ck, entry->u.aka.ck, EAP_AKA_CK_LEN);
13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(res, entry->u.aka.res, EAP_AKA_RES_MAX_LEN);
13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*res_len = entry->u.aka.res_len;
13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(entry);
13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->sock < 0) {
13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_sim_db_open_socket(data) < 0)
13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EAP_SIM_DB_FAILURE;
13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	imsi_len = os_strlen(imsi);
13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = os_snprintf(msg, sizeof(msg), "AKA-REQ-AUTH ");
13814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (len < 0 || len + imsi_len >= sizeof(msg))
13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
13834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_memcpy(msg + len, imsi, imsi_len);
13844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	len += imsi_len;
13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: requesting AKA authentication "
13874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		    "data for IMSI '%s'", imsi);
13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_sim_db_send(data, msg, len) < 0)
13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry = os_zalloc(sizeof(*entry));
13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entry == NULL)
13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EAP_SIM_DB_FAILURE;
13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&entry->timestamp);
13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->aka = 1;
13974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_strlcpy(entry->imsi, imsi, sizeof(entry->imsi));
13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->cb_session_ctx = cb_session_ctx;
13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entry->state = PENDING;
14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sim_db_add_pending(data, entry);
14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_sim_db_expire_pending(data);
14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return EAP_SIM_DB_PENDING;
14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_resynchronize - Resynchronize AKA AUTN
14094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @data: Private data pointer from eap_sim_db_init()
14104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @username: Permanent username
14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @auts: AUTS value from the peer
14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @_rand: RAND value used in the rejected message
14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called when the peer reports synchronization failure in the
14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AUTN value by sending AUTS. The AUTS and RAND values should be sent to
14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * HLR/AuC to allow it to resynchronize with the peer. After this,
14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db_get_aka_auth() will be called again to to fetch updated
14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RAND/AUTN values for the next challenge.
14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
14214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint eap_sim_db_resynchronize(struct eap_sim_db_data *data,
14224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			     const char *username,
14234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			     const u8 *auts, const u8 *_rand)
14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	const char *imsi;
14264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	size_t imsi_len;
14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (username == NULL ||
14294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    (username[0] != EAP_AKA_PERMANENT_PREFIX &&
14304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	     username[0] != EAP_AKA_PRIME_PERMANENT_PREFIX) ||
14314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	    username[1] == '\0' || os_strlen(username) > 20) {
14324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: unexpected username '%s'",
14334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   username);
14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	imsi = username + 1;
14374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_printf(MSG_DEBUG, "EAP-SIM DB: Get AKA auth for IMSI '%s'",
14384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		   imsi);
14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->sock >= 0) {
14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char msg[100];
14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int len, ret;
14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		imsi_len = os_strlen(imsi);
14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = os_snprintf(msg, sizeof(msg), "AKA-AUTS ");
14464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (len < 0 || len + imsi_len >= sizeof(msg))
14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
14484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		os_memcpy(msg + len, imsi, imsi_len);
14494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		len += imsi_len;
14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(msg + len, sizeof(msg) - len, " ");
14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || (size_t) ret >= sizeof(msg) - len)
14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len += ret;
14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len += wpa_snprintf_hex(msg + len, sizeof(msg) - len,
14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					auts, EAP_AKA_AUTS_LEN);
14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = os_snprintf(msg + len, sizeof(msg) - len, " ");
14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ret < 0 || (size_t) ret >= sizeof(msg) - len)
14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len += ret;
14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len += wpa_snprintf_hex(msg + len, sizeof(msg) - len,
14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					_rand, EAP_AKA_RAND_LEN);
14634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-SIM DB: reporting AKA AUTS for "
14644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			   "IMSI '%s'", imsi);
14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_sim_db_send(data, msg, len) < 0)
14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
14724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
14734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt/**
14744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * sim_get_username - Extract username from SIM identity
14754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @identity: Identity
14764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * @identity_len: Identity length
14774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * Returns: Allocated buffer with the username part of the identity
14784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt *
14794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * Caller is responsible for freeing the returned buffer with os_free().
14804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt */
14814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtchar * sim_get_username(const u8 *identity, size_t identity_len)
14824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
14834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *username;
14844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	size_t pos;
14854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
14864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (identity == NULL)
14874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
14884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
14894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	for (pos = 0; pos < identity_len; pos++) {
14904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (identity[pos] == '@' || identity[pos] == '\0')
14914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			break;
14924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
14934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
14944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	username = os_malloc(pos + 1);
14954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (username == NULL)
14964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return NULL;
14974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	os_memcpy(username, identity, pos);
14984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	username[pos] = '\0';
14994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
15004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return username;
15014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
1502