@@ -3027,6 +3027,7 @@ void wpa_config_free(struct wpa_config *config)
{
struct wpa_ssid *ssid, *prev = NULL;
struct wpa_cred *cred, *cprev;
+ struct wpa_dev_ik *identity, *iprev;
int i;
ssid = config->ssid;
@@ -3043,6 +3044,13 @@ void wpa_config_free(struct wpa_config *config)
wpa_config_free_cred(cprev);
}
+ identity = config->identity;
+ while (identity) {
+ iprev = identity;
+ identity = identity->next;
+ wpa_config_free_identity(iprev);
+ }
+
wpa_config_flush_blobs(config);
wpabuf_free(config->wps_vendor_ext_m1);
@@ -4105,6 +4113,60 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
return -1;
}
+int wpa_config_set_identity(struct wpa_dev_ik *identity, const char *var,
+ const char *value, int line)
+{
+ char *val;
+ size_t len;
+
+ if (os_strcmp(var, "dik_cipher") == 0) {
+ identity->dik_cipher = atoi(value);
+ return 0;
+ }
+
+ if (os_strcmp(var, "dik_len") == 0) {
+ identity->dik_len = atoi(value);
+ return 0;
+ }
+
+ val = wpa_config_parse_string(value, &len);
+ if (val == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid field '%s' string "
+ "value '%s'.", line, var, value);
+ return -1;
+ }
+
+ if (os_strcmp(var, "dik_data") == 0) {
+ os_free(identity->dik_data);
+ identity->dik_data = val;
+ return 0;
+ }
+
+ if (os_strcmp(var, "pmk_len") == 0) {
+ identity->pmk_len = atoi(value);
+ return 0;
+ }
+
+ if (os_strcmp(var, "pmk") == 0) {
+ os_free(identity->pmk);
+ identity->pmk = val;
+ return 0;
+ }
+ if (os_strcmp(var, "pmkid") == 0) {
+ os_free(identity->pmkid);
+ identity->pmkid = val;
+ return 0;
+ }
+
+ if (line) {
+ wpa_printf(MSG_ERROR, "Line %d: unknown identity field '%s'.",
+ line, var);
+ }
+
+ os_free(val);
+
+ return -1;
+}
static char * alloc_int_str(int val)
{
@@ -5763,3 +5825,73 @@ int wpa_config_process_global(struct wpa_config *config, char *pos, int line)
return ret;
}
+
+void wpa_config_free_identity(struct wpa_dev_ik *identity)
+{
+ os_free(identity->dik_data);
+ os_free(identity->pmk);
+ os_free(identity->pmkid);
+ os_free(identity);
+}
+
+/**
+ * wpa_config_add_identity - Add a new device identity with empty configuration
+ * @config: Configuration data from wpa_config_read()
+ * Returns: The new device identity or %NULL if operation failed
+ */
+struct wpa_dev_ik * wpa_config_add_identity(struct wpa_config *config)
+{
+ int id;
+ struct wpa_dev_ik *identity, *last = NULL;
+
+ id = -1;
+ identity = config->identity;
+ while (identity) {
+ if (identity->id > id)
+ id = identity->id;
+ last = identity;
+ identity = identity->next;
+ }
+ id++;
+
+ identity = os_zalloc(sizeof(*identity));
+ if (identity == NULL)
+ return NULL;
+ identity->id = id;
+ if (last)
+ last->next = identity;
+ else
+ config->identity = identity;
+
+ return identity;
+}
+
+/**
+ * wpa_config_remove_identity - Remove a configured identity based on id
+ * @config: Configuration data from wpa_config_read()
+ * @id: Unique network id to search for
+ * Returns: 0 on success, or -1 if the network was not found
+ */
+int wpa_config_remove_identity(struct wpa_config *config, int id)
+{
+ struct wpa_dev_ik *identity, *prev = NULL;
+
+ identity = config->identity;
+ while (identity) {
+ if (id == identity->id)
+ break;
+ prev = identity;
+ identity = identity->next;
+ }
+
+ if (identity == NULL)
+ return -1;
+
+ if (prev)
+ prev->next = identity->next;
+ else
+ config->identity = identity->next;
+
+ wpa_config_free_identity(identity);
+ return 0;
+}
@@ -417,6 +417,57 @@ struct wpa_cred {
int sim_num;
};
+struct wpa_dev_ik {
+ /**
+ * next - Next device Identity in the list
+ *
+ * This pointer can be used to iterate over all device Indetity keys.
+ * The head of this list is stored in the dev_ik field of struct
+ * wpa_config.
+ */
+ struct wpa_dev_ik *next;
+
+ /**
+ * id - Unique id for the credential
+ *
+ * This identifier is used as a unique identifier for each identity
+ * block when using the control interface. Each identity is allocated
+ * an id when it is being created, either when reading the
+ * configuration file or when a new identity is added through the
+ * control interface.
+ */
+ int id;
+
+ /**
+ * dik_cipher - Device Identity key cipher version
+ */
+ int dik_cipher;
+
+ /**
+ * dik_len - Device Identity key length
+ */
+ int dik_len;
+
+ /**
+ * dik_data - Device Identity key which is unique for the device
+ */
+ char *dik_data;
+
+ /**
+ * pmk_len - PMK length
+ */
+ int pmk_len;
+
+ /**
+ * pmk - pmk associated of previous connection with the given device
+ */
+ char *pmk;
+
+ /**
+ * pmkid - pmkid of previous connection with the given device
+ */
+ char *pmkid;
+};
#define CFG_CHANGED_DEVICE_NAME BIT(0)
#define CFG_CHANGED_CONFIG_METHODS BIT(1)
@@ -1823,6 +1874,12 @@ struct wpa_config {
/* length of DevIK */
size_t dik_len;
+ /**
+ * identity - Head of the list of peer device identities
+ *
+ * This is the head for the list of all the paired devices.
+ */
+ struct wpa_dev_ik *identity;
};
@@ -1867,6 +1924,8 @@ int wpa_config_remove_cred(struct wpa_config *config, int id);
void wpa_config_free_cred(struct wpa_cred *cred);
int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
const char *value, int line);
+int wpa_config_set_identity(struct wpa_dev_ik *identity, const char *var,
+ const char *value, int line);
char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var);
struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
@@ -1919,5 +1978,8 @@ struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp,
* Each configuration backend needs to implement this function.
*/
int wpa_config_write(const char *name, struct wpa_config *config);
+void wpa_config_free_identity(struct wpa_dev_ik *identity);
+struct wpa_dev_ik * wpa_config_add_identity(struct wpa_config *config);
+int wpa_config_remove_identity(struct wpa_config *config, int id);
#endif /* CONFIG_H */
@@ -296,6 +296,60 @@ static int wpa_config_process_blob(struct wpa_config *config, FILE *f,
#endif /* CONFIG_NO_CONFIG_BLOBS */
+static struct wpa_dev_ik * wpa_config_read_identity(FILE *f, int *line, int id)
+{
+ struct wpa_dev_ik *identity;
+ int errors = 0, end = 0;
+ char buf[256], *pos, *pos2;
+
+ wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new identity block", *line);
+ identity = os_zalloc(sizeof(*identity));
+ if (identity == NULL)
+ return NULL;
+ identity->id = id;
+
+ while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) {
+ if (os_strcmp(pos, "}") == 0) {
+ end = 1;
+ break;
+ }
+
+ pos2 = os_strchr(pos, '=');
+ if (pos2 == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid identity line "
+ "'%s'.", *line, pos);
+ errors++;
+ continue;
+ }
+
+ *pos2++ = '\0';
+ if (*pos2 == '"') {
+ if (os_strchr(pos2 + 1, '"') == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid "
+ "quotation '%s'.", *line, pos2);
+ errors++;
+ continue;
+ }
+ }
+
+ if (wpa_config_set_identity(identity, pos, pos2, *line) < 0)
+ errors++;
+ }
+
+ if (!end) {
+ wpa_printf(MSG_ERROR, "Line %d: identity block was not "
+ "terminated properly.", *line);
+ errors++;
+ }
+
+ if (errors) {
+ wpa_config_free_identity(identity);
+ identity = NULL;
+ }
+
+ return identity;
+}
+
struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp,
bool ro)
{
@@ -304,9 +358,11 @@ struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp,
int errors = 0, line = 0;
struct wpa_ssid *ssid, *tail, *head;
struct wpa_cred *cred, *cred_tail, *cred_head;
+ struct wpa_dev_ik *identity, *identity_tail, *identity_head;
struct wpa_config *config;
static int id = 0;
static int cred_id = 0;
+ static int identity_id = 0;
if (name == NULL)
return NULL;
@@ -325,6 +381,9 @@ struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp,
cred_tail = cred_head = config->cred;
while (cred_tail && cred_tail->next)
cred_tail = cred_tail->next;
+ identity_tail = identity_head = config->identity;
+ while (identity_tail && identity_tail->next)
+ identity_tail = identity_tail->next;
wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name);
f = fopen(name, "r");
@@ -383,6 +442,20 @@ struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp,
continue;
}
#endif /* CONFIG_NO_CONFIG_BLOBS */
+ } else if (os_strcmp(pos, "identity={") == 0) {
+ identity = wpa_config_read_identity(f, &line, identity_id++);
+ if (identity == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: failed to "
+ "parse identity block.", line);
+ errors++;
+ continue;
+ }
+ if (identity_head == NULL) {
+ identity_head = identity_tail = identity;
+ } else {
+ identity_tail->next = identity;
+ identity_tail = identity;
+ }
} else if (wpa_config_process_global(config, pos, line) < 0) {
wpa_printf(MSG_ERROR, "Line %d: Invalid configuration "
"line '%s'.", line, pos);
@@ -396,6 +469,7 @@ struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp,
config->ssid = head;
wpa_config_debug_dump_networks(config);
config->cred = cred_head;
+ config->identity = identity_head;
#ifndef WPA_IGNORE_CONFIG_ERRORS
if (errors) {
@@ -1075,6 +1149,21 @@ static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred)
cred->imsi_privacy_attr);
}
+static void wpa_config_write_identity(FILE *f, struct wpa_dev_ik *dev_ik)
+{
+ fprintf(f, "\tdik_cipher=%d\n", dev_ik->dik_cipher);
+
+ fprintf(f, "\tdik_len=%d\n", dev_ik->dik_len);
+ if (dev_ik->dik_data)
+ fprintf(f, "\tdik_data=\"%s\"\n", dev_ik->dik_data);
+
+ fprintf(f, "\tpmk_len=%d\n", dev_ik->pmk_len);
+ if (dev_ik->pmk)
+ fprintf(f, "\tpmk=\"%s\"\n", dev_ik->pmk);
+
+ if (dev_ik->pmkid)
+ fprintf(f, "\tpmkid=\"%s\"\n", dev_ik->pmkid);
+}
#ifndef CONFIG_NO_CONFIG_BLOBS
static int wpa_config_write_blob(FILE *f, struct wpa_config_blob *blob)
@@ -1646,6 +1735,7 @@ int wpa_config_write(const char *name, struct wpa_config *config)
FILE *f;
struct wpa_ssid *ssid;
struct wpa_cred *cred;
+ struct wpa_dev_ik *dev_ik;
#ifndef CONFIG_NO_CONFIG_BLOBS
struct wpa_config_blob *blob;
#endif /* CONFIG_NO_CONFIG_BLOBS */
@@ -1700,6 +1790,12 @@ int wpa_config_write(const char *name, struct wpa_config *config)
fprintf(f, "}\n");
}
+ for (dev_ik = config->identity; dev_ik; dev_ik = dev_ik->next) {
+ fprintf(f, "\nidentity={\n");
+ wpa_config_write_identity(f, dev_ik);
+ fprintf(f, "}\n");
+ }
+
#ifndef CONFIG_NO_CONFIG_BLOBS
for (blob = config->blobs; blob; blob = blob->next) {
ret = wpa_config_write_blob(f, blob);
Add device identity block to store dik, pmk, pmikd, cipher version. This persistent data is used during pairing verification of previously paired peers. Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com> --- wpa_supplicant/config.c | 132 +++++++++++++++++++++++++++++++++++++++++++ wpa_supplicant/config.h | 62 ++++++++++++++++++++ wpa_supplicant/config_file.c | 96 +++++++++++++++++++++++++++++++ 3 files changed, 290 insertions(+)