wps_attr_build.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /*
  2. * Wi-Fi Protected Setup - attribute building
  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 "crypto.h"
  18. #include "sha256.h"
  19. #include "aes_wrap.h"
  20. #include "wps_i.h"
  21. int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg)
  22. {
  23. struct wpabuf *pubkey;
  24. wpa_printf(MSG_DEBUG, "WPS: * Public Key");
  25. wpabuf_free(wps->dh_privkey);
  26. if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey) {
  27. wpa_printf(MSG_DEBUG, "WPS: Using pre-configured DH keys");
  28. wps->dh_privkey = wpabuf_dup(wps->wps->dh_privkey);
  29. pubkey = wpabuf_dup(wps->wps->dh_pubkey);
  30. } else {
  31. wpa_printf(MSG_DEBUG, "WPS: Generate new DH keys");
  32. wps->dh_privkey = NULL;
  33. pubkey = dh_init(dh_groups_get(WPS_DH_GROUP),
  34. &wps->dh_privkey);
  35. pubkey = wpabuf_zeropad(pubkey, 192);
  36. }
  37. if (wps->dh_privkey == NULL || pubkey == NULL) {
  38. wpa_printf(MSG_DEBUG, "WPS: Failed to initialize "
  39. "Diffie-Hellman handshake");
  40. wpabuf_free(pubkey);
  41. return -1;
  42. }
  43. wpabuf_put_be16(msg, ATTR_PUBLIC_KEY);
  44. wpabuf_put_be16(msg, wpabuf_len(pubkey));
  45. wpabuf_put_buf(msg, pubkey);
  46. if (wps->registrar) {
  47. wpabuf_free(wps->dh_pubkey_r);
  48. wps->dh_pubkey_r = pubkey;
  49. } else {
  50. wpabuf_free(wps->dh_pubkey_e);
  51. wps->dh_pubkey_e = pubkey;
  52. }
  53. return 0;
  54. }
  55. int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type)
  56. {
  57. wpa_printf(MSG_DEBUG, "WPS: * Request Type");
  58. wpabuf_put_be16(msg, ATTR_REQUEST_TYPE);
  59. wpabuf_put_be16(msg, 1);
  60. wpabuf_put_u8(msg, type);
  61. return 0;
  62. }
  63. int wps_build_config_methods(struct wpabuf *msg, u16 methods)
  64. {
  65. wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods);
  66. wpabuf_put_be16(msg, ATTR_CONFIG_METHODS);
  67. wpabuf_put_be16(msg, 2);
  68. wpabuf_put_be16(msg, methods);
  69. return 0;
  70. }
  71. int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid)
  72. {
  73. wpa_printf(MSG_DEBUG, "WPS: * UUID-E");
  74. wpabuf_put_be16(msg, ATTR_UUID_E);
  75. wpabuf_put_be16(msg, WPS_UUID_LEN);
  76. wpabuf_put_data(msg, uuid, WPS_UUID_LEN);
  77. return 0;
  78. }
  79. int wps_build_dev_password_id(struct wpabuf *msg, u16 id)
  80. {
  81. wpa_printf(MSG_DEBUG, "WPS: * Device Password ID (%d)", id);
  82. wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID);
  83. wpabuf_put_be16(msg, 2);
  84. wpabuf_put_be16(msg, id);
  85. return 0;
  86. }
  87. int wps_build_config_error(struct wpabuf *msg, u16 err)
  88. {
  89. wpa_printf(MSG_DEBUG, "WPS: * Configuration Error (%d)", err);
  90. wpabuf_put_be16(msg, ATTR_CONFIG_ERROR);
  91. wpabuf_put_be16(msg, 2);
  92. wpabuf_put_be16(msg, err);
  93. return 0;
  94. }
  95. int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg)
  96. {
  97. u8 hash[SHA256_MAC_LEN];
  98. const u8 *addr[2];
  99. size_t len[2];
  100. if (wps->last_msg == NULL) {
  101. wpa_printf(MSG_DEBUG, "WPS: Last message not available for "
  102. "building authenticator");
  103. return -1;
  104. }
  105. /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*)
  106. * (M_curr* is M_curr without the Authenticator attribute)
  107. */
  108. addr[0] = wpabuf_head(wps->last_msg);
  109. len[0] = wpabuf_len(wps->last_msg);
  110. addr[1] = wpabuf_head(msg);
  111. len[1] = wpabuf_len(msg);
  112. hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash);
  113. wpa_printf(MSG_DEBUG, "WPS: * Authenticator");
  114. wpabuf_put_be16(msg, ATTR_AUTHENTICATOR);
  115. wpabuf_put_be16(msg, WPS_AUTHENTICATOR_LEN);
  116. wpabuf_put_data(msg, hash, WPS_AUTHENTICATOR_LEN);
  117. return 0;
  118. }
  119. int wps_build_version(struct wpabuf *msg)
  120. {
  121. wpa_printf(MSG_DEBUG, "WPS: * Version");
  122. wpabuf_put_be16(msg, ATTR_VERSION);
  123. wpabuf_put_be16(msg, 1);
  124. wpabuf_put_u8(msg, WPS_VERSION);
  125. return 0;
  126. }
  127. int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type)
  128. {
  129. wpa_printf(MSG_DEBUG, "WPS: * Message Type (%d)", msg_type);
  130. wpabuf_put_be16(msg, ATTR_MSG_TYPE);
  131. wpabuf_put_be16(msg, 1);
  132. wpabuf_put_u8(msg, msg_type);
  133. return 0;
  134. }
  135. int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg)
  136. {
  137. wpa_printf(MSG_DEBUG, "WPS: * Enrollee Nonce");
  138. wpabuf_put_be16(msg, ATTR_ENROLLEE_NONCE);
  139. wpabuf_put_be16(msg, WPS_NONCE_LEN);
  140. wpabuf_put_data(msg, wps->nonce_e, WPS_NONCE_LEN);
  141. return 0;
  142. }
  143. int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg)
  144. {
  145. wpa_printf(MSG_DEBUG, "WPS: * Registrar Nonce");
  146. wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE);
  147. wpabuf_put_be16(msg, WPS_NONCE_LEN);
  148. wpabuf_put_data(msg, wps->nonce_r, WPS_NONCE_LEN);
  149. return 0;
  150. }
  151. int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg)
  152. {
  153. wpa_printf(MSG_DEBUG, "WPS: * Authentication Type Flags");
  154. wpabuf_put_be16(msg, ATTR_AUTH_TYPE_FLAGS);
  155. wpabuf_put_be16(msg, 2);
  156. wpabuf_put_be16(msg, WPS_AUTH_TYPES);
  157. return 0;
  158. }
  159. int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg)
  160. {
  161. wpa_printf(MSG_DEBUG, "WPS: * Encryption Type Flags");
  162. wpabuf_put_be16(msg, ATTR_ENCR_TYPE_FLAGS);
  163. wpabuf_put_be16(msg, 2);
  164. wpabuf_put_be16(msg, WPS_ENCR_TYPES);
  165. return 0;
  166. }
  167. int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg)
  168. {
  169. wpa_printf(MSG_DEBUG, "WPS: * Connection Type Flags");
  170. wpabuf_put_be16(msg, ATTR_CONN_TYPE_FLAGS);
  171. wpabuf_put_be16(msg, 1);
  172. wpabuf_put_u8(msg, WPS_CONN_ESS);
  173. return 0;
  174. }
  175. int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg)
  176. {
  177. wpa_printf(MSG_DEBUG, "WPS: * Association State");
  178. wpabuf_put_be16(msg, ATTR_ASSOC_STATE);
  179. wpabuf_put_be16(msg, 2);
  180. wpabuf_put_be16(msg, WPS_ASSOC_NOT_ASSOC);
  181. return 0;
  182. }
  183. int wps_build_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg)
  184. {
  185. u8 hash[SHA256_MAC_LEN];
  186. wpa_printf(MSG_DEBUG, "WPS: * Key Wrap Authenticator");
  187. hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, wpabuf_head(msg),
  188. wpabuf_len(msg), hash);
  189. wpabuf_put_be16(msg, ATTR_KEY_WRAP_AUTH);
  190. wpabuf_put_be16(msg, WPS_KWA_LEN);
  191. wpabuf_put_data(msg, hash, WPS_KWA_LEN);
  192. return 0;
  193. }
  194. int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg,
  195. struct wpabuf *plain)
  196. {
  197. size_t pad_len;
  198. const size_t block_size = 16;
  199. u8 *iv, *data;
  200. wpa_printf(MSG_DEBUG, "WPS: * Encrypted Settings");
  201. /* PKCS#5 v2.0 pad */
  202. pad_len = block_size - wpabuf_len(plain) % block_size;
  203. os_memset(wpabuf_put(plain, pad_len), pad_len, pad_len);
  204. wpabuf_put_be16(msg, ATTR_ENCR_SETTINGS);
  205. wpabuf_put_be16(msg, block_size + wpabuf_len(plain));
  206. iv = wpabuf_put(msg, block_size);
  207. if (os_get_random(iv, block_size) < 0)
  208. return -1;
  209. data = wpabuf_put(msg, 0);
  210. wpabuf_put_buf(msg, plain);
  211. if (aes_128_cbc_encrypt(wps->keywrapkey, iv, data, wpabuf_len(plain)))
  212. return -1;
  213. return 0;
  214. }
  215. #ifdef CONFIG_WPS_OOB
  216. int wps_build_oob_dev_password(struct wpabuf *msg, struct wps_context *wps)
  217. {
  218. size_t hash_len;
  219. const u8 *addr[1];
  220. u8 pubkey_hash[WPS_HASH_LEN];
  221. u8 dev_password_bin[WPS_OOB_DEVICE_PASSWORD_LEN];
  222. wpa_printf(MSG_DEBUG, "WPS: * OOB Device Password");
  223. addr[0] = wpabuf_head(wps->dh_pubkey);
  224. hash_len = wpabuf_len(wps->dh_pubkey);
  225. sha256_vector(1, addr, &hash_len, pubkey_hash);
  226. if (os_get_random((u8 *) &wps->oob_dev_pw_id, sizeof(u16)) < 0) {
  227. wpa_printf(MSG_ERROR, "WPS: device password id "
  228. "generation error");
  229. return -1;
  230. }
  231. wps->oob_dev_pw_id |= 0x0010;
  232. if (os_get_random(dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN) < 0) {
  233. wpa_printf(MSG_ERROR, "WPS: OOB device password "
  234. "generation error");
  235. return -1;
  236. }
  237. wpabuf_put_be16(msg, ATTR_OOB_DEVICE_PASSWORD);
  238. wpabuf_put_be16(msg, WPS_OOB_DEVICE_PASSWORD_ATTR_LEN);
  239. wpabuf_put_data(msg, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
  240. wpabuf_put_be16(msg, wps->oob_dev_pw_id);
  241. wpabuf_put_data(msg, dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN);
  242. wpa_snprintf_hex_uppercase(
  243. wpabuf_put(wps->oob_conf.dev_password,
  244. wpabuf_size(wps->oob_conf.dev_password)),
  245. wpabuf_size(wps->oob_conf.dev_password),
  246. dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN);
  247. return 0;
  248. }
  249. #endif /* CONFIG_WPS_OOB */