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@xxxxxxxxxxx> --- wpa_supplicant/config.c | 132 +++++++++++++++++++++++++++++++++++++++++++ wpa_supplicant/config.h | 62 ++++++++++++++++++++ wpa_supplicant/config_file.c | 96 +++++++++++++++++++++++++++++++ 3 files changed, 290 insertions(+) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index d0957eb..f9d34b2 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -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; +} diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 6b8f0cb..3333125 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -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 */ diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 68aed57..f79b301 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -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); -- 2.7.4 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap