$search
00001 /* 00002 * Wi-Fi Protected Setup - attribute building 00003 * Copyright (c) 2008, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "common.h" 00018 #include "crypto/aes_wrap.h" 00019 #include "crypto/crypto.h" 00020 #include "crypto/dh_group5.h" 00021 #include "crypto/sha256.h" 00022 #include "wps_i.h" 00023 00024 00025 int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg) 00026 { 00027 struct wpabuf *pubkey; 00028 00029 wpa_printf(MSG_DEBUG, "WPS: * Public Key"); 00030 wpabuf_free(wps->dh_privkey); 00031 if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey) { 00032 wpa_printf(MSG_DEBUG, "WPS: Using pre-configured DH keys"); 00033 wps->dh_privkey = wpabuf_dup(wps->wps->dh_privkey); 00034 wps->dh_ctx = wps->wps->dh_ctx; 00035 wps->wps->dh_ctx = NULL; 00036 pubkey = wpabuf_dup(wps->wps->dh_pubkey); 00037 } else { 00038 wpa_printf(MSG_DEBUG, "WPS: Generate new DH keys"); 00039 wps->dh_privkey = NULL; 00040 dh5_free(wps->dh_ctx); 00041 wps->dh_ctx = dh5_init(&wps->dh_privkey, &pubkey); 00042 pubkey = wpabuf_zeropad(pubkey, 192); 00043 } 00044 if (wps->dh_ctx == NULL || wps->dh_privkey == NULL || pubkey == NULL) { 00045 wpa_printf(MSG_DEBUG, "WPS: Failed to initialize " 00046 "Diffie-Hellman handshake"); 00047 wpabuf_free(pubkey); 00048 return -1; 00049 } 00050 00051 wpabuf_put_be16(msg, ATTR_PUBLIC_KEY); 00052 wpabuf_put_be16(msg, wpabuf_len(pubkey)); 00053 wpabuf_put_buf(msg, pubkey); 00054 00055 if (wps->registrar) { 00056 wpabuf_free(wps->dh_pubkey_r); 00057 wps->dh_pubkey_r = pubkey; 00058 } else { 00059 wpabuf_free(wps->dh_pubkey_e); 00060 wps->dh_pubkey_e = pubkey; 00061 } 00062 00063 return 0; 00064 } 00065 00066 00067 int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type) 00068 { 00069 wpa_printf(MSG_DEBUG, "WPS: * Request Type"); 00070 wpabuf_put_be16(msg, ATTR_REQUEST_TYPE); 00071 wpabuf_put_be16(msg, 1); 00072 wpabuf_put_u8(msg, type); 00073 return 0; 00074 } 00075 00076 00077 int wps_build_config_methods(struct wpabuf *msg, u16 methods) 00078 { 00079 wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods); 00080 wpabuf_put_be16(msg, ATTR_CONFIG_METHODS); 00081 wpabuf_put_be16(msg, 2); 00082 wpabuf_put_be16(msg, methods); 00083 return 0; 00084 } 00085 00086 00087 int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid) 00088 { 00089 wpa_printf(MSG_DEBUG, "WPS: * UUID-E"); 00090 wpabuf_put_be16(msg, ATTR_UUID_E); 00091 wpabuf_put_be16(msg, WPS_UUID_LEN); 00092 wpabuf_put_data(msg, uuid, WPS_UUID_LEN); 00093 return 0; 00094 } 00095 00096 00097 int wps_build_dev_password_id(struct wpabuf *msg, u16 id) 00098 { 00099 wpa_printf(MSG_DEBUG, "WPS: * Device Password ID (%d)", id); 00100 wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID); 00101 wpabuf_put_be16(msg, 2); 00102 wpabuf_put_be16(msg, id); 00103 return 0; 00104 } 00105 00106 00107 int wps_build_config_error(struct wpabuf *msg, u16 err) 00108 { 00109 wpa_printf(MSG_DEBUG, "WPS: * Configuration Error (%d)", err); 00110 wpabuf_put_be16(msg, ATTR_CONFIG_ERROR); 00111 wpabuf_put_be16(msg, 2); 00112 wpabuf_put_be16(msg, err); 00113 return 0; 00114 } 00115 00116 00117 int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg) 00118 { 00119 u8 hash[SHA256_MAC_LEN]; 00120 const u8 *addr[2]; 00121 size_t len[2]; 00122 00123 if (wps->last_msg == NULL) { 00124 wpa_printf(MSG_DEBUG, "WPS: Last message not available for " 00125 "building authenticator"); 00126 return -1; 00127 } 00128 00129 /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*) 00130 * (M_curr* is M_curr without the Authenticator attribute) 00131 */ 00132 addr[0] = wpabuf_head(wps->last_msg); 00133 len[0] = wpabuf_len(wps->last_msg); 00134 addr[1] = wpabuf_head(msg); 00135 len[1] = wpabuf_len(msg); 00136 hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash); 00137 00138 wpa_printf(MSG_DEBUG, "WPS: * Authenticator"); 00139 wpabuf_put_be16(msg, ATTR_AUTHENTICATOR); 00140 wpabuf_put_be16(msg, WPS_AUTHENTICATOR_LEN); 00141 wpabuf_put_data(msg, hash, WPS_AUTHENTICATOR_LEN); 00142 00143 return 0; 00144 } 00145 00146 00147 int wps_build_version(struct wpabuf *msg) 00148 { 00149 wpa_printf(MSG_DEBUG, "WPS: * Version"); 00150 wpabuf_put_be16(msg, ATTR_VERSION); 00151 wpabuf_put_be16(msg, 1); 00152 wpabuf_put_u8(msg, WPS_VERSION); 00153 return 0; 00154 } 00155 00156 00157 int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type) 00158 { 00159 wpa_printf(MSG_DEBUG, "WPS: * Message Type (%d)", msg_type); 00160 wpabuf_put_be16(msg, ATTR_MSG_TYPE); 00161 wpabuf_put_be16(msg, 1); 00162 wpabuf_put_u8(msg, msg_type); 00163 return 0; 00164 } 00165 00166 00167 int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg) 00168 { 00169 wpa_printf(MSG_DEBUG, "WPS: * Enrollee Nonce"); 00170 wpabuf_put_be16(msg, ATTR_ENROLLEE_NONCE); 00171 wpabuf_put_be16(msg, WPS_NONCE_LEN); 00172 wpabuf_put_data(msg, wps->nonce_e, WPS_NONCE_LEN); 00173 return 0; 00174 } 00175 00176 00177 int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg) 00178 { 00179 wpa_printf(MSG_DEBUG, "WPS: * Registrar Nonce"); 00180 wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE); 00181 wpabuf_put_be16(msg, WPS_NONCE_LEN); 00182 wpabuf_put_data(msg, wps->nonce_r, WPS_NONCE_LEN); 00183 return 0; 00184 } 00185 00186 00187 int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg) 00188 { 00189 wpa_printf(MSG_DEBUG, "WPS: * Authentication Type Flags"); 00190 wpabuf_put_be16(msg, ATTR_AUTH_TYPE_FLAGS); 00191 wpabuf_put_be16(msg, 2); 00192 wpabuf_put_be16(msg, WPS_AUTH_TYPES); 00193 return 0; 00194 } 00195 00196 00197 int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg) 00198 { 00199 wpa_printf(MSG_DEBUG, "WPS: * Encryption Type Flags"); 00200 wpabuf_put_be16(msg, ATTR_ENCR_TYPE_FLAGS); 00201 wpabuf_put_be16(msg, 2); 00202 wpabuf_put_be16(msg, WPS_ENCR_TYPES); 00203 return 0; 00204 } 00205 00206 00207 int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg) 00208 { 00209 wpa_printf(MSG_DEBUG, "WPS: * Connection Type Flags"); 00210 wpabuf_put_be16(msg, ATTR_CONN_TYPE_FLAGS); 00211 wpabuf_put_be16(msg, 1); 00212 wpabuf_put_u8(msg, WPS_CONN_ESS); 00213 return 0; 00214 } 00215 00216 00217 int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg) 00218 { 00219 wpa_printf(MSG_DEBUG, "WPS: * Association State"); 00220 wpabuf_put_be16(msg, ATTR_ASSOC_STATE); 00221 wpabuf_put_be16(msg, 2); 00222 wpabuf_put_be16(msg, WPS_ASSOC_NOT_ASSOC); 00223 return 0; 00224 } 00225 00226 00227 int wps_build_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg) 00228 { 00229 u8 hash[SHA256_MAC_LEN]; 00230 00231 wpa_printf(MSG_DEBUG, "WPS: * Key Wrap Authenticator"); 00232 hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, wpabuf_head(msg), 00233 wpabuf_len(msg), hash); 00234 00235 wpabuf_put_be16(msg, ATTR_KEY_WRAP_AUTH); 00236 wpabuf_put_be16(msg, WPS_KWA_LEN); 00237 wpabuf_put_data(msg, hash, WPS_KWA_LEN); 00238 return 0; 00239 } 00240 00241 00242 int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg, 00243 struct wpabuf *plain) 00244 { 00245 size_t pad_len; 00246 const size_t block_size = 16; 00247 u8 *iv, *data; 00248 00249 wpa_printf(MSG_DEBUG, "WPS: * Encrypted Settings"); 00250 00251 /* PKCS#5 v2.0 pad */ 00252 pad_len = block_size - wpabuf_len(plain) % block_size; 00253 os_memset(wpabuf_put(plain, pad_len), pad_len, pad_len); 00254 00255 wpabuf_put_be16(msg, ATTR_ENCR_SETTINGS); 00256 wpabuf_put_be16(msg, block_size + wpabuf_len(plain)); 00257 00258 iv = wpabuf_put(msg, block_size); 00259 if (os_get_random(iv, block_size) < 0) 00260 return -1; 00261 00262 data = wpabuf_put(msg, 0); 00263 wpabuf_put_buf(msg, plain); 00264 if (aes_128_cbc_encrypt(wps->keywrapkey, iv, data, wpabuf_len(plain))) 00265 return -1; 00266 00267 return 0; 00268 } 00269 00270 00271 #ifdef CONFIG_WPS_OOB 00272 int wps_build_oob_dev_password(struct wpabuf *msg, struct wps_context *wps) 00273 { 00274 size_t hash_len; 00275 const u8 *addr[1]; 00276 u8 pubkey_hash[WPS_HASH_LEN]; 00277 u8 dev_password_bin[WPS_OOB_DEVICE_PASSWORD_LEN]; 00278 00279 wpa_printf(MSG_DEBUG, "WPS: * OOB Device Password"); 00280 00281 addr[0] = wpabuf_head(wps->dh_pubkey); 00282 hash_len = wpabuf_len(wps->dh_pubkey); 00283 sha256_vector(1, addr, &hash_len, pubkey_hash); 00284 00285 if (os_get_random((u8 *) &wps->oob_dev_pw_id, sizeof(u16)) < 0) { 00286 wpa_printf(MSG_ERROR, "WPS: device password id " 00287 "generation error"); 00288 return -1; 00289 } 00290 wps->oob_dev_pw_id |= 0x0010; 00291 00292 if (os_get_random(dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN) < 0) { 00293 wpa_printf(MSG_ERROR, "WPS: OOB device password " 00294 "generation error"); 00295 return -1; 00296 } 00297 00298 wpabuf_put_be16(msg, ATTR_OOB_DEVICE_PASSWORD); 00299 wpabuf_put_be16(msg, WPS_OOB_DEVICE_PASSWORD_ATTR_LEN); 00300 wpabuf_put_data(msg, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); 00301 wpabuf_put_be16(msg, wps->oob_dev_pw_id); 00302 wpabuf_put_data(msg, dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN); 00303 00304 wpa_snprintf_hex_uppercase( 00305 wpabuf_put(wps->oob_conf.dev_password, 00306 wpabuf_size(wps->oob_conf.dev_password)), 00307 wpabuf_size(wps->oob_conf.dev_password), 00308 dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN); 00309 00310 return 0; 00311 } 00312 #endif /* CONFIG_WPS_OOB */