WPS: Added support for wildcard PINs that work with any UUID-E
authorJouni Malinen <j@w1.fi>
Sun, 30 Nov 2008 18:32:03 +0000 (20:32 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 30 Nov 2008 18:32:03 +0000 (20:32 +0200)
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.

hostapd/README-WPS
hostapd/wps_hostapd.c
src/wps/wps_registrar.c

index 5e8a68d..2786c60 100644 (file)
@@ -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
index 76258ee..4871d9c 100644 (file)
@@ -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));
 }
 
index 4b45c7d..01fa767 100644 (file)
@@ -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;
                }