WPS: Added support for wildcard PINs that work with any UUID-E
[libeap.git] / src / wps / wps_registrar.c
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;
                }