2 * Wi-Fi Protected Setup - attribute building
3 * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
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.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
18 #include "crypto/aes_wrap.h"
19 #include "crypto/crypto.h"
20 #include "crypto/dh_group5.h"
21 #include "crypto/sha256.h"
25 int wps_build_public_key(struct wps_data
*wps
, struct wpabuf
*msg
)
27 struct wpabuf
*pubkey
;
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
);
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);
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");
51 wpabuf_put_be16(msg
, ATTR_PUBLIC_KEY
);
52 wpabuf_put_be16(msg
, wpabuf_len(pubkey
));
53 wpabuf_put_buf(msg
, pubkey
);
56 wpabuf_free(wps
->dh_pubkey_r
);
57 wps
->dh_pubkey_r
= pubkey
;
59 wpabuf_free(wps
->dh_pubkey_e
);
60 wps
->dh_pubkey_e
= pubkey
;
67 int wps_build_req_type(struct wpabuf
*msg
, enum wps_request_type type
)
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
);
77 int wps_build_config_methods(struct wpabuf
*msg
, u16 methods
)
79 wpa_printf(MSG_DEBUG
, "WPS: * Config Methods (%x)", methods
);
80 wpabuf_put_be16(msg
, ATTR_CONFIG_METHODS
);
81 wpabuf_put_be16(msg
, 2);
82 wpabuf_put_be16(msg
, methods
);
87 int wps_build_uuid_e(struct wpabuf
*msg
, const u8
*uuid
)
89 wpa_printf(MSG_DEBUG
, "WPS: * UUID-E");
90 wpabuf_put_be16(msg
, ATTR_UUID_E
);
91 wpabuf_put_be16(msg
, WPS_UUID_LEN
);
92 wpabuf_put_data(msg
, uuid
, WPS_UUID_LEN
);
97 int wps_build_dev_password_id(struct wpabuf
*msg
, u16 id
)
99 wpa_printf(MSG_DEBUG
, "WPS: * Device Password ID (%d)", id
);
100 wpabuf_put_be16(msg
, ATTR_DEV_PASSWORD_ID
);
101 wpabuf_put_be16(msg
, 2);
102 wpabuf_put_be16(msg
, id
);
107 int wps_build_config_error(struct wpabuf
*msg
, u16 err
)
109 wpa_printf(MSG_DEBUG
, "WPS: * Configuration Error (%d)", err
);
110 wpabuf_put_be16(msg
, ATTR_CONFIG_ERROR
);
111 wpabuf_put_be16(msg
, 2);
112 wpabuf_put_be16(msg
, err
);
117 int wps_build_authenticator(struct wps_data
*wps
, struct wpabuf
*msg
)
119 u8 hash
[SHA256_MAC_LEN
];
123 if (wps
->last_msg
== NULL
) {
124 wpa_printf(MSG_DEBUG
, "WPS: Last message not available for "
125 "building authenticator");
129 /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*)
130 * (M_curr* is M_curr without the Authenticator attribute)
132 addr
[0] = wpabuf_head(wps
->last_msg
);
133 len
[0] = wpabuf_len(wps
->last_msg
);
134 addr
[1] = wpabuf_head(msg
);
135 len
[1] = wpabuf_len(msg
);
136 hmac_sha256_vector(wps
->authkey
, WPS_AUTHKEY_LEN
, 2, addr
, len
, hash
);
138 wpa_printf(MSG_DEBUG
, "WPS: * Authenticator");
139 wpabuf_put_be16(msg
, ATTR_AUTHENTICATOR
);
140 wpabuf_put_be16(msg
, WPS_AUTHENTICATOR_LEN
);
141 wpabuf_put_data(msg
, hash
, WPS_AUTHENTICATOR_LEN
);
147 int wps_build_version(struct wpabuf
*msg
)
149 wpa_printf(MSG_DEBUG
, "WPS: * Version");
150 wpabuf_put_be16(msg
, ATTR_VERSION
);
151 wpabuf_put_be16(msg
, 1);
152 wpabuf_put_u8(msg
, WPS_VERSION
);
157 int wps_build_msg_type(struct wpabuf
*msg
, enum wps_msg_type msg_type
)
159 wpa_printf(MSG_DEBUG
, "WPS: * Message Type (%d)", msg_type
);
160 wpabuf_put_be16(msg
, ATTR_MSG_TYPE
);
161 wpabuf_put_be16(msg
, 1);
162 wpabuf_put_u8(msg
, msg_type
);
167 int wps_build_enrollee_nonce(struct wps_data
*wps
, struct wpabuf
*msg
)
169 wpa_printf(MSG_DEBUG
, "WPS: * Enrollee Nonce");
170 wpabuf_put_be16(msg
, ATTR_ENROLLEE_NONCE
);
171 wpabuf_put_be16(msg
, WPS_NONCE_LEN
);
172 wpabuf_put_data(msg
, wps
->nonce_e
, WPS_NONCE_LEN
);
177 int wps_build_registrar_nonce(struct wps_data
*wps
, struct wpabuf
*msg
)
179 wpa_printf(MSG_DEBUG
, "WPS: * Registrar Nonce");
180 wpabuf_put_be16(msg
, ATTR_REGISTRAR_NONCE
);
181 wpabuf_put_be16(msg
, WPS_NONCE_LEN
);
182 wpabuf_put_data(msg
, wps
->nonce_r
, WPS_NONCE_LEN
);
187 int wps_build_auth_type_flags(struct wps_data
*wps
, struct wpabuf
*msg
)
189 wpa_printf(MSG_DEBUG
, "WPS: * Authentication Type Flags");
190 wpabuf_put_be16(msg
, ATTR_AUTH_TYPE_FLAGS
);
191 wpabuf_put_be16(msg
, 2);
192 wpabuf_put_be16(msg
, WPS_AUTH_TYPES
);
197 int wps_build_encr_type_flags(struct wps_data
*wps
, struct wpabuf
*msg
)
199 wpa_printf(MSG_DEBUG
, "WPS: * Encryption Type Flags");
200 wpabuf_put_be16(msg
, ATTR_ENCR_TYPE_FLAGS
);
201 wpabuf_put_be16(msg
, 2);
202 wpabuf_put_be16(msg
, WPS_ENCR_TYPES
);
207 int wps_build_conn_type_flags(struct wps_data
*wps
, struct wpabuf
*msg
)
209 wpa_printf(MSG_DEBUG
, "WPS: * Connection Type Flags");
210 wpabuf_put_be16(msg
, ATTR_CONN_TYPE_FLAGS
);
211 wpabuf_put_be16(msg
, 1);
212 wpabuf_put_u8(msg
, WPS_CONN_ESS
);
217 int wps_build_assoc_state(struct wps_data
*wps
, struct wpabuf
*msg
)
219 wpa_printf(MSG_DEBUG
, "WPS: * Association State");
220 wpabuf_put_be16(msg
, ATTR_ASSOC_STATE
);
221 wpabuf_put_be16(msg
, 2);
222 wpabuf_put_be16(msg
, WPS_ASSOC_NOT_ASSOC
);
227 int wps_build_key_wrap_auth(struct wps_data
*wps
, struct wpabuf
*msg
)
229 u8 hash
[SHA256_MAC_LEN
];
231 wpa_printf(MSG_DEBUG
, "WPS: * Key Wrap Authenticator");
232 hmac_sha256(wps
->authkey
, WPS_AUTHKEY_LEN
, wpabuf_head(msg
),
233 wpabuf_len(msg
), hash
);
235 wpabuf_put_be16(msg
, ATTR_KEY_WRAP_AUTH
);
236 wpabuf_put_be16(msg
, WPS_KWA_LEN
);
237 wpabuf_put_data(msg
, hash
, WPS_KWA_LEN
);
242 int wps_build_encr_settings(struct wps_data
*wps
, struct wpabuf
*msg
,
243 struct wpabuf
*plain
)
246 const size_t block_size
= 16;
249 wpa_printf(MSG_DEBUG
, "WPS: * Encrypted Settings");
251 /* PKCS#5 v2.0 pad */
252 pad_len
= block_size
- wpabuf_len(plain
) % block_size
;
253 os_memset(wpabuf_put(plain
, pad_len
), pad_len
, pad_len
);
255 wpabuf_put_be16(msg
, ATTR_ENCR_SETTINGS
);
256 wpabuf_put_be16(msg
, block_size
+ wpabuf_len(plain
));
258 iv
= wpabuf_put(msg
, block_size
);
259 if (os_get_random(iv
, block_size
) < 0)
262 data
= wpabuf_put(msg
, 0);
263 wpabuf_put_buf(msg
, plain
);
264 if (aes_128_cbc_encrypt(wps
->keywrapkey
, iv
, data
, wpabuf_len(plain
)))
271 #ifdef CONFIG_WPS_OOB
272 int wps_build_oob_dev_password(struct wpabuf
*msg
, struct wps_context
*wps
)
276 u8 pubkey_hash
[WPS_HASH_LEN
];
277 u8 dev_password_bin
[WPS_OOB_DEVICE_PASSWORD_LEN
];
279 wpa_printf(MSG_DEBUG
, "WPS: * OOB Device Password");
281 addr
[0] = wpabuf_head(wps
->dh_pubkey
);
282 hash_len
= wpabuf_len(wps
->dh_pubkey
);
283 sha256_vector(1, addr
, &hash_len
, pubkey_hash
);
285 if (os_get_random((u8
*) &wps
->oob_dev_pw_id
, sizeof(u16
)) < 0) {
286 wpa_printf(MSG_ERROR
, "WPS: device password id "
290 wps
->oob_dev_pw_id
|= 0x0010;
292 if (os_get_random(dev_password_bin
, WPS_OOB_DEVICE_PASSWORD_LEN
) < 0) {
293 wpa_printf(MSG_ERROR
, "WPS: OOB device password "
298 wpabuf_put_be16(msg
, ATTR_OOB_DEVICE_PASSWORD
);
299 wpabuf_put_be16(msg
, WPS_OOB_DEVICE_PASSWORD_ATTR_LEN
);
300 wpabuf_put_data(msg
, pubkey_hash
, WPS_OOB_PUBKEY_HASH_LEN
);
301 wpabuf_put_be16(msg
, wps
->oob_dev_pw_id
);
302 wpabuf_put_data(msg
, dev_password_bin
, WPS_OOB_DEVICE_PASSWORD_LEN
);
304 wpa_snprintf_hex_uppercase(
305 wpabuf_put(wps
->oob_conf
.dev_password
,
306 wpabuf_size(wps
->oob_conf
.dev_password
)),
307 wpabuf_size(wps
->oob_conf
.dev_password
),
308 dev_password_bin
, WPS_OOB_DEVICE_PASSWORD_LEN
);
312 #endif /* CONFIG_WPS_OOB */