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.
This commit is contained in:
Jouni Malinen 2008-11-30 20:32:03 +02:00
parent 79d7d8efe7
commit 08bec36178
3 changed files with 58 additions and 20 deletions

View 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 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 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 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 client device and the client can then use that key to connect to the

View file

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

View file

@ -26,6 +26,7 @@
struct wps_uuid_pin { struct wps_uuid_pin {
struct wps_uuid_pin *next; struct wps_uuid_pin *next;
u8 uuid[WPS_UUID_LEN]; u8 uuid[WPS_UUID_LEN];
int wildcard_uuid;
u8 *pin; u8 *pin;
size_t pin_len; size_t pin_len;
int locked; int locked;
@ -339,7 +340,10 @@ int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *uuid,
p = os_zalloc(sizeof(*p)); p = os_zalloc(sizeof(*p));
if (p == NULL) if (p == NULL)
return -1; 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); p->pin = os_malloc(pin_len);
if (p->pin == NULL) { if (p->pin == NULL) {
os_free(p); os_free(p);
@ -394,26 +398,43 @@ static const u8 * wps_registrar_get_pin(struct wps_registrar *reg,
pin = reg->pins; pin = reg->pins;
while (pin) { while (pin) {
if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) { if (!pin->wildcard_uuid &&
/* os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0)
* Lock the PIN to avoid attacks based on concurrent break;
* 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;
}
pin = pin->next; pin = pin->next;
} }
return NULL; 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 = pin->next;
}
}
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; pin = reg->pins;
while (pin) { while (pin) {
if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) { 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; pin->locked = 0;
return 0; return 0;
} }