diff --git a/src/utils/uuid.c b/src/utils/uuid.c index 0f224f976..98e43d02f 100644 --- a/src/utils/uuid.c +++ b/src/utils/uuid.c @@ -9,6 +9,7 @@ #include "includes.h" #include "common.h" +#include "crypto/sha256.h" #include "uuid.h" int uuid_str2bin(const char *str, u8 *bin) @@ -69,3 +70,27 @@ int is_nil_uuid(const u8 *uuid) return 0; return 1; } + + +int uuid_random(u8 *uuid) +{ + struct os_time t; + u8 hash[SHA256_MAC_LEN]; + + /* Use HMAC-SHA256 and timestamp as context to avoid exposing direct + * os_get_random() output in the UUID field. */ + os_get_time(&t); + if (os_get_random(uuid, UUID_LEN) < 0 || + hmac_sha256(uuid, UUID_LEN, (const u8 *) &t, sizeof(t), hash) < 0) + return -1; + + os_memcpy(uuid, hash, UUID_LEN); + + /* Version: 4 = random */ + uuid[6] = (4 << 4) | (uuid[6] & 0x0f); + + /* Variant specified in RFC 4122 */ + uuid[8] = 0x80 | (uuid[8] & 0x3f); + + return 0; +} diff --git a/src/utils/uuid.h b/src/utils/uuid.h index 5e860cbc5..6e20210f9 100644 --- a/src/utils/uuid.h +++ b/src/utils/uuid.h @@ -14,5 +14,6 @@ int uuid_str2bin(const char *str, u8 *bin); int uuid_bin2str(const u8 *bin, char *str, size_t max_len); int is_nil_uuid(const u8 *uuid); +int uuid_random(u8 *uuid); #endif /* UUID_H */ diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 9e54f6cad..9ef11d86d 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -4408,6 +4408,7 @@ static const struct global_parse_data global_fields[] = { { FUNC_NO_VAR(load_dynamic_eap), 0 }, #ifdef CONFIG_WPS { FUNC(uuid), CFG_CHANGED_UUID }, + { INT_RANGE(auto_uuid, 0, 1), 0 }, { STR_RANGE(device_name, 0, WPS_DEV_NAME_MAX_LEN), CFG_CHANGED_DEVICE_NAME }, { STR_RANGE(manufacturer, 0, 64), CFG_CHANGED_WPS_STRING }, diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index a7b043561..c883c18c3 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -625,6 +625,13 @@ struct wpa_config { */ u8 uuid[16]; + /** + * auto_uuid - Automatic UUID behavior + * 0 = generate static value based on the local MAC address (default) + * 1 = generate a random UUID every time wpa_supplicant starts + */ + int auto_uuid; + /** * device_name - Device Name (WPS) * User-friendly description of device; up to 32 octets encoded in diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index e8f11493e..3a44c8a0d 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -1088,6 +1088,8 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) uuid_bin2str(config->uuid, buf, sizeof(buf)); fprintf(f, "uuid=%s\n", buf); } + if (config->auto_uuid) + fprintf(f, "auto_uuid=%d\n", config->auto_uuid); if (config->device_name) fprintf(f, "device_name=%s\n", config->device_name); if (config->manufacturer) diff --git a/wpa_supplicant/config_winreg.c b/wpa_supplicant/config_winreg.c index 6bea59760..b22ed5c66 100644 --- a/wpa_supplicant/config_winreg.c +++ b/wpa_supplicant/config_winreg.c @@ -233,6 +233,7 @@ static int wpa_config_read_global(struct wpa_config *config, HKEY hk) #ifdef CONFIG_WPS if (wpa_config_read_global_uuid(config, hk)) errors++; + wpa_config_read_reg_dword(hk, TEXT("auto_uuid"), &config->auto_uuid); config->device_name = wpa_config_read_reg_string( hk, TEXT("device_name")); config->manufacturer = wpa_config_read_reg_string( @@ -579,6 +580,8 @@ static int wpa_config_write_global(struct wpa_config *config, HKEY hk) uuid_bin2str(config->uuid, buf, sizeof(buf)); wpa_config_write_reg_string(hk, "uuid", buf); } + wpa_config_write_reg_dword(hk, TEXT("auto_uuid"), config->auto_uuid, + 0); wpa_config_write_reg_string(hk, "device_name", config->device_name); wpa_config_write_reg_string(hk, "manufacturer", config->manufacturer); wpa_config_write_reg_string(hk, "model_name", config->model_name); diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index 6dac20e20..c07badbde 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -218,9 +218,15 @@ fast_reauth=1 # Wi-Fi Protected Setup (WPS) parameters # Universally Unique IDentifier (UUID; see RFC 4122) of the device -# If not configured, UUID will be generated based on the local MAC address. +# If not configured, UUID will be generated based on the mechanism selected with +# the auto_uuid parameter. #uuid=12345678-9abc-def0-1234-56789abcdef0 +# Automatic UUID behavior +# 0 = generate static value based on the local MAC address (default) +# 1 = generate a random UUID every time wpa_supplicant starts +#auto_uuid=0 + # Device Name # User-friendly description of device; up to 32 octets encoded in UTF-8 #device_name=Wireless Client diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index 2117b009f..3b12c8f3c 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -1481,6 +1481,9 @@ static void wpas_wps_set_uuid(struct wpa_supplicant *wpa_s, wpa_s->global->ifaces->wps->uuid, WPS_UUID_LEN); src = "from the first interface"; + } else if (wpa_s->conf->auto_uuid == 1) { + uuid_random(wps->uuid); + src = "based on random data"; } else { uuid_gen_mac_addr(wpa_s->own_addr, wps->uuid); src = "based on MAC address";