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