2 * Wi-Fi Protected Setup - common functionality
3 * Copyright (c) 2008-2009, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
18 #include "crypto/aes_wrap.h"
19 #include "crypto/crypto.h"
20 #include "crypto/dh_group5.h"
21 #include "crypto/sha1.h"
22 #include "crypto/sha256.h"
24 #include "wps_dev_attr.h"
27 void wps_kdf(const u8
*key
, const u8
*label_prefix
, size_t label_prefix_len
,
28 const char *label
, u8
*res
, size_t res_len
)
30 u8 i_buf
[4], key_bits
[4];
34 u8 hash
[SHA256_MAC_LEN
], *opos
;
37 WPA_PUT_BE32(key_bits
, res_len
* 8);
40 len
[0] = sizeof(i_buf
);
41 addr
[1] = label_prefix
;
42 len
[1] = label_prefix_len
;
43 addr
[2] = (const u8
*) label
;
44 len
[2] = os_strlen(label
);
46 len
[3] = sizeof(key_bits
);
48 iter
= (res_len
+ SHA256_MAC_LEN
- 1) / SHA256_MAC_LEN
;
52 for (i
= 1; i
<= iter
; i
++) {
53 WPA_PUT_BE32(i_buf
, i
);
54 hmac_sha256_vector(key
, SHA256_MAC_LEN
, 4, addr
, len
, hash
);
56 os_memcpy(opos
, hash
, SHA256_MAC_LEN
);
57 opos
+= SHA256_MAC_LEN
;
58 left
-= SHA256_MAC_LEN
;
60 os_memcpy(opos
, hash
, left
);
65 int wps_derive_keys(struct wps_data
*wps
)
67 struct wpabuf
*pubkey
, *dh_shared
;
68 u8 dhkey
[SHA256_MAC_LEN
], kdk
[SHA256_MAC_LEN
];
71 u8 keys
[WPS_AUTHKEY_LEN
+ WPS_KEYWRAPKEY_LEN
+ WPS_EMSK_LEN
];
73 if (wps
->dh_privkey
== NULL
) {
74 wpa_printf(MSG_DEBUG
, "WPS: Own DH private key not available");
78 pubkey
= wps
->registrar
? wps
->dh_pubkey_e
: wps
->dh_pubkey_r
;
80 wpa_printf(MSG_DEBUG
, "WPS: Peer DH public key not available");
84 dh_shared
= dh5_derive_shared(wps
->dh_ctx
, pubkey
, wps
->dh_privkey
);
85 dh5_free(wps
->dh_ctx
);
87 dh_shared
= wpabuf_zeropad(dh_shared
, 192);
88 if (dh_shared
== NULL
) {
89 wpa_printf(MSG_DEBUG
, "WPS: Failed to derive DH shared key");
93 /* Own DH private key is not needed anymore */
94 wpabuf_free(wps
->dh_privkey
);
95 wps
->dh_privkey
= NULL
;
97 wpa_hexdump_buf_key(MSG_DEBUG
, "WPS: DH shared key", dh_shared
);
99 /* DHKey = SHA-256(g^AB mod p) */
100 addr
[0] = wpabuf_head(dh_shared
);
101 len
[0] = wpabuf_len(dh_shared
);
102 sha256_vector(1, addr
, len
, dhkey
);
103 wpa_hexdump_key(MSG_DEBUG
, "WPS: DHKey", dhkey
, sizeof(dhkey
));
104 wpabuf_free(dh_shared
);
106 /* KDK = HMAC-SHA-256_DHKey(N1 || EnrolleeMAC || N2) */
107 addr
[0] = wps
->nonce_e
;
108 len
[0] = WPS_NONCE_LEN
;
109 addr
[1] = wps
->mac_addr_e
;
111 addr
[2] = wps
->nonce_r
;
112 len
[2] = WPS_NONCE_LEN
;
113 hmac_sha256_vector(dhkey
, sizeof(dhkey
), 3, addr
, len
, kdk
);
114 wpa_hexdump_key(MSG_DEBUG
, "WPS: KDK", kdk
, sizeof(kdk
));
116 wps_kdf(kdk
, NULL
, 0, "Wi-Fi Easy and Secure Key Derivation",
118 os_memcpy(wps
->authkey
, keys
, WPS_AUTHKEY_LEN
);
119 os_memcpy(wps
->keywrapkey
, keys
+ WPS_AUTHKEY_LEN
, WPS_KEYWRAPKEY_LEN
);
120 os_memcpy(wps
->emsk
, keys
+ WPS_AUTHKEY_LEN
+ WPS_KEYWRAPKEY_LEN
,
123 wpa_hexdump_key(MSG_DEBUG
, "WPS: AuthKey",
124 wps
->authkey
, WPS_AUTHKEY_LEN
);
125 wpa_hexdump_key(MSG_DEBUG
, "WPS: KeyWrapKey",
126 wps
->keywrapkey
, WPS_KEYWRAPKEY_LEN
);
127 wpa_hexdump_key(MSG_DEBUG
, "WPS: EMSK", wps
->emsk
, WPS_EMSK_LEN
);
133 void wps_derive_psk(struct wps_data
*wps
, const u8
*dev_passwd
,
134 size_t dev_passwd_len
)
136 u8 hash
[SHA256_MAC_LEN
];
138 hmac_sha256(wps
->authkey
, WPS_AUTHKEY_LEN
, dev_passwd
,
139 (dev_passwd_len
+ 1) / 2, hash
);
140 os_memcpy(wps
->psk1
, hash
, WPS_PSK_LEN
);
141 hmac_sha256(wps
->authkey
, WPS_AUTHKEY_LEN
,
142 dev_passwd
+ (dev_passwd_len
+ 1) / 2,
143 dev_passwd_len
/ 2, hash
);
144 os_memcpy(wps
->psk2
, hash
, WPS_PSK_LEN
);
146 wpa_hexdump_ascii_key(MSG_DEBUG
, "WPS: Device Password",
147 dev_passwd
, dev_passwd_len
);
148 wpa_hexdump_key(MSG_DEBUG
, "WPS: PSK1", wps
->psk1
, WPS_PSK_LEN
);
149 wpa_hexdump_key(MSG_DEBUG
, "WPS: PSK2", wps
->psk2
, WPS_PSK_LEN
);
153 struct wpabuf
* wps_decrypt_encr_settings(struct wps_data
*wps
, const u8
*encr
,
156 struct wpabuf
*decrypted
;
157 const size_t block_size
= 16;
163 if (encr
== NULL
|| encr_len
< 2 * block_size
|| encr_len
% block_size
)
165 wpa_printf(MSG_DEBUG
, "WPS: No Encrypted Settings received");
169 decrypted
= wpabuf_alloc(encr_len
- block_size
);
170 if (decrypted
== NULL
)
173 wpa_hexdump(MSG_MSGDUMP
, "WPS: Encrypted Settings", encr
, encr_len
);
174 wpabuf_put_data(decrypted
, encr
+ block_size
, encr_len
- block_size
);
175 if (aes_128_cbc_decrypt(wps
->keywrapkey
, encr
, wpabuf_mhead(decrypted
),
176 wpabuf_len(decrypted
))) {
177 wpabuf_free(decrypted
);
181 wpa_hexdump_buf_key(MSG_MSGDUMP
, "WPS: Decrypted Encrypted Settings",
184 pos
= wpabuf_head_u8(decrypted
) + wpabuf_len(decrypted
) - 1;
186 if (pad
> wpabuf_len(decrypted
)) {
187 wpa_printf(MSG_DEBUG
, "WPS: Invalid PKCS#5 v2.0 pad value");
188 wpabuf_free(decrypted
);
191 for (i
= 0; i
< pad
; i
++) {
193 wpa_printf(MSG_DEBUG
, "WPS: Invalid PKCS#5 v2.0 pad "
195 wpabuf_free(decrypted
);
199 decrypted
->used
-= pad
;
206 * wps_pin_checksum - Compute PIN checksum
207 * @pin: Seven digit PIN (i.e., eight digit PIN without the checksum digit)
208 * Returns: Checksum digit
210 unsigned int wps_pin_checksum(unsigned int pin
)
212 unsigned int accum
= 0;
214 accum
+= 3 * (pin
% 10);
220 return (10 - accum
% 10) % 10;
225 * wps_pin_valid - Check whether a PIN has a valid checksum
226 * @pin: Eight digit PIN (i.e., including the checksum digit)
227 * Returns: 1 if checksum digit is valid, or 0 if not
229 unsigned int wps_pin_valid(unsigned int pin
)
231 return wps_pin_checksum(pin
/ 10) == (pin
% 10);
236 * wps_generate_pin - Generate a random PIN
237 * Returns: Eight digit PIN (i.e., including the checksum digit)
239 unsigned int wps_generate_pin(void)
243 /* Generate seven random digits for the PIN */
244 if (os_get_random((unsigned char *) &val
, sizeof(val
)) < 0) {
247 val
= os_random() ^ now
.sec
^ now
.usec
;
251 /* Append checksum digit */
252 return val
* 10 + wps_pin_checksum(val
);
256 void wps_fail_event(struct wps_context
*wps
, enum wps_msg_type msg
)
258 union wps_event_data data
;
260 if (wps
->event_cb
== NULL
)
263 os_memset(&data
, 0, sizeof(data
));
265 wps
->event_cb(wps
->cb_ctx
, WPS_EV_FAIL
, &data
);
269 void wps_success_event(struct wps_context
*wps
)
271 if (wps
->event_cb
== NULL
)
274 wps
->event_cb(wps
->cb_ctx
, WPS_EV_SUCCESS
, NULL
);
278 void wps_pwd_auth_fail_event(struct wps_context
*wps
, int enrollee
, int part
)
280 union wps_event_data data
;
282 if (wps
->event_cb
== NULL
)
285 os_memset(&data
, 0, sizeof(data
));
286 data
.pwd_auth_fail
.enrollee
= enrollee
;
287 data
.pwd_auth_fail
.part
= part
;
288 wps
->event_cb(wps
->cb_ctx
, WPS_EV_PWD_AUTH_FAIL
, &data
);
292 void wps_pbc_overlap_event(struct wps_context
*wps
)
294 if (wps
->event_cb
== NULL
)
297 wps
->event_cb(wps
->cb_ctx
, WPS_EV_PBC_OVERLAP
, NULL
);
301 void wps_pbc_timeout_event(struct wps_context
*wps
)
303 if (wps
->event_cb
== NULL
)
306 wps
->event_cb(wps
->cb_ctx
, WPS_EV_PBC_TIMEOUT
, NULL
);
310 #ifdef CONFIG_WPS_OOB
312 static struct wpabuf
* wps_get_oob_cred(struct wps_context
*wps
)
314 struct wps_data data
;
315 struct wpabuf
*plain
;
317 plain
= wpabuf_alloc(500);
319 wpa_printf(MSG_ERROR
, "WPS: Failed to allocate memory for OOB "
324 os_memset(&data
, 0, sizeof(data
));
326 data
.auth_type
= wps
->auth_types
;
327 data
.encr_type
= wps
->encr_types
;
328 if (wps_build_version(plain
) || wps_build_cred(&data
, plain
)) {
337 static struct wpabuf
* wps_get_oob_dev_pwd(struct wps_context
*wps
)
341 data
= wpabuf_alloc(9 + WPS_OOB_DEVICE_PASSWORD_ATTR_LEN
);
343 wpa_printf(MSG_ERROR
, "WPS: Failed to allocate memory for OOB "
344 "device password attribute");
348 wpabuf_free(wps
->oob_conf
.dev_password
);
349 wps
->oob_conf
.dev_password
=
350 wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN
* 2 + 1);
351 if (wps
->oob_conf
.dev_password
== NULL
) {
352 wpa_printf(MSG_ERROR
, "WPS: Failed to allocate memory for OOB "
358 if (wps_build_version(data
) ||
359 wps_build_oob_dev_password(data
, wps
)) {
360 wpa_printf(MSG_ERROR
, "WPS: Build OOB device password "
370 static int wps_parse_oob_dev_pwd(struct wps_context
*wps
,
373 struct oob_conf_data
*oob_conf
= &wps
->oob_conf
;
374 struct wps_parse_attr attr
;
377 if (wps_parse_msg(data
, &attr
) < 0 ||
378 attr
.oob_dev_password
== NULL
) {
379 wpa_printf(MSG_ERROR
, "WPS: OOB device password not found");
383 pos
= attr
.oob_dev_password
;
385 oob_conf
->pubkey_hash
=
386 wpabuf_alloc_copy(pos
, WPS_OOB_PUBKEY_HASH_LEN
);
387 if (oob_conf
->pubkey_hash
== NULL
) {
388 wpa_printf(MSG_ERROR
, "WPS: Failed to allocate memory for OOB "
392 pos
+= WPS_OOB_PUBKEY_HASH_LEN
;
394 wps
->oob_dev_pw_id
= WPA_GET_BE16(pos
);
395 pos
+= sizeof(wps
->oob_dev_pw_id
);
397 oob_conf
->dev_password
=
398 wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN
* 2 + 1);
399 if (oob_conf
->dev_password
== NULL
) {
400 wpa_printf(MSG_ERROR
, "WPS: Failed to allocate memory for OOB "
404 wpa_snprintf_hex_uppercase(wpabuf_put(oob_conf
->dev_password
,
405 wpabuf_size(oob_conf
->dev_password
)),
406 wpabuf_size(oob_conf
->dev_password
), pos
,
407 WPS_OOB_DEVICE_PASSWORD_LEN
);
413 static int wps_parse_oob_cred(struct wps_context
*wps
, struct wpabuf
*data
)
416 struct wps_parse_attr attr
;
419 if (wps_parse_msg(data
, &attr
) < 0 || attr
.num_cred
<= 0) {
420 wpa_printf(MSG_ERROR
, "WPS: OOB credential not found");
424 for (i
= 0; i
< attr
.num_cred
; i
++) {
425 struct wps_credential local_cred
;
426 struct wps_parse_attr cattr
;
428 os_memset(&local_cred
, 0, sizeof(local_cred
));
429 wpabuf_set(&msg
, attr
.cred
[i
], attr
.cred_len
[i
]);
430 if (wps_parse_msg(&msg
, &cattr
) < 0 ||
431 wps_process_cred(&cattr
, &local_cred
)) {
432 wpa_printf(MSG_ERROR
, "WPS: Failed to parse OOB "
436 wps
->cred_cb(wps
->cb_ctx
, &local_cred
);
443 int wps_process_oob(struct wps_context
*wps
, struct oob_device_data
*oob_dev
,
447 int ret
, write_f
, oob_method
= wps
->oob_conf
.oob_method
;
450 write_f
= oob_method
== OOB_METHOD_DEV_PWD_E
? !registrar
: registrar
;
452 oob_priv
= oob_dev
->init_func(wps
, oob_dev
, registrar
);
453 if (oob_priv
== NULL
) {
454 wpa_printf(MSG_ERROR
, "WPS: Failed to initialize OOB device");
459 if (oob_method
== OOB_METHOD_CRED
)
460 data
= wps_get_oob_cred(wps
);
462 data
= wps_get_oob_dev_pwd(wps
);
465 if (data
== NULL
|| oob_dev
->write_func(oob_priv
, data
) < 0)
468 data
= oob_dev
->read_func(oob_priv
);
472 if (oob_method
== OOB_METHOD_CRED
)
473 ret
= wps_parse_oob_cred(wps
, data
);
475 ret
= wps_parse_oob_dev_pwd(wps
, data
);
479 oob_dev
->deinit_func(oob_priv
);
482 wpa_printf(MSG_ERROR
, "WPS: Failed to process OOB data");
490 struct oob_device_data
* wps_get_oob_device(char *device_type
)
492 #ifdef CONFIG_WPS_UFD
493 if (os_strstr(device_type
, "ufd") != NULL
)
494 return &oob_ufd_device_data
;
495 #endif /* CONFIG_WPS_UFD */
496 #ifdef CONFIG_WPS_NFC
497 if (os_strstr(device_type
, "nfc") != NULL
)
498 return &oob_nfc_device_data
;
499 #endif /* CONFIG_WPS_NFC */
505 #ifdef CONFIG_WPS_NFC
506 struct oob_nfc_device_data
* wps_get_oob_nfc_device(char *device_name
)
508 if (device_name
== NULL
)
510 #ifdef CONFIG_WPS_NFC_PN531
511 if (os_strstr(device_name
, "pn531") != NULL
)
512 return &oob_nfc_pn531_device_data
;
513 #endif /* CONFIG_WPS_NFC_PN531 */
517 #endif /* CONFIG_WPS_NFC */
520 int wps_get_oob_method(char *method
)
522 if (os_strstr(method
, "pin-e") != NULL
)
523 return OOB_METHOD_DEV_PWD_E
;
524 if (os_strstr(method
, "pin-r") != NULL
)
525 return OOB_METHOD_DEV_PWD_R
;
526 if (os_strstr(method
, "cred") != NULL
)
527 return OOB_METHOD_CRED
;
528 return OOB_METHOD_UNKNOWN
;
531 #endif /* CONFIG_WPS_OOB */
534 int wps_dev_type_str2bin(const char *str
, u8 dev_type
[WPS_DEV_TYPE_LEN
])
538 /* <categ>-<OUI>-<subcateg> */
539 WPA_PUT_BE16(dev_type
, atoi(str
));
540 pos
= os_strchr(str
, '-');
544 if (hexstr2bin(pos
, &dev_type
[2], 4))
546 pos
= os_strchr(pos
, '-');
550 WPA_PUT_BE16(&dev_type
[6], atoi(pos
));
557 char * wps_dev_type_bin2str(const u8 dev_type
[WPS_DEV_TYPE_LEN
], char *buf
,
562 ret
= os_snprintf(buf
, buf_len
, "%u-%08X-%u",
563 WPA_GET_BE16(dev_type
), WPA_GET_BE32(&dev_type
[2]),
564 WPA_GET_BE16(&dev_type
[6]));
565 if (ret
< 0 || (unsigned int) ret
>= buf_len
)
572 void uuid_gen_mac_addr(const u8
*mac_addr
, u8
*uuid
)
576 u8 hash
[SHA1_MAC_LEN
];
578 0x52, 0x64, 0x80, 0xf8,
582 0x58, 0xed, 0x5f, 0x5d, 0x60, 0x84
586 len
[0] = sizeof(nsid
);
589 sha1_vector(2, addr
, len
, hash
);
590 os_memcpy(uuid
, hash
, 16);
592 /* Version: 5 = named-based version using SHA-1 */
593 uuid
[6] = (5 << 4) | (uuid
[6] & 0x0f);
595 /* Variant specified in RFC 4122 */
596 uuid
[8] = 0x80 | (uuid
[8] & 0x3f);
600 u16
wps_config_methods_str2bin(const char *str
)
605 /* Default to enabling methods based on build configuration */
606 methods
|= WPS_CONFIG_DISPLAY
| WPS_CONFIG_KEYPAD
;
607 #ifdef CONFIG_WPS_UFD
608 methods
|= WPS_CONFIG_USBA
;
609 #endif /* CONFIG_WPS_UFD */
610 #ifdef CONFIG_WPS_NFC
611 methods
|= WPS_CONFIG_NFC_INTERFACE
;
612 #endif /* CONFIG_WPS_NFC */
614 if (os_strstr(str
, "usba"))
615 methods
|= WPS_CONFIG_USBA
;
616 if (os_strstr(str
, "ethernet"))
617 methods
|= WPS_CONFIG_ETHERNET
;
618 if (os_strstr(str
, "label"))
619 methods
|= WPS_CONFIG_LABEL
;
620 if (os_strstr(str
, "display"))
621 methods
|= WPS_CONFIG_DISPLAY
;
622 if (os_strstr(str
, "ext_nfc_token"))
623 methods
|= WPS_CONFIG_EXT_NFC_TOKEN
;
624 if (os_strstr(str
, "int_nfc_token"))
625 methods
|= WPS_CONFIG_INT_NFC_TOKEN
;
626 if (os_strstr(str
, "nfc_interface"))
627 methods
|= WPS_CONFIG_NFC_INTERFACE
;
628 if (os_strstr(str
, "push_button"))
629 methods
|= WPS_CONFIG_PUSHBUTTON
;
630 if (os_strstr(str
, "keypad"))
631 methods
|= WPS_CONFIG_KEYPAD
;