Home | History | Annotate | Download | only in wps
      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