Add device identity block to store DIK, PMK, PMKID, and cipher version.
This persistent data is used during pairing verification of previously
paired peers. This commit defines the data structures and adds reading
and writing routines. The actual use of the information will be added in
following commits.
Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
{
struct wpa_ssid *ssid, *prev = NULL;
struct wpa_cred *cred, *cprev;
+ struct wpa_dev_ik *identity, *iprev;
int i;
ssid = config->ssid;
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);
return ret;
}
+
+
+int wpa_config_set_identity(struct wpa_dev_ik *identity, const char *var,
+ const char *value, int line)
+{
+ char *val;
+ size_t len;
+ int ret = 0;
+
+ if (os_strcmp(var, "dik_cipher") == 0) {
+ identity->dik_cipher = atoi(value);
+ return 0;
+ }
+
+ val = wpa_config_parse_string(value, &len);
+ if (!val) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid field '%s' string value '%s'.",
+ line, var, value);
+ return -1;
+ }
+
+ if (os_strcmp(var, "dik") == 0) {
+ wpabuf_free(identity->dik);
+ identity->dik = wpabuf_alloc_copy(val, len);
+ if (!identity->dik)
+ ret = -1;
+ } else if (os_strcmp(var, "pmk") == 0) {
+ wpabuf_free(identity->pmk);
+ identity->pmk = wpabuf_alloc_copy(val, len);
+ if (!identity->pmk)
+ ret = -1;
+ } else if (os_strcmp(var, "pmkid") == 0) {
+ if (len == PMKID_LEN) {
+ wpabuf_free(identity->pmkid);
+ identity->pmkid = wpabuf_alloc_copy(val, len);
+ if (!identity->pmkid)
+ ret = -1;
+ } else {
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid field '%s' string value '%s'.",
+ line, var, value);
+ ret = -1;
+ }
+ } else if (line) {
+ wpa_printf(MSG_ERROR, "Line %d: unknown identity field '%s'.",
+ line, var);
+ ret = -1;
+ }
+
+ os_free(val);
+ return ret;
+}
+
+
+void wpa_config_free_identity(struct wpa_dev_ik *identity)
+{
+ wpabuf_clear_free(identity->dik);
+ wpabuf_clear_free(identity->pmk);
+ wpabuf_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)
+ 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)
+ return -1;
+
+ if (prev)
+ prev->next = identity->next;
+ else
+ config->identity = identity->next;
+
+ wpa_config_free_identity(identity);
+ return 0;
+}
int sim_num;
};
+struct wpa_dev_ik {
+ /**
+ * next - Next device identity in the list
+ *
+ * This pointer can be used to iterate over all device identity 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 identity
+ *
+ * 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.
+ */
+ int id;
+
+ /**
+ * dik_cipher - Device identity key cipher version
+ */
+ int dik_cipher;
+
+ /**
+ * dik - Device identity key which is unique for the device
+ */
+ struct wpabuf *dik;
+
+ /**
+ * pmk - PMK associated with the previous connection with the device
+ */
+ struct wpabuf *pmk;
+
+ /**
+ * pmkid - PMKID used in the previous connection with the device
+ */
+ struct wpabuf *pmkid;
+};
+
#define CFG_CHANGED_DEVICE_NAME BIT(0)
#define CFG_CHANGED_CONFIG_METHODS BIT(1)
/* DevIK */
struct wpabuf *dik;
+
+ /**
+ * identity - P2P2 peer device identities
+ *
+ * This is the head for the list of all the paired devices.
+ */
+ struct wpa_dev_ik *identity;
};
const char *value, int line);
char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var);
+int wpa_config_set_identity(struct wpa_dev_ik *identity, const char *var,
+ const char *value, int line);
+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);
+
struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
const char *driver_param);
#ifndef CONFIG_NO_STDOUT_DEBUG
#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)
+ 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) {
+ 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)
{
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;
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");
continue;
}
#endif /* CONFIG_NO_CONFIG_BLOBS */
+ } else if (os_strcmp(pos, "identity={") == 0) {
+ identity = wpa_config_read_identity(f, &line,
+ identity_id++);
+ if (!identity) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: failed to parse identity block.",
+ line);
+ errors++;
+ continue;
+ }
+ if (!identity_head) {
+ 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);
config->ssid = head;
wpa_config_debug_dump_networks(config);
config->cred = cred_head;
+ config->identity = identity_head;
#ifndef WPA_IGNORE_CONFIG_ERRORS
if (errors) {
}
}
+static void wpa_config_write_identity(FILE *f, struct wpa_dev_ik *dev_ik)
+{
+ fprintf(f, "\tdik_cipher=%d\n", dev_ik->dik_cipher);
+
+ if (dev_ik->dik)
+ write_global_bin(f, "\tdik", dev_ik->dik);
+
+ if (dev_ik->pmk)
+ write_global_bin(f, "\tpmk", dev_ik->pmk);
+
+ if (dev_ik->pmkid)
+ write_global_bin(f, "\tpmkid", dev_ik->pmkid);
+}
+
#endif /* CONFIG_NO_CONFIG_WRITE */
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 */
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);