wps_common.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /*
  2. * Wi-Fi Protected Setup - common functionality
  3. * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
  4. *
  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.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. * See README and COPYING for more details.
  13. */
  14. #include "includes.h"
  15. #include "common.h"
  16. #include "dh_groups.h"
  17. #include "sha256.h"
  18. #include "aes_wrap.h"
  19. #include "crypto.h"
  20. #include "wps_i.h"
  21. #include "wps_dev_attr.h"
  22. void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len,
  23. const char *label, u8 *res, size_t res_len)
  24. {
  25. u8 i_buf[4], key_bits[4];
  26. const u8 *addr[4];
  27. size_t len[4];
  28. int i, iter;
  29. u8 hash[SHA256_MAC_LEN], *opos;
  30. size_t left;
  31. WPA_PUT_BE32(key_bits, res_len * 8);
  32. addr[0] = i_buf;
  33. len[0] = sizeof(i_buf);
  34. addr[1] = label_prefix;
  35. len[1] = label_prefix_len;
  36. addr[2] = (const u8 *) label;
  37. len[2] = os_strlen(label);
  38. addr[3] = key_bits;
  39. len[3] = sizeof(key_bits);
  40. iter = (res_len + SHA256_MAC_LEN - 1) / SHA256_MAC_LEN;
  41. opos = res;
  42. left = res_len;
  43. for (i = 1; i <= iter; i++) {
  44. WPA_PUT_BE32(i_buf, i);
  45. hmac_sha256_vector(key, SHA256_MAC_LEN, 4, addr, len, hash);
  46. if (i < iter) {
  47. os_memcpy(opos, hash, SHA256_MAC_LEN);
  48. opos += SHA256_MAC_LEN;
  49. left -= SHA256_MAC_LEN;
  50. } else
  51. os_memcpy(opos, hash, left);
  52. }
  53. }
  54. int wps_derive_keys(struct wps_data *wps)
  55. {
  56. struct wpabuf *pubkey, *dh_shared;
  57. u8 dhkey[SHA256_MAC_LEN], kdk[SHA256_MAC_LEN];
  58. const u8 *addr[3];
  59. size_t len[3];
  60. u8 keys[WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN + WPS_EMSK_LEN];
  61. if (wps->dh_privkey == NULL) {
  62. wpa_printf(MSG_DEBUG, "WPS: Own DH private key not available");
  63. return -1;
  64. }
  65. pubkey = wps->registrar ? wps->dh_pubkey_e : wps->dh_pubkey_r;
  66. if (pubkey == NULL) {
  67. wpa_printf(MSG_DEBUG, "WPS: Peer DH public key not available");
  68. return -1;
  69. }
  70. dh_shared = dh_derive_shared(pubkey, wps->dh_privkey,
  71. dh_groups_get(WPS_DH_GROUP));
  72. if (dh_shared == NULL) {
  73. wpa_printf(MSG_DEBUG, "WPS: Failed to derive DH shared key");
  74. return -1;
  75. }
  76. /* Own DH private key is not needed anymore */
  77. wpabuf_free(wps->dh_privkey);
  78. wps->dh_privkey = NULL;
  79. wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH shared key", dh_shared);
  80. /* DHKey = SHA-256(g^AB mod p) */
  81. addr[0] = wpabuf_head(dh_shared);
  82. len[0] = wpabuf_len(dh_shared);
  83. sha256_vector(1, addr, len, dhkey);
  84. wpa_hexdump_key(MSG_DEBUG, "WPS: DHKey", dhkey, sizeof(dhkey));
  85. wpabuf_free(dh_shared);
  86. /* KDK = HMAC-SHA-256_DHKey(N1 || EnrolleeMAC || N2) */
  87. addr[0] = wps->nonce_e;
  88. len[0] = WPS_NONCE_LEN;
  89. addr[1] = wps->mac_addr_e;
  90. len[1] = ETH_ALEN;
  91. addr[2] = wps->nonce_r;
  92. len[2] = WPS_NONCE_LEN;
  93. hmac_sha256_vector(dhkey, sizeof(dhkey), 3, addr, len, kdk);
  94. wpa_hexdump_key(MSG_DEBUG, "WPS: KDK", kdk, sizeof(kdk));
  95. wps_kdf(kdk, NULL, 0, "Wi-Fi Easy and Secure Key Derivation",
  96. keys, sizeof(keys));
  97. os_memcpy(wps->authkey, keys, WPS_AUTHKEY_LEN);
  98. os_memcpy(wps->keywrapkey, keys + WPS_AUTHKEY_LEN, WPS_KEYWRAPKEY_LEN);
  99. os_memcpy(wps->emsk, keys + WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN,
  100. WPS_EMSK_LEN);
  101. wpa_hexdump_key(MSG_DEBUG, "WPS: AuthKey",
  102. wps->authkey, WPS_AUTHKEY_LEN);
  103. wpa_hexdump_key(MSG_DEBUG, "WPS: KeyWrapKey",
  104. wps->keywrapkey, WPS_KEYWRAPKEY_LEN);
  105. wpa_hexdump_key(MSG_DEBUG, "WPS: EMSK", wps->emsk, WPS_EMSK_LEN);
  106. return 0;
  107. }
  108. int wps_derive_mgmt_keys(struct wps_data *wps)
  109. {
  110. u8 nonces[2 * WPS_NONCE_LEN];
  111. u8 keys[WPS_MGMTAUTHKEY_LEN + WPS_MGMTENCKEY_LEN];
  112. u8 hash[SHA256_MAC_LEN];
  113. const u8 *addr[2];
  114. size_t len[2];
  115. const char *auth_label = "WFA-WLAN-Management-MgmtAuthKey";
  116. const char *enc_label = "WFA-WLAN-Management-MgmtEncKey";
  117. /* MgmtAuthKey || MgmtEncKey =
  118. * kdf(EMSK, N1 || N2 || "WFA-WLAN-Management-Keys", 384) */
  119. os_memcpy(nonces, wps->nonce_e, WPS_NONCE_LEN);
  120. os_memcpy(nonces + WPS_NONCE_LEN, wps->nonce_r, WPS_NONCE_LEN);
  121. wps_kdf(wps->emsk, nonces, sizeof(nonces), "WFA-WLAN-Management-Keys",
  122. keys, sizeof(keys));
  123. os_memcpy(wps->mgmt_auth_key, keys, WPS_MGMTAUTHKEY_LEN);
  124. os_memcpy(wps->mgmt_enc_key, keys + WPS_MGMTAUTHKEY_LEN,
  125. WPS_MGMTENCKEY_LEN);
  126. addr[0] = nonces;
  127. len[0] = sizeof(nonces);
  128. /* MgmtEncKeyID = first 128 bits of
  129. * SHA-256(N1 || N2 || "WFA-WLAN-Management-MgmtAuthKey") */
  130. addr[1] = (const u8 *) auth_label;
  131. len[1] = os_strlen(auth_label);
  132. sha256_vector(2, addr, len, hash);
  133. os_memcpy(wps->mgmt_auth_key_id, hash, WPS_MGMT_KEY_ID_LEN);
  134. /* MgmtEncKeyID = first 128 bits of
  135. * SHA-256(N1 || N2 || "WFA-WLAN-Management-MgmtEncKey") */
  136. addr[1] = (const u8 *) enc_label;
  137. len[1] = os_strlen(enc_label);
  138. sha256_vector(2, addr, len, hash);
  139. os_memcpy(wps->mgmt_enc_key_id, hash, WPS_MGMT_KEY_ID_LEN);
  140. wpa_hexdump_key(MSG_DEBUG, "WPS: MgmtAuthKey",
  141. wps->mgmt_auth_key, WPS_MGMTAUTHKEY_LEN);
  142. wpa_hexdump(MSG_DEBUG, "WPS: MgmtAuthKeyID",
  143. wps->mgmt_auth_key_id, WPS_MGMT_KEY_ID_LEN);
  144. wpa_hexdump_key(MSG_DEBUG, "WPS: MgmtEncKey",
  145. wps->mgmt_enc_key, WPS_MGMTENCKEY_LEN);
  146. wpa_hexdump(MSG_DEBUG, "WPS: MgmtEncKeyID",
  147. wps->mgmt_enc_key_id, WPS_MGMT_KEY_ID_LEN);
  148. return 0;
  149. }
  150. void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd,
  151. size_t dev_passwd_len)
  152. {
  153. u8 hash[SHA256_MAC_LEN];
  154. hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd,
  155. (dev_passwd_len + 1) / 2, hash);
  156. os_memcpy(wps->psk1, hash, WPS_PSK_LEN);
  157. hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN,
  158. dev_passwd + (dev_passwd_len + 1) / 2,
  159. dev_passwd_len / 2, hash);
  160. os_memcpy(wps->psk2, hash, WPS_PSK_LEN);
  161. wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Device Password",
  162. dev_passwd, dev_passwd_len);
  163. wpa_hexdump_key(MSG_DEBUG, "WPS: PSK1", wps->psk1, WPS_PSK_LEN);
  164. wpa_hexdump_key(MSG_DEBUG, "WPS: PSK2", wps->psk2, WPS_PSK_LEN);
  165. }
  166. struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr,
  167. size_t encr_len)
  168. {
  169. struct wpabuf *decrypted;
  170. const size_t block_size = 16;
  171. size_t i;
  172. u8 pad;
  173. const u8 *pos;
  174. /* AES-128-CBC */
  175. if (encr == NULL || encr_len < 2 * block_size || encr_len % block_size)
  176. {
  177. wpa_printf(MSG_DEBUG, "WPS: No Encrypted Settings received");
  178. return NULL;
  179. }
  180. decrypted = wpabuf_alloc(encr_len - block_size);
  181. if (decrypted == NULL)
  182. return NULL;
  183. wpa_hexdump(MSG_MSGDUMP, "WPS: Encrypted Settings", encr, encr_len);
  184. wpabuf_put_data(decrypted, encr + block_size, encr_len - block_size);
  185. if (aes_128_cbc_decrypt(wps->keywrapkey, encr, wpabuf_mhead(decrypted),
  186. wpabuf_len(decrypted))) {
  187. wpabuf_free(decrypted);
  188. return NULL;
  189. }
  190. wpa_hexdump_buf_key(MSG_MSGDUMP, "WPS: Decrypted Encrypted Settings",
  191. decrypted);
  192. pos = wpabuf_head_u8(decrypted) + wpabuf_len(decrypted) - 1;
  193. pad = *pos;
  194. if (pad > wpabuf_len(decrypted)) {
  195. wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad value");
  196. wpabuf_free(decrypted);
  197. return NULL;
  198. }
  199. for (i = 0; i < pad; i++) {
  200. if (*pos-- != pad) {
  201. wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad "
  202. "string");
  203. wpabuf_free(decrypted);
  204. return NULL;
  205. }
  206. }
  207. decrypted->used -= pad;
  208. return decrypted;
  209. }
  210. /**
  211. * wps_pin_checksum - Compute PIN checksum
  212. * @pin: Seven digit PIN (i.e., eight digit PIN without the checksum digit)
  213. * Returns: Checksum digit
  214. */
  215. unsigned int wps_pin_checksum(unsigned int pin)
  216. {
  217. unsigned int accum = 0;
  218. while (pin) {
  219. accum += 3 * (pin % 10);
  220. pin /= 10;
  221. accum += pin % 10;
  222. pin /= 10;
  223. }
  224. return (10 - accum % 10) % 10;
  225. }
  226. /**
  227. * wps_pin_valid - Check whether a PIN has a valid checksum
  228. * @pin: Eight digit PIN (i.e., including the checksum digit)
  229. * Returns: 1 if checksum digit is valid, or 0 if not
  230. */
  231. unsigned int wps_pin_valid(unsigned int pin)
  232. {
  233. return wps_pin_checksum(pin / 10) == (pin % 10);
  234. }
  235. /**
  236. * wps_generate_pin - Generate a random PIN
  237. * Returns: Eight digit PIN (i.e., including the checksum digit)
  238. */
  239. unsigned int wps_generate_pin(void)
  240. {
  241. unsigned int val;
  242. /* Generate seven random digits for the PIN */
  243. if (os_get_random((unsigned char *) &val, sizeof(val)) < 0) {
  244. struct os_time now;
  245. os_get_time(&now);
  246. val = os_random() ^ now.sec ^ now.usec;
  247. }
  248. val %= 10000000;
  249. /* Append checksum digit */
  250. return val * 10 + wps_pin_checksum(val);
  251. }
  252. void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg)
  253. {
  254. union wps_event_data data;
  255. if (wps->event_cb == NULL)
  256. return;
  257. os_memset(&data, 0, sizeof(data));
  258. data.fail.msg = msg;
  259. wps->event_cb(wps->cb_ctx, WPS_EV_FAIL, &data);
  260. }