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