Parcourir la source

WPS: Added support for wildcard PINs that work with any UUID-E

Since the Registrar may not yet know the UUID-E when a new PIN is
entered, use of a wildcard PIN that works with any UUID-E can be useful.
Such a PIN will be bound to the first Enrollee trying to use it and it
will be invalidated after the first use.
Jouni Malinen il y a 16 ans
Parent
commit
08bec36178
3 fichiers modifiés avec 57 ajouts et 19 suppressions
  1. 6 0
      hostapd/README-WPS
  2. 8 2
      hostapd/wps_hostapd.c
  3. 43 17
      src/wps/wps_registrar.c

+ 6 - 0
hostapd/README-WPS

@@ -154,6 +154,12 @@ Example command to add a PIN (12345670) for an Enrollee:
 
 hostapd_cli wps_pin 53b63a98-d29e-4457-a2ed-094d7e6a669c 12345670
 
+If the UUID-E is not available (e.g., Enrollee waits for the Registrar
+to be selected before connecting), wildcard UUID may be used to allow the PIN to be used once with any UUID:
+
+hostapd_cli wps_pin any 12345670
+
+
 After this, the Enrollee can connect to the AP again and complete WPS
 negotiation. At that point, a new, random WPA PSK is generated for the
 client device and the client can then use that key to connect to the

+ 8 - 2
hostapd/wps_hostapd.c

@@ -543,9 +543,15 @@ int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid,
 			const char *pin)
 {
 	u8 u[UUID_LEN];
-	if (hapd->wps == NULL || uuid_str2bin(uuid, u))
+	int any = 0;
+
+	if (hapd->wps == NULL)
+		return -1;
+	if (os_strcmp(uuid, "any") == 0)
+		any = 1;
+	else if (uuid_str2bin(uuid, u))
 		return -1;
-	return wps_registrar_add_pin(hapd->wps->registrar, u,
+	return wps_registrar_add_pin(hapd->wps->registrar, any ? NULL : u,
 				     (const u8 *) pin, os_strlen(pin));
 }
 

+ 43 - 17
src/wps/wps_registrar.c

@@ -26,6 +26,7 @@
 struct wps_uuid_pin {
 	struct wps_uuid_pin *next;
 	u8 uuid[WPS_UUID_LEN];
+	int wildcard_uuid;
 	u8 *pin;
 	size_t pin_len;
 	int locked;
@@ -339,7 +340,10 @@ int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *uuid,
 	p = os_zalloc(sizeof(*p));
 	if (p == NULL)
 		return -1;
-	os_memcpy(p->uuid, uuid, WPS_UUID_LEN);
+	if (uuid == NULL)
+		p->wildcard_uuid = 1;
+	else
+		os_memcpy(p->uuid, uuid, WPS_UUID_LEN);
 	p->pin = os_malloc(pin_len);
 	if (p->pin == NULL) {
 		os_free(p);
@@ -394,26 +398,43 @@ static const u8 * wps_registrar_get_pin(struct wps_registrar *reg,
 
 	pin = reg->pins;
 	while (pin) {
-		if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) {
-			/*
-			 * Lock the PIN to avoid attacks based on concurrent
-			 * re-use of the PIN that could otherwise avoid PIN
-			 * invalidations.
-			 */
-			if (pin->locked) {
-				wpa_printf(MSG_DEBUG, "WPS: Selected PIN "
-					   "locked - do not allow concurrent "
-					   "re-use");
-				return NULL;
+		if (!pin->wildcard_uuid &&
+		    os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0)
+			break;
+		pin = pin->next;
+	}
+
+	if (!pin) {
+		/* Check for wildcard UUIDs since none of the UUID-specific
+		 * PINs matched */
+		pin = reg->pins;
+		while (pin) {
+			if (pin->wildcard_uuid == 1) {
+				wpa_printf(MSG_DEBUG, "WPS: Found a wildcard "
+					   "PIN. Assigned it for this UUID-E");
+				pin->wildcard_uuid = 2;
+				os_memcpy(pin->uuid, uuid, WPS_UUID_LEN);
+				break;
 			}
-			*pin_len = pin->pin_len;
-			pin->locked = 1;
-			return pin->pin;
+			pin = pin->next;
 		}
-		pin = pin->next;
 	}
 
-	return NULL;
+	if (!pin)
+		return NULL;
+
+	/*
+	 * Lock the PIN to avoid attacks based on concurrent re-use of the PIN
+	 * that could otherwise avoid PIN invalidations.
+	 */
+	if (pin->locked) {
+		wpa_printf(MSG_DEBUG, "WPS: Selected PIN locked - do not "
+			   "allow concurrent re-use");
+		return NULL;
+	}
+	*pin_len = pin->pin_len;
+	pin->locked = 1;
+	return pin->pin;
 }
 
 
@@ -424,6 +445,11 @@ int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid)
 	pin = reg->pins;
 	while (pin) {
 		if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) {
+			if (pin->wildcard_uuid == 2) {
+				wpa_printf(MSG_DEBUG, "WPS: Invalidating used "
+					   "wildcard PIN");
+				return wps_registrar_invalidate_pin(reg, uuid);
+			}
 			pin->locked = 0;
 			return 0;
 		}